diff options
Diffstat (limited to 'fs/reiserfs/resize.c')
-rw-r--r-- | fs/reiserfs/resize.c | 71 |
1 files changed, 46 insertions, 25 deletions
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 39cc7f47f5dc..315684793d1d 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) | |||
22 | int err = 0; | 22 | int err = 0; |
23 | struct reiserfs_super_block *sb; | 23 | struct reiserfs_super_block *sb; |
24 | struct reiserfs_bitmap_info *bitmap; | 24 | struct reiserfs_bitmap_info *bitmap; |
25 | struct reiserfs_bitmap_info *info; | ||
25 | struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s); | 26 | struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s); |
26 | struct buffer_head *bh; | 27 | struct buffer_head *bh; |
27 | struct reiserfs_transaction_handle th; | 28 | struct reiserfs_transaction_handle th; |
@@ -127,16 +128,20 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
127 | * transaction begins, and the new bitmaps don't matter if the | 128 | * transaction begins, and the new bitmaps don't matter if the |
128 | * transaction fails. */ | 129 | * transaction fails. */ |
129 | for (i = bmap_nr; i < bmap_nr_new; i++) { | 130 | for (i = bmap_nr; i < bmap_nr_new; i++) { |
130 | bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8); | 131 | /* don't use read_bitmap_block since it will cache |
131 | memset(bitmap[i].bh->b_data, 0, sb_blocksize(sb)); | 132 | * the uninitialized bitmap */ |
132 | reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data); | 133 | bh = sb_bread(s, i * s->s_blocksize * 8); |
133 | 134 | memset(bh->b_data, 0, sb_blocksize(sb)); | |
134 | set_buffer_uptodate(bitmap[i].bh); | 135 | reiserfs_test_and_set_le_bit(0, bh->b_data); |
135 | mark_buffer_dirty(bitmap[i].bh); | 136 | reiserfs_cache_bitmap_metadata(s, bh, bitmap + i); |
136 | sync_dirty_buffer(bitmap[i].bh); | 137 | |
138 | set_buffer_uptodate(bh); | ||
139 | mark_buffer_dirty(bh); | ||
140 | sync_dirty_buffer(bh); | ||
137 | // update bitmap_info stuff | 141 | // update bitmap_info stuff |
138 | bitmap[i].first_zero_hint = 1; | 142 | bitmap[i].first_zero_hint = 1; |
139 | bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; | 143 | bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; |
144 | brelse(bh); | ||
140 | } | 145 | } |
141 | /* free old bitmap blocks array */ | 146 | /* free old bitmap blocks array */ |
142 | SB_AP_BITMAP(s) = bitmap; | 147 | SB_AP_BITMAP(s) = bitmap; |
@@ -150,30 +155,46 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
150 | if (err) | 155 | if (err) |
151 | return err; | 156 | return err; |
152 | 157 | ||
153 | /* correct last bitmap blocks in old and new disk layout */ | 158 | /* Extend old last bitmap block - new blocks have been made available */ |
154 | reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1); | 159 | info = SB_AP_BITMAP(s) + bmap_nr - 1; |
160 | bh = reiserfs_read_bitmap_block(s, bmap_nr - 1); | ||
161 | if (!bh) { | ||
162 | int jerr = journal_end(&th, s, 10); | ||
163 | if (jerr) | ||
164 | return jerr; | ||
165 | return -EIO; | ||
166 | } | ||
167 | |||
168 | reiserfs_prepare_for_journal(s, bh, 1); | ||
155 | for (i = block_r; i < s->s_blocksize * 8; i++) | 169 | for (i = block_r; i < s->s_blocksize * 8; i++) |
156 | reiserfs_test_and_clear_le_bit(i, | 170 | reiserfs_test_and_clear_le_bit(i, bh->b_data); |
157 | SB_AP_BITMAP(s)[bmap_nr - | 171 | info->free_count += s->s_blocksize * 8 - block_r; |
158 | 1].bh->b_data); | 172 | if (!info->first_zero_hint) |
159 | SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r; | 173 | info->first_zero_hint = block_r; |
160 | if (!SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint) | ||
161 | SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r; | ||
162 | 174 | ||
163 | journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh); | 175 | journal_mark_dirty(&th, s, bh); |
176 | brelse(bh); | ||
177 | |||
178 | /* Correct new last bitmap block - It may not be full */ | ||
179 | info = SB_AP_BITMAP(s) + bmap_nr_new - 1; | ||
180 | bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1); | ||
181 | if (!bh) { | ||
182 | int jerr = journal_end(&th, s, 10); | ||
183 | if (jerr) | ||
184 | return jerr; | ||
185 | return -EIO; | ||
186 | } | ||
164 | 187 | ||
165 | reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1); | 188 | reiserfs_prepare_for_journal(s, bh, 1); |
166 | for (i = block_r_new; i < s->s_blocksize * 8; i++) | 189 | for (i = block_r_new; i < s->s_blocksize * 8; i++) |
167 | reiserfs_test_and_set_le_bit(i, | 190 | reiserfs_test_and_set_le_bit(i, bh->b_data); |
168 | SB_AP_BITMAP(s)[bmap_nr_new - | 191 | journal_mark_dirty(&th, s, bh); |
169 | 1].bh->b_data); | 192 | brelse(bh); |
170 | journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh); | ||
171 | 193 | ||
172 | SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -= | 194 | info->free_count -= s->s_blocksize * 8 - block_r_new; |
173 | s->s_blocksize * 8 - block_r_new; | ||
174 | /* Extreme case where last bitmap is the only valid block in itself. */ | 195 | /* Extreme case where last bitmap is the only valid block in itself. */ |
175 | if (!SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count) | 196 | if (!info->free_count) |
176 | SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0; | 197 | info->first_zero_hint = 0; |
177 | /* update super */ | 198 | /* update super */ |
178 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); | 199 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); |
179 | free_blocks = SB_FREE_BLOCKS(s); | 200 | free_blocks = SB_FREE_BLOCKS(s); |