diff options
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/resize.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index a4693c0428be..771f7ada15d9 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -154,6 +154,34 @@ static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /* | 156 | /* |
157 | * If we have fewer than thresh credits, extend by EXT3_MAX_TRANS_DATA. | ||
158 | * If that fails, restart the transaction & regain write access for the | ||
159 | * buffer head which is used for block_bitmap modifications. | ||
160 | */ | ||
161 | static int extend_or_restart_transaction(handle_t *handle, int thresh, | ||
162 | struct buffer_head *bh) | ||
163 | { | ||
164 | int err; | ||
165 | |||
166 | if (handle->h_buffer_credits >= thresh) | ||
167 | return 0; | ||
168 | |||
169 | err = ext3_journal_extend(handle, EXT3_MAX_TRANS_DATA); | ||
170 | if (err < 0) | ||
171 | return err; | ||
172 | if (err) { | ||
173 | err = ext3_journal_restart(handle, EXT3_MAX_TRANS_DATA); | ||
174 | if (err) | ||
175 | return err; | ||
176 | err = ext3_journal_get_write_access(handle, bh); | ||
177 | if (err) | ||
178 | return err; | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | /* | ||
157 | * Set up the block and inode bitmaps, and the inode table for the new group. | 185 | * Set up the block and inode bitmaps, and the inode table for the new group. |
158 | * This doesn't need to be part of the main transaction, since we are only | 186 | * This doesn't need to be part of the main transaction, since we are only |
159 | * changing blocks outside the actual filesystem. We still do journaling to | 187 | * changing blocks outside the actual filesystem. We still do journaling to |
@@ -175,8 +203,9 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
175 | int i; | 203 | int i; |
176 | int err = 0, err2; | 204 | int err = 0, err2; |
177 | 205 | ||
178 | handle = ext3_journal_start_sb(sb, reserved_gdb + gdblocks + | 206 | /* This transaction may be extended/restarted along the way */ |
179 | 2 + sbi->s_itb_per_group); | 207 | handle = ext3_journal_start_sb(sb, EXT3_MAX_TRANS_DATA); |
208 | |||
180 | if (IS_ERR(handle)) | 209 | if (IS_ERR(handle)) |
181 | return PTR_ERR(handle); | 210 | return PTR_ERR(handle); |
182 | 211 | ||
@@ -203,6 +232,10 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
203 | 232 | ||
204 | ext3_debug("update backup group %#04lx (+%d)\n", block, bit); | 233 | ext3_debug("update backup group %#04lx (+%d)\n", block, bit); |
205 | 234 | ||
235 | err = extend_or_restart_transaction(handle, 1, bh); | ||
236 | if (err) | ||
237 | goto exit_bh; | ||
238 | |||
206 | gdb = sb_getblk(sb, block); | 239 | gdb = sb_getblk(sb, block); |
207 | if (!gdb) { | 240 | if (!gdb) { |
208 | err = -EIO; | 241 | err = -EIO; |
@@ -228,6 +261,10 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
228 | 261 | ||
229 | ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit); | 262 | ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit); |
230 | 263 | ||
264 | err = extend_or_restart_transaction(handle, 1, bh); | ||
265 | if (err) | ||
266 | goto exit_bh; | ||
267 | |||
231 | if (IS_ERR(gdb = bclean(handle, sb, block))) { | 268 | if (IS_ERR(gdb = bclean(handle, sb, block))) { |
232 | err = PTR_ERR(bh); | 269 | err = PTR_ERR(bh); |
233 | goto exit_bh; | 270 | goto exit_bh; |
@@ -249,6 +286,11 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
249 | struct buffer_head *it; | 286 | struct buffer_head *it; |
250 | 287 | ||
251 | ext3_debug("clear inode block %#04lx (+%d)\n", block, bit); | 288 | ext3_debug("clear inode block %#04lx (+%d)\n", block, bit); |
289 | |||
290 | err = extend_or_restart_transaction(handle, 1, bh); | ||
291 | if (err) | ||
292 | goto exit_bh; | ||
293 | |||
252 | if (IS_ERR(it = bclean(handle, sb, block))) { | 294 | if (IS_ERR(it = bclean(handle, sb, block))) { |
253 | err = PTR_ERR(it); | 295 | err = PTR_ERR(it); |
254 | goto exit_bh; | 296 | goto exit_bh; |
@@ -257,6 +299,11 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
257 | brelse(it); | 299 | brelse(it); |
258 | ext3_set_bit(bit, bh->b_data); | 300 | ext3_set_bit(bit, bh->b_data); |
259 | } | 301 | } |
302 | |||
303 | err = extend_or_restart_transaction(handle, 2, bh); | ||
304 | if (err) | ||
305 | goto exit_bh; | ||
306 | |||
260 | mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb), | 307 | mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb), |
261 | bh->b_data); | 308 | bh->b_data); |
262 | ext3_journal_dirty_metadata(handle, bh); | 309 | ext3_journal_dirty_metadata(handle, bh); |