summaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-06-22 11:42:09 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-06-22 11:42:09 -0400
commit30a7eb970c3aae6f1b74b2edea896fdca1cbea38 (patch)
tree28f27a320e3f0db679e8629ea201c053c871c159 /fs/ext4/inode.c
parent02749a4c20827649859bf7e2435f1b238c24f935 (diff)
ext4: cleanup transaction restarts during inode deletion
During inode deletion, the number of journal credits that will be needed is hard to determine. For that reason we have journal extend/restart calls in several places. Whenever a transaction is restarted, filesystem must be in a consistent state because there is no atomicity guarantee beyond a restart call. Add ext4_xattr_ensure_credits() helper function which takes care of journal extend/restart logic. It also handles getting jbd2 write access and dirty metadata calls. This function is called at every iteration of handling an ea_inode reference. Signed-off-by: Tahsin Erdogan <tahsin@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c66
1 files changed, 17 insertions, 49 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3e9415e2e74d..46def73d3472 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -239,7 +239,11 @@ void ext4_evict_inode(struct inode *inode)
239 */ 239 */
240 sb_start_intwrite(inode->i_sb); 240 sb_start_intwrite(inode->i_sb);
241 241
242 handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, extra_credits); 242 if (!IS_NOQUOTA(inode))
243 extra_credits += EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb);
244
245 handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE,
246 ext4_blocks_for_truncate(inode)+extra_credits);
243 if (IS_ERR(handle)) { 247 if (IS_ERR(handle)) {
244 ext4_std_error(inode->i_sb, PTR_ERR(handle)); 248 ext4_std_error(inode->i_sb, PTR_ERR(handle));
245 /* 249 /*
@@ -251,36 +255,9 @@ void ext4_evict_inode(struct inode *inode)
251 sb_end_intwrite(inode->i_sb); 255 sb_end_intwrite(inode->i_sb);
252 goto no_delete; 256 goto no_delete;
253 } 257 }
258
254 if (IS_SYNC(inode)) 259 if (IS_SYNC(inode))
255 ext4_handle_sync(handle); 260 ext4_handle_sync(handle);
256
257 /*
258 * Delete xattr inode before deleting the main inode.
259 */
260 err = ext4_xattr_delete_inode(handle, inode, &ea_inode_array);
261 if (err) {
262 ext4_warning(inode->i_sb,
263 "couldn't delete inode's xattr (err %d)", err);
264 goto stop_handle;
265 }
266
267 if (!IS_NOQUOTA(inode))
268 extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb);
269
270 if (!ext4_handle_has_enough_credits(handle,
271 ext4_blocks_for_truncate(inode) + extra_credits)) {
272 err = ext4_journal_extend(handle,
273 ext4_blocks_for_truncate(inode) + extra_credits);
274 if (err > 0)
275 err = ext4_journal_restart(handle,
276 ext4_blocks_for_truncate(inode) + extra_credits);
277 if (err != 0) {
278 ext4_warning(inode->i_sb,
279 "couldn't extend journal (err %d)", err);
280 goto stop_handle;
281 }
282 }
283
284 inode->i_size = 0; 261 inode->i_size = 0;
285 err = ext4_mark_inode_dirty(handle, inode); 262 err = ext4_mark_inode_dirty(handle, inode);
286 if (err) { 263 if (err) {
@@ -298,25 +275,17 @@ void ext4_evict_inode(struct inode *inode)
298 } 275 }
299 } 276 }
300 277
301 /* 278 /* Remove xattr references. */
302 * ext4_ext_truncate() doesn't reserve any slop when it 279 err = ext4_xattr_delete_inode(handle, inode, &ea_inode_array,
303 * restarts journal transactions; therefore there may not be 280 extra_credits);
304 * enough credits left in the handle to remove the inode from 281 if (err) {
305 * the orphan list and set the dtime field. 282 ext4_warning(inode->i_sb, "xattr delete (err %d)", err);
306 */ 283stop_handle:
307 if (!ext4_handle_has_enough_credits(handle, extra_credits)) { 284 ext4_journal_stop(handle);
308 err = ext4_journal_extend(handle, extra_credits); 285 ext4_orphan_del(NULL, inode);
309 if (err > 0) 286 sb_end_intwrite(inode->i_sb);
310 err = ext4_journal_restart(handle, extra_credits); 287 ext4_xattr_inode_array_free(ea_inode_array);
311 if (err != 0) { 288 goto no_delete;
312 ext4_warning(inode->i_sb,
313 "couldn't extend journal (err %d)", err);
314 stop_handle:
315 ext4_journal_stop(handle);
316 ext4_orphan_del(NULL, inode);
317 sb_end_intwrite(inode->i_sb);
318 goto no_delete;
319 }
320 } 289 }
321 290
322 /* 291 /*
@@ -342,7 +311,6 @@ void ext4_evict_inode(struct inode *inode)
342 ext4_clear_inode(inode); 311 ext4_clear_inode(inode);
343 else 312 else
344 ext4_free_inode(handle, inode); 313 ext4_free_inode(handle, inode);
345
346 ext4_journal_stop(handle); 314 ext4_journal_stop(handle);
347 sb_end_intwrite(inode->i_sb); 315 sb_end_intwrite(inode->i_sb);
348 ext4_xattr_inode_array_free(ea_inode_array); 316 ext4_xattr_inode_array_free(ea_inode_array);