Do spisu tresci tematu podgrupy
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; }