aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/tree-log.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 67e5bf709dca..60e1d0083faa 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4273,6 +4273,9 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
4273 struct dentry *old_parent = NULL; 4273 struct dentry *old_parent = NULL;
4274 int ret = 0; 4274 int ret = 0;
4275 u64 last_committed = root->fs_info->last_trans_committed; 4275 u64 last_committed = root->fs_info->last_trans_committed;
4276 const struct dentry * const first_parent = parent;
4277 const bool did_unlink = (BTRFS_I(inode)->last_unlink_trans >
4278 last_committed);
4276 4279
4277 sb = inode->i_sb; 4280 sb = inode->i_sb;
4278 4281
@@ -4328,7 +4331,6 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
4328 goto end_trans; 4331 goto end_trans;
4329 } 4332 }
4330 4333
4331 inode_only = LOG_INODE_EXISTS;
4332 while (1) { 4334 while (1) {
4333 if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb) 4335 if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
4334 break; 4336 break;
@@ -4337,8 +4339,22 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
4337 if (root != BTRFS_I(inode)->root) 4339 if (root != BTRFS_I(inode)->root)
4338 break; 4340 break;
4339 4341
4342 /*
4343 * On unlink we must make sure our immediate parent directory
4344 * inode is fully logged. This is to prevent leaving dangling
4345 * directory index entries and a wrong directory inode's i_size.
4346 * Not doing so can result in a directory being impossible to
4347 * delete after log replay (rmdir will always fail with error
4348 * -ENOTEMPTY).
4349 */
4350 if (did_unlink && parent == first_parent)
4351 inode_only = LOG_INODE_ALL;
4352 else
4353 inode_only = LOG_INODE_EXISTS;
4354
4340 if (BTRFS_I(inode)->generation > 4355 if (BTRFS_I(inode)->generation >
4341 root->fs_info->last_trans_committed) { 4356 root->fs_info->last_trans_committed ||
4357 inode_only == LOG_INODE_ALL) {
4342 ret = btrfs_log_inode(trans, root, inode, inode_only, 4358 ret = btrfs_log_inode(trans, root, inode, inode_only,
4343 0, LLONG_MAX, ctx); 4359 0, LLONG_MAX, ctx);
4344 if (ret) 4360 if (ret)