btrfs: check FS error state bit early during write
authorGoldwyn Rodrigues <rgoldwyn@suse.com>
Thu, 24 Sep 2020 16:39:14 +0000 (11:39 -0500)
committerDavid Sterba <dsterba@suse.com>
Tue, 8 Dec 2020 14:53:46 +0000 (15:53 +0100)
fs_info::fs_state is a filesystem bit check as opposed to inode and can
be performed before we begin with write checks. This eliminates inode
lock/unlock in case the error bit is set.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/file.c

index e80d729..f5d02b4 100644 (file)
@@ -1907,6 +1907,14 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
        size_t count;
        loff_t oldsize;
 
+       /*
+        * If the fs flips readonly due to some impossible error, although we
+        * have opened a file as writable, we have to stop this write operation
+        * to ensure consistency.
+        */
+       if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
+               return -EROFS;
+
        if (!(iocb->ki_flags & IOCB_DIRECT) &&
            (iocb->ki_flags & IOCB_NOWAIT))
                return -EOPNOTSUPP;
@@ -1957,18 +1965,6 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
        }
 
        /*
-        * If BTRFS flips readonly due to some impossible error
-        * (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR),
-        * although we have opened a file as writable, we have
-        * to stop this write operation to ensure FS consistency.
-        */
-       if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
-               inode_unlock(inode);
-               err = -EROFS;
-               goto out;
-       }
-
-       /*
         * We reserve space for updating the inode when we reserve space for the
         * extent we are going to write, so we will enospc out there.  We don't
         * need to start yet another transaction to update the inode as we will