X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Freiserfs%2Fresize.c;h=f71c3948edef8324ac68a71042fbc35209cb5ea3;hb=2848077044a5fdeb942bd1342c550da4c452d66a;hp=39cc7f47f5dc57686469302c9ba75e3289d1360f;hpb=ef88b7dba2b47c70037a34a599d383462bb74bd3;p=linux-2.6-omap-h63xx.git diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 39cc7f47f5d..f71c3948ede 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c @@ -22,6 +22,7 @@ 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; @@ -60,7 +61,8 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) } /* count used bits in last bitmap block */ - block_r = SB_BLOCK_COUNT(s) - (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8; + block_r = SB_BLOCK_COUNT(s) - + (reiserfs_bmap_count(s) - 1) * s->s_blocksize * 8; /* count bitmap blocks in new fs */ bmap_nr_new = block_count_new / (s->s_blocksize * 8); @@ -72,7 +74,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) /* save old values */ block_count = SB_BLOCK_COUNT(s); - bmap_nr = SB_BMAP_NR(s); + bmap_nr = reiserfs_bmap_count(s); /* resizing of reiserfs bitmaps (journal and real), if needed */ if (bmap_nr_new > bmap_nr) { @@ -118,7 +120,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) return -ENOMEM; } memset(bitmap, 0, - sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); + sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); for (i = 0; i < bmap_nr; i++) bitmap[i] = old_bitmap[i]; @@ -127,16 +129,23 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) * transaction begins, and the new bitmaps don't matter if the * transaction fails. */ 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); + /* don't use read_bitmap_block since it will cache + * the uninitialized bitmap */ + bh = sb_bread(s, i * s->s_blocksize * 8); + if (!bh) { + vfree(bitmap); + return -EIO; + } + 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; @@ -150,30 +159,41 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) if (err) return err; - /* correct last bitmap blocks in old and new disk layout */ - reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1); + /* 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, - 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; + reiserfs_test_and_clear_le_bit(i, bh->b_data); + info->free_count += s->s_blocksize * 8 - block_r; - journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh); + journal_mark_dirty(&th, s, bh); + brelse(bh); - reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1); + /* 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, - 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; + 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; /* update super */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); free_blocks = SB_FREE_BLOCKS(s); @@ -181,7 +201,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) 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); + PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new); s->s_dirt = 1; journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));