static void _reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t block, int for_unformatted) { struct super_block * s = th->t_super; struct reiserfs_super_block * rs; struct buffer_head * sbh; struct reiserfs_bitmap_info *apbi; int nr, offset; BUG_ON (!th->t_trans_id); PROC_INFO_INC( s, free_block ); rs = SB_DISK_SUPER_BLOCK (s); sbh = SB_BUFFER_WITH_SB (s); apbi = SB_AP_BITMAP(s); get_bit_address (s, block, &nr, &offset); if (nr >= sb_bmap_nr (rs)) { reiserfs_warning (s, "vs-4075: reiserfs_free_block: " "block %lu is out of range on %s", block, reiserfs_bdevname (s)); return; } reiserfs_prepare_for_journal(s, apbi[nr].bh, 1 ) ; /* clear bit for the given block in bit map */ if (!reiserfs_test_and_clear_le_bit (offset, apbi[nr].bh->b_data)) { reiserfs_warning (s, "vs-4080: reiserfs_free_block: " "free_block (%s:%lu)[dev:blocknr]: bit already cleared", reiserfs_bdevname (s), block); } apbi[nr].free_count ++; journal_mark_dirty (th, s, apbi[nr].bh); reiserfs_prepare_for_journal(s, sbh, 1) ; /* update super block */ set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 ); journal_mark_dirty (th, s, sbh); if (for_unformatted) DQUOT_FREE_BLOCK_NODIRTY(inode, 1); }
static void _reiserfs_free_block (struct reiserfs_transaction_handle *th, b_blocknr_t block) { struct super_block * s = th->t_super; struct reiserfs_super_block * rs; struct buffer_head * sbh; struct reiserfs_bitmap_info *apbi; int nr, offset; PROC_INFO_INC( s, free_block ); rs = SB_DISK_SUPER_BLOCK (s); sbh = SB_BUFFER_WITH_SB (s); apbi = SB_AP_BITMAP(s); get_bit_address (s, block, &nr, &offset); if (nr >= sb_bmap_nr (rs)) { reiserfs_warning ("vs-4075: reiserfs_free_block: " "block %lu is out of range on %s\n", block, bdevname(s->s_dev)); return; } reiserfs_prepare_for_journal(s, apbi[nr].bh, 1 ) ; /* clear bit for the given block in bit map */ if (!reiserfs_test_and_clear_le_bit (offset, apbi[nr].bh->b_data)) { reiserfs_warning ("vs-4080: reiserfs_free_block: " "free_block (%04x:%lu)[dev:blocknr]: bit already cleared\n", s->s_dev, block); } if (offset < apbi[nr].first_zero_hint) { apbi[nr].first_zero_hint = offset; } apbi[nr].free_count ++; journal_mark_dirty (th, s, apbi[nr].bh); reiserfs_prepare_for_journal(s, sbh, 1) ; /* update super block */ set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 ); journal_mark_dirty (th, s, sbh); }
/* I wonder if it would be less modest now that we use journaling. -Hans */ void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long block) { struct super_block * s = th->t_super; struct reiserfs_super_block * rs; struct buffer_head * sbh; struct buffer_head ** apbh; int nr, offset; RFALSE(!s, "vs-4060: trying to free block on nonexistent device"); RFALSE(is_reusable (s, block, 1) == 0, "vs-4070: can not free such block"); PROC_INFO_INC( s, free_block ); rs = SB_DISK_SUPER_BLOCK (s); sbh = SB_BUFFER_WITH_SB (s); apbh = SB_AP_BITMAP (s); get_bit_address (s, block, &nr, &offset); /* mark it before we clear it, just in case */ journal_mark_freed(th, s, block) ; reiserfs_prepare_for_journal(s, apbh[nr], 1 ) ; /* clear bit for the given block in bit map */ if (!reiserfs_test_and_clear_le_bit (offset, apbh[nr]->b_data)) { reiserfs_warning ("vs-4080: reiserfs_free_block: " "free_block (%04x:%lu)[dev:blocknr]: bit already cleared\n", s->s_dev, block); } journal_mark_dirty (th, s, apbh[nr]); reiserfs_prepare_for_journal(s, sbh, 1) ; /* update super block */ set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 ); journal_mark_dirty (th, s, sbh); s->s_dirt = 1; }
/* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap * block; */ static int scan_bitmap_block (struct reiserfs_transaction_handle *th, int bmap_n, int *beg, int boundary, int min, int max, int unfm) { struct super_block *s = th->t_super; struct reiserfs_bitmap_info *bi=&SB_AP_BITMAP(s)[bmap_n]; int end, next; int org = *beg; BUG_ON (!th->t_trans_id); RFALSE(bmap_n >= SB_BMAP_NR (s), "Bitmap %d is out of range (0..%d)",bmap_n, SB_BMAP_NR (s) - 1); PROC_INFO_INC( s, scan_bitmap.bmap ); /* this is unclear and lacks comments, explain how journal bitmaps work here for the reader. Convey a sense of the design here. What is a window? */ /* - I mean `a window of zero bits' as in description of this function - Zam. */ if ( !bi ) { reiserfs_warning (s, "NULL bitmap info pointer for bitmap %d", bmap_n); return 0; } if (buffer_locked (bi->bh)) { PROC_INFO_INC( s, scan_bitmap.wait ); __wait_on_buffer (bi->bh); } while (1) { cont: if (bi->free_count < min) return 0; // No free blocks in this bitmap /* search for a first zero bit -- beggining of a window */ *beg = reiserfs_find_next_zero_le_bit ((unsigned long*)(bi->bh->b_data), boundary, *beg); if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block * cannot contain a zero window of minimum size */ return 0; } if (unfm && is_block_in_journal(s,bmap_n, *beg, beg)) continue; /* first zero bit found; we check next bits */ for (end = *beg + 1;; end ++) { if (end >= *beg + max || end >= boundary || reiserfs_test_le_bit (end, bi->bh->b_data)) { next = end; break; } /* finding the other end of zero bit window requires looking into journal structures (in * case of searching for free blocks for unformatted nodes) */ if (unfm && is_block_in_journal(s, bmap_n, end, &next)) break; } /* now (*beg) points to beginning of zero bits window, * (end) points to one bit after the window end */ if (end - *beg >= min) { /* it seems we have found window of proper size */ int i; reiserfs_prepare_for_journal (s, bi->bh, 1); /* try to set all blocks used checking are they still free */ for (i = *beg; i < end; i++) { /* It seems that we should not check in journal again. */ if (reiserfs_test_and_set_le_bit (i, bi->bh->b_data)) { /* bit was set by another process * while we slept in prepare_for_journal() */ PROC_INFO_INC( s, scan_bitmap.stolen ); if (i >= *beg + min) { /* we can continue with smaller set of allocated blocks, * if length of this set is more or equal to `min' */ end = i; break; } /* otherwise we clear all bit were set ... */ while (--i >= *beg) reiserfs_test_and_clear_le_bit (i, bi->bh->b_data); reiserfs_restore_prepared_buffer (s, bi->bh); *beg = org; /* ... and search again in current block from beginning */ goto cont; } } bi->free_count -= (end - *beg); journal_mark_dirty (th, s, bi->bh); /* free block count calculation */ reiserfs_prepare_for_journal (s, SB_BUFFER_WITH_SB(s), 1); PUT_SB_FREE_BLOCKS(s, SB_FREE_BLOCKS(s) - (end - *beg)); journal_mark_dirty (th, s, SB_BUFFER_WITH_SB(s)); return end - (*beg); } else { *beg = next; } } }
int reiserfs_resize (struct super_block * s, unsigned long block_count_new) { struct reiserfs_super_block * sb; struct reiserfs_bitmap_info *bitmap; struct buffer_head * bh; struct reiserfs_transaction_handle th; unsigned int bmap_nr_new, bmap_nr; unsigned int block_r_new, block_r; struct reiserfs_list_bitmap * jb; struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS]; unsigned long int block_count, free_blocks; int i; int copy_size ; sb = SB_DISK_SUPER_BLOCK(s); if (SB_BLOCK_COUNT(s) >= block_count_new) { printk("can\'t shrink filesystem on-line\n"); return -EINVAL; } /* check the device size */ bh = sb_bread(s, block_count_new - 1); if (!bh) { printk("reiserfs_resize: can\'t read last block\n"); return -EINVAL; } bforget(bh); /* old disk layout detection; those partitions can be mounted, but * cannot be resized */ if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size != REISERFS_DISK_OFFSET_IN_BYTES ) { printk("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)\n"); return -ENOTSUPP; } /* count used bits in last bitmap block */ block_r = SB_BLOCK_COUNT(s) - (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8; /* count bitmap blocks in new fs */ bmap_nr_new = block_count_new / ( s->s_blocksize * 8 ); block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8; if (block_r_new) bmap_nr_new++; else block_r_new = s->s_blocksize * 8; /* save old values */ block_count = SB_BLOCK_COUNT(s); bmap_nr = SB_BMAP_NR(s); /* resizing of reiserfs bitmaps (journal and real), if needed */ if (bmap_nr_new > bmap_nr) { /* reallocate journal bitmaps */ if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) { printk("reiserfs_resize: unable to allocate memory for journal bitmaps\n"); unlock_super(s) ; return -ENOMEM ; } /* the new journal bitmaps are zero filled, now we copy in the bitmap ** node pointers from the old journal bitmap structs, and then ** transfer the new data structures into the journal struct. ** ** using the copy_size var below allows this code to work for ** both shrinking and expanding the FS. */ copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr ; copy_size = copy_size * sizeof(struct reiserfs_list_bitmap_node *) ; for (i = 0 ; i < JOURNAL_NUM_BITMAPS ; i++) { struct reiserfs_bitmap_node **node_tmp ; jb = SB_JOURNAL(s)->j_list_bitmap + i ; memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size) ; /* just in case vfree schedules on us, copy the new ** pointer into the journal struct before freeing the ** old one */ node_tmp = jb->bitmaps ; jb->bitmaps = jbitmap[i].bitmaps ; vfree(node_tmp) ; } /* allocate additional bitmap blocks, reallocate array of bitmap * block pointers */ bitmap = vmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); if (!bitmap) { printk("reiserfs_resize: unable to allocate memory.\n"); return -ENOMEM; } memset (bitmap, 0, sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); for (i = 0; i < bmap_nr; i++) bitmap[i] = SB_AP_BITMAP(s)[i]; for (i = bmap_nr; i < bmap_nr_new; i++) { bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8); memset(bitmap[i].bh->b_data, 0, sb_blocksize(sb)); reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data); set_buffer_uptodate(bitmap[i].bh); mark_buffer_dirty(bitmap[i].bh) ; sync_dirty_buffer(bitmap[i].bh); // update bitmap_info stuff bitmap[i].first_zero_hint=1; bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; } /* free old bitmap blocks array */ vfree(SB_AP_BITMAP(s)); SB_AP_BITMAP(s) = bitmap; } /* begin transaction */ journal_begin(&th, s, 10); /* correct last bitmap blocks in old and new disk layout */ reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1); for (i = block_r; i < s->s_blocksize * 8; i++) reiserfs_test_and_clear_le_bit(i, SB_AP_BITMAP(s)[bmap_nr - 1].bh->b_data); SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r; if ( !SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint) SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r; journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh); reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1); for (i = block_r_new; i < s->s_blocksize * 8; i++) reiserfs_test_and_set_le_bit(i, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh->b_data); journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh); SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -= s->s_blocksize * 8 - block_r_new; /* Extreme case where last bitmap is the only valid block in itself. */ if ( !SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count ) SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0; /* update super */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ; free_blocks = SB_FREE_BLOCKS(s); PUT_SB_FREE_BLOCKS(s, free_blocks + (block_count_new - block_count - (bmap_nr_new - bmap_nr))); PUT_SB_BLOCK_COUNT(s, block_count_new); PUT_SB_BMAP_NR(s, bmap_nr_new); s->s_dirt = 1; journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); SB_JOURNAL(s)->j_must_wait = 1; journal_end(&th, s, 10); return 0; }
int reiserfs_resize(struct super_block *s, unsigned long block_count_new) { int err = 0; struct reiserfs_super_block *sb; struct reiserfs_bitmap_info *bitmap; struct reiserfs_bitmap_info *info; struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s); struct buffer_head *bh; struct reiserfs_transaction_handle th; unsigned int bmap_nr_new, bmap_nr; unsigned int block_r_new, block_r; struct reiserfs_list_bitmap *jb; struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS]; unsigned long int block_count, free_blocks; int i; int copy_size; sb = SB_DISK_SUPER_BLOCK(s); if (SB_BLOCK_COUNT(s) >= block_count_new) { printk("can\'t shrink filesystem on-line\n"); return -EINVAL; } /* check the device size */ bh = sb_bread(s, block_count_new - 1); if (!bh) { printk("reiserfs_resize: can\'t read last block\n"); return -EINVAL; } bforget(bh); /* old disk layout detection; those partitions can be mounted, but * cannot be resized */ if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size != REISERFS_DISK_OFFSET_IN_BYTES) { printk ("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)\n"); return -ENOTSUPP; } /* count used bits in last bitmap block */ block_r = SB_BLOCK_COUNT(s) - (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8; /* count bitmap blocks in new fs */ bmap_nr_new = block_count_new / (s->s_blocksize * 8); block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8; if (block_r_new) bmap_nr_new++; else block_r_new = s->s_blocksize * 8; /* save old values */ block_count = SB_BLOCK_COUNT(s); bmap_nr = SB_BMAP_NR(s); /* resizing of reiserfs bitmaps (journal and real), if needed */ if (bmap_nr_new > bmap_nr) { /* reallocate journal bitmaps */ if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) { printk ("reiserfs_resize: unable to allocate memory for journal bitmaps\n"); unlock_super(s); return -ENOMEM; } /* the new journal bitmaps are zero filled, now we copy in the bitmap ** node pointers from the old journal bitmap structs, and then ** transfer the new data structures into the journal struct. ** ** using the copy_size var below allows this code to work for ** both shrinking and expanding the FS. */ copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr; copy_size = copy_size * sizeof(struct reiserfs_list_bitmap_node *); for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) { struct reiserfs_bitmap_node **node_tmp; jb = SB_JOURNAL(s)->j_list_bitmap + i; memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size); /* just in case vfree schedules on us, copy the new ** pointer into the journal struct before freeing the ** old one */ node_tmp = jb->bitmaps; jb->bitmaps = jbitmap[i].bitmaps; vfree(node_tmp); } /* allocate additional bitmap blocks, reallocate array of bitmap * block pointers */ bitmap = vmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); if (!bitmap) { /* Journal bitmaps are still supersized, but the memory isn't * leaked, so I guess it's ok */ printk("reiserfs_resize: unable to allocate memory.\n"); return -ENOMEM; } memset(bitmap, 0, sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); for (i = 0; i < bmap_nr; i++) bitmap[i] = old_bitmap[i]; /* This doesn't go through the journal, but it doesn't have to. * The changes are still atomic: We're synced up when the journal * transaction begins, and the new bitmaps don't matter if the * transaction fails. */ for (i = bmap_nr; i < bmap_nr_new; i++) { /* don't use read_bitmap_block since it will cache * the uninitialized bitmap */ bh = sb_bread(s, i * s->s_blocksize * 8); memset(bh->b_data, 0, sb_blocksize(sb)); reiserfs_test_and_set_le_bit(0, bh->b_data); reiserfs_cache_bitmap_metadata(s, bh, bitmap + i); set_buffer_uptodate(bh); mark_buffer_dirty(bh); sync_dirty_buffer(bh); // update bitmap_info stuff bitmap[i].first_zero_hint = 1; bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; brelse(bh); } /* free old bitmap blocks array */ SB_AP_BITMAP(s) = bitmap; vfree(old_bitmap); } /* begin transaction, if there was an error, it's fine. Yes, we have * incorrect bitmaps now, but none of it is ever going to touch the * disk anyway. */ err = journal_begin(&th, s, 10); if (err) return err; /* Extend old last bitmap block - new blocks have been made available */ info = SB_AP_BITMAP(s) + bmap_nr - 1; bh = reiserfs_read_bitmap_block(s, bmap_nr - 1); if (!bh) { int jerr = journal_end(&th, s, 10); if (jerr) return jerr; return -EIO; } reiserfs_prepare_for_journal(s, bh, 1); for (i = block_r; i < s->s_blocksize * 8; i++) reiserfs_test_and_clear_le_bit(i, bh->b_data); info->free_count += s->s_blocksize * 8 - block_r; if (!info->first_zero_hint) info->first_zero_hint = block_r; journal_mark_dirty(&th, s, bh); brelse(bh); /* Correct new last bitmap block - It may not be full */ info = SB_AP_BITMAP(s) + bmap_nr_new - 1; bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1); if (!bh) { int jerr = journal_end(&th, s, 10); if (jerr) return jerr; return -EIO; } reiserfs_prepare_for_journal(s, bh, 1); for (i = block_r_new; i < s->s_blocksize * 8; i++) reiserfs_test_and_set_le_bit(i, bh->b_data); journal_mark_dirty(&th, s, bh); brelse(bh); info->free_count -= s->s_blocksize * 8 - block_r_new; /* Extreme case where last bitmap is the only valid block in itself. */ if (!info->free_count) info->first_zero_hint = 0; /* update super */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); free_blocks = SB_FREE_BLOCKS(s); PUT_SB_FREE_BLOCKS(s, free_blocks + (block_count_new - block_count - (bmap_nr_new - bmap_nr))); PUT_SB_BLOCK_COUNT(s, block_count_new); PUT_SB_BMAP_NR(s, bmap_nr_new); s->s_dirt = 1; journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); SB_JOURNAL(s)->j_must_wait = 1; return journal_end(&th, s, 10); }