Do spisu tresci tematu podgrupy



6.3.3.4 Skomentowany kod procedury zwalniania bloków dyskowych ext2_free_blocks.



Algorytm zwalniania bloków dyskowych jest zaimplementowany w Linuxie w procedurze ext2_free_blocks.


/*
 *  linux/fs/ext2/balloc.c
 */
 

void ext2_free_blocks (const struct inode * inode, unsigned long block,  unsigned long count)
    inode  - wskażnik do i_węzła pliku do, którego należą zwalniane bloki
    block  - numer bloku, od którego zaczynamy zwalniać
    count - liczba bloków do zwolnienia. 

Procedura zwalnia spójny ciąg bloków dyskowych począwszy
od bloku o numerze block. Zwalniany ciąg liczy sobie count bloków.

{
struct buffer_head * bh;        /*  wskaźnik do nagłówka bufora
                                        zawierającego bitmapę */
	struct buffer_head * bh2;   /* wskaźnik  bufora zawierającego deskryptor grupy */
	unsigned long block_group;  /* numer grupy bloków */
	unsigned long bit;          /* numer bloku w grupie */
	unsigned long i;
	int bitmap_nr;              /* numer bitmapy grupy w której są bloki do zwolnienia */
	struct super_block * sb;    /* wskaźnik do  bloku identyfikacyjnego w pamięci */
	struct ext2_group_desc * gdp;/* wskaźnik do deskryptora grupy */
	struct ext2_super_block * es;/* wskaźnik do bloku identyfikacyjnego */

	sb = inode->i_sb;
	if (!sb) {
		printk ("ext2_free_blocks: nonexistent device");
		return;
	}

 /****  załóż blokadę na blok identyfikacyjny *****/ 
	lock_super (sb);
	es = sb->u.ext2_sb.s_es;

 /**** sprawdź poprawność argumentów  ****/
 /**** 1.  Czy bloki do zwolnienia leżą w strefie bloków z danymi  ****/
	if (block < es->s_first_data_block || 
	    (block + count) > es->s_blocks_count) {
		ext2_error (sb, "ext2_free_blocks",
			    "Freeing blocks not in datazone - "
			    "block = %lu, count = %lu", block, count);
		unlock_super (sb);
		return;
	}

	ext2_debug ("freeing block %lu\n", block);
            
   /****  2. Czy zwalniane bloki leżą w jednej grupie ****/
             
	block_group = (block - es->s_first_data_block) /
		      EXT2_BLOCKS_PER_GROUP(sb);
	bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
	if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
		ext2_panic (sb, "ext2_free_blocks",
			    "Freeing blocks across group boundary - "
			    "Block = %lu, count = %lu",
			    block, count);
            
   /*****  Wczytaj bitmapę grupy bloków i deskryptor tej grupy ****/
   /***** Funkcje te jeśli nie ma w pamięci wczytują  bitmapę i deskryptor z dysku ****/ 

	bitmap_nr = load_block_bitmap (sb, block_group);
	bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
	gdp = get_group_desc (sb, block_group, &bh2);

	if (test_opt (sb, CHECK_STRICT) &&
	    (in_range (gdp->bg_block_bitmap, block, count) ||
	     in_range (gdp->bg_inode_bitmap, block, count) ||
	     in_range (block, gdp->bg_inode_table,
		       sb->u.ext2_sb.s_itb_per_group) ||
	     in_range (block + count - 1, gdp->bg_inode_table,
		       sb->u.ext2_sb.s_itb_per_group)))
		ext2_panic (sb, "ext2_free_blocks",
			    "Freeing blocks in system zones - "
			    "Block = %lu, count = %lu",
			    block, count);

/****  argumenty sprawdzone       *****/
/**** zwalniamy kolejne bloki      *****/

	for (i = 0; i < count; i++) {
            /* czyszcząc bit w bitmapie */
		if (!clear_bit (bit + i, bh->b_data))          
			ext2_warning (sb, "ext2_free_blocks",
				      "bit already cleared for block %lu", 
				      block);
		else {    /* jeśli wyczyściliśmy bit w bitmapie */
			if (sb->dq_op)
			       /* to uaktualnij dane w i-węźle */
				sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_bloc->s_blocksize));
                           
                  /* zwiększ licznik wolnych bloków */
			gdp->bg_free_blocks_count++; /* w deskryptorze grupy */
			es->s_free_blocks_count++;   /* w bloku identyfikacyjnym */
		}
	}
	
  /* zaznacz, że aktualizowano struktury w pamięci */
	mark_buffer_dirty(bh2, 1);
	mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);  /* bufor zawierający */
                                                /*blok  identyfikacyjny */

	mark_buffer_dirty(bh, 1);           /* bufor zawierający bitmapę */
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}
	sb->s_dirt = 1;   /* zaznaczamy sam blok identyfikacyjny */

	unlock_super (sb); /* zdejmij blokadę z bloku identyfikacyjnego */
	return;
}



Bibliografia

  1. Plik źródłowy Linuxa:


Autor: Maciej Zarzycki