]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: make btrfs_check_nocow_lock nowait compatible
authorJosef Bacik <josef@toxicpanda.com>
Mon, 12 Sep 2022 19:27:46 +0000 (12:27 -0700)
committerDavid Sterba <dsterba@suse.com>
Thu, 29 Sep 2022 15:08:28 +0000 (17:08 +0200)
Now all the helpers that btrfs_check_nocow_lock uses handle nowait, add
a nowait flag to btrfs_check_nocow_lock so it can be used by the write
path.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Stefan Roesch <shr@fb.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/btrfs/inode.c

index 5a337d10c5e29beea3c317c01947f1a6354a81e2..fee0e6925e175fbeae2fd300c1a6240b9cac31e1 100644 (file)
@@ -3525,7 +3525,7 @@ int btrfs_dirty_pages(struct btrfs_inode *inode, struct page **pages,
                      struct extent_state **cached, bool noreserve);
 int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end);
 int btrfs_check_nocow_lock(struct btrfs_inode *inode, loff_t pos,
-                          size_t *write_bytes);
+                          size_t *write_bytes, bool nowait);
 void btrfs_check_nocow_unlock(struct btrfs_inode *inode);
 bool btrfs_find_delalloc_in_range(struct btrfs_inode *inode, u64 start, u64 end,
                                  u64 *delalloc_start_ret, u64 *delalloc_end_ret);
index 94a9b47d5ae5ec4ddba0a113ec35fc712b72e902..c7edac4733810bd2cef45be060da22647231947a 100644 (file)
@@ -1480,7 +1480,7 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
  * NOTE: Callers need to call btrfs_check_nocow_unlock() if we return > 0.
  */
 int btrfs_check_nocow_lock(struct btrfs_inode *inode, loff_t pos,
-                          size_t *write_bytes)
+                          size_t *write_bytes, bool nowait)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        struct btrfs_root *root = inode->root;
@@ -1499,16 +1499,21 @@ int btrfs_check_nocow_lock(struct btrfs_inode *inode, loff_t pos,
                           fs_info->sectorsize) - 1;
        num_bytes = lockend - lockstart + 1;
 
-       btrfs_lock_and_flush_ordered_range(inode, lockstart, lockend, NULL);
+       if (nowait) {
+               if (!btrfs_try_lock_ordered_range(inode, lockstart, lockend)) {
+                       btrfs_drew_write_unlock(&root->snapshot_lock);
+                       return -EAGAIN;
+               }
+       } else {
+               btrfs_lock_and_flush_ordered_range(inode, lockstart, lockend, NULL);
+       }
        ret = can_nocow_extent(&inode->vfs_inode, lockstart, &num_bytes,
-                       NULL, NULL, NULL, false, false);
-       if (ret <= 0) {
-               ret = 0;
+                       NULL, NULL, NULL, nowait, false);
+       if (ret <= 0)
                btrfs_drew_write_unlock(&root->snapshot_lock);
-       } else {
+       else
                *write_bytes = min_t(size_t, *write_bytes ,
                                     num_bytes - pos + lockstart);
-       }
        unlock_extent(&inode->io_tree, lockstart, lockend, NULL);
 
        return ret;
@@ -1665,16 +1670,22 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
                                                  &data_reserved, pos,
                                                  write_bytes, false);
                if (ret < 0) {
+                       int can_nocow;
+
                        /*
                         * If we don't have to COW at the offset, reserve
                         * metadata only. write_bytes may get smaller than
                         * requested here.
                         */
-                       if (btrfs_check_nocow_lock(BTRFS_I(inode), pos,
-                                                  &write_bytes) > 0)
-                               only_release_metadata = true;
-                       else
+                       can_nocow = btrfs_check_nocow_lock(BTRFS_I(inode), pos,
+                                                          &write_bytes, false);
+                       if (can_nocow < 0)
+                               ret = can_nocow;
+                       if (can_nocow > 0)
+                               ret = 0;
+                       if (ret)
                                break;
+                       only_release_metadata = true;
                }
 
                num_pages = DIV_ROUND_UP(write_bytes + offset, PAGE_SIZE);
index 0c92b22aa3b6279579036a59753d3771f1a0c9fb..d5fac2979deb967981704aff591f3388fd706fcc 100644 (file)
@@ -4887,7 +4887,7 @@ int btrfs_truncate_block(struct btrfs_inode *inode, loff_t from, loff_t len,
        ret = btrfs_check_data_free_space(inode, &data_reserved, block_start,
                                          blocksize, false);
        if (ret < 0) {
-               if (btrfs_check_nocow_lock(inode, block_start, &write_bytes) > 0) {
+               if (btrfs_check_nocow_lock(inode, block_start, &write_bytes, false) > 0) {
                        /* For nocow case, no need to reserve data space */
                        only_release_metadata = true;
                } else {