Btrfs: hold i_mutex when calling btrfs_log_dentry_safe
authorJosef Bacik <josef@redhat.com>
Fri, 19 Nov 2010 20:36:10 +0000 (20:36 +0000)
committerChris Mason <chris.mason@oracle.com>
Mon, 22 Nov 2010 03:26:09 +0000 (22:26 -0500)
Since we walk up the path logging all of the parts of the inode's path, we need
to hold i_mutex to make sure that the inode is not renamed while we're logging
everything.  btrfs_log_dentry_safe does dget_parent and all of that jazz, but we
may get unexpected results if the rename changes the inode's location while
we're higher up the path logging those dentries, so do this for safety reasons.
Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/file.c

index e354c33df0824592bb9356be4987fd0ddfbbdc71..c1faded5fca03a7cbcb509908cfdf3cc8362ce1f 100644 (file)
@@ -1047,8 +1047,14 @@ out:
 
                if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
                        trans = btrfs_start_transaction(root, 0);
+                       if (IS_ERR(trans)) {
+                               num_written = PTR_ERR(trans);
+                               goto done;
+                       }
+                       mutex_lock(&inode->i_mutex);
                        ret = btrfs_log_dentry_safe(trans, root,
                                                    file->f_dentry);
+                       mutex_unlock(&inode->i_mutex);
                        if (ret == 0) {
                                ret = btrfs_sync_log(trans, root);
                                if (ret == 0)
@@ -1067,6 +1073,7 @@ out:
                             (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT);
                }
        }
+done:
        current->backing_dev_info = NULL;
        return num_written ? num_written : err;
 }