btrfs: refactor btrfs_dec_test_* functions for ordered extents
authorQu Wenruo <wqu@suse.com>
Tue, 22 Dec 2020 05:59:24 +0000 (13:59 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 8 Feb 2021 21:58:51 +0000 (22:58 +0100)
The refactoring involves the following modifications:

- Return bool instead of int

- Parameter update for @cached of btrfs_dec_test_first_ordered_pending()
  For btrfs_dec_test_first_ordered_pending(), @cached is only used to
  return the finished ordered extent.
  Rename it to @finished_ret.

- Comment updates

  * Change one stale comment
    Which still refers to btrfs_dec_test_ordered_pending(), but the
    context is calling  btrfs_dec_test_first_ordered_pending().
  * Follow the common comment style for both functions
    Add more detailed descriptions for parameters and the return value
  * Move the reason why test_and_set_bit() is used into the call sites

- Change how the return value is calculated
  The most anti-human part of the return value is:

    if (...)
ret = 1;
    ...
    return ret == 0;

  This means, when we set ret to 1, the function returns 0.
  Change the local variable name to @finished, and directly return the
  value of it.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/inode.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h

index 4056fc3b39cff3cb4a72e8345db3d6b66b8db413..ef6cb7b620d005d5ef0a0befa5b56742d9819a05 100644 (file)
@@ -7797,10 +7797,8 @@ static void __endio_write_update_ordered(struct btrfs_inode *inode,
                                        NULL);
                        btrfs_queue_work(wq, &ordered->work);
                }
-               /*
-                * If btrfs_dec_test_ordered_pending does not find any ordered
-                * extent in the range, we can exit.
-                */
+
+               /* No ordered extent found in the range, exit */
                if (ordered_offset == last_offset)
                        return;
                /*
index 79d366a36223a790fafae0c23c15b8161459597f..d5d326c674b1a77e3894eb944677307b04879ad7 100644 (file)
@@ -297,26 +297,33 @@ void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry,
 }
 
 /*
- * this is used to account for finished IO across a given range
- * of the file.  The IO may span ordered extents.  If
- * a given ordered_extent is completely done, 1 is returned, otherwise
- * 0.
+ * Finish IO for one ordered extent across a given range.  The range can
+ * contain several ordered extents.
  *
- * test_and_set_bit on a flag in the struct btrfs_ordered_extent is used
- * to make sure this function only returns 1 once for a given ordered extent.
+ * @found_ret:  Return the finished ordered extent
+ * @file_offset: File offset for the finished IO
+ *              Will also be updated to one byte past the range that is
+ *              recordered as finished. This allows caller to walk forward.
+ * @io_size:    Length of the finish IO range
+ * @uptodate:   If the IO finished without problem
  *
- * file_offset is updated to one byte past the range that is recorded as
- * complete.  This allows you to walk forward in the file.
+ * Return true if any ordered extent is finished in the range, and update
+ * @found_ret and @file_offset.
+ * Return false otherwise.
+ *
+ * NOTE: Although The range can cross multiple ordered extents, only one
+ * ordered extent will be updated during one call. The caller is responsible to
+ * iterate all ordered extents in the range.
  */
-int btrfs_dec_test_first_ordered_pending(struct btrfs_inode *inode,
-                                  struct btrfs_ordered_extent **cached,
+bool btrfs_dec_test_first_ordered_pending(struct btrfs_inode *inode,
+                                  struct btrfs_ordered_extent **finished_ret,
                                   u64 *file_offset, u64 io_size, int uptodate)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        struct btrfs_ordered_inode_tree *tree = &inode->ordered_tree;
        struct rb_node *node;
        struct btrfs_ordered_extent *entry = NULL;
-       int ret;
+       bool finished = false;
        unsigned long flags;
        u64 dec_end;
        u64 dec_start;
@@ -324,16 +331,12 @@ int btrfs_dec_test_first_ordered_pending(struct btrfs_inode *inode,
 
        spin_lock_irqsave(&tree->lock, flags);
        node = tree_search(tree, *file_offset);
-       if (!node) {
-               ret = 1;
+       if (!node)
                goto out;
-       }
 
        entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-       if (!offset_in_entry(entry, *file_offset)) {
-               ret = 1;
+       if (!offset_in_entry(entry, *file_offset))
                goto out;
-       }
 
        dec_start = max(*file_offset, entry->file_offset);
        dec_end = min(*file_offset + io_size,
@@ -354,39 +357,50 @@ int btrfs_dec_test_first_ordered_pending(struct btrfs_inode *inode,
                set_bit(BTRFS_ORDERED_IOERR, &entry->flags);
 
        if (entry->bytes_left == 0) {
-               ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
+               /*
+                * Ensure only one caller can set the flag and finished_ret
+                * accordingly
+                */
+               finished = !test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
                /* test_and_set_bit implies a barrier */
                cond_wake_up_nomb(&entry->wait);
-       } else {
-               ret = 1;
        }
 out:
-       if (!ret && cached && entry) {
-               *cached = entry;
+       if (finished && finished_ret && entry) {
+               *finished_ret = entry;
                refcount_inc(&entry->refs);
        }
        spin_unlock_irqrestore(&tree->lock, flags);
-       return ret == 0;
+       return finished;
 }
 
 /*
- * this is used to account for finished IO across a given range
- * of the file.  The IO should not span ordered extents.  If
- * a given ordered_extent is completely done, 1 is returned, otherwise
- * 0.
+ * Finish IO for one ordered extent across a given range.  The range can only
+ * contain one ordered extent.
+ *
+ * @cached:     The cached ordered extent. If not NULL, we can skip the tree
+ *               search and use the ordered extent directly.
+ *              Will be also used to store the finished ordered extent.
+ * @file_offset: File offset for the finished IO
+ * @io_size:    Length of the finish IO range
+ * @uptodate:   If the IO finishes without problem
+ *
+ * Return true if the ordered extent is finished in the range, and update
+ * @cached.
+ * Return false otherwise.
  *
- * test_and_set_bit on a flag in the struct btrfs_ordered_extent is used
- * to make sure this function only returns 1 once for a given ordered extent.
+ * NOTE: The range can NOT cross multiple ordered extents.
+ * Thus caller should ensure the range doesn't cross ordered extents.
  */
-int btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
-                                  struct btrfs_ordered_extent **cached,
-                                  u64 file_offset, u64 io_size, int uptodate)
+bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
+                                   struct btrfs_ordered_extent **cached,
+                                   u64 file_offset, u64 io_size, int uptodate)
 {
        struct btrfs_ordered_inode_tree *tree = &inode->ordered_tree;
        struct rb_node *node;
        struct btrfs_ordered_extent *entry = NULL;
        unsigned long flags;
-       int ret;
+       bool finished = false;
 
        spin_lock_irqsave(&tree->lock, flags);
        if (cached && *cached) {
@@ -395,41 +409,39 @@ int btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
        }
 
        node = tree_search(tree, file_offset);
-       if (!node) {
-               ret = 1;
+       if (!node)
                goto out;
-       }
 
        entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
 have_entry:
-       if (!offset_in_entry(entry, file_offset)) {
-               ret = 1;
+       if (!offset_in_entry(entry, file_offset))
                goto out;
-       }
 
-       if (io_size > entry->bytes_left) {
+       if (io_size > entry->bytes_left)
                btrfs_crit(inode->root->fs_info,
                           "bad ordered accounting left %llu size %llu",
                       entry->bytes_left, io_size);
-       }
+
        entry->bytes_left -= io_size;
        if (!uptodate)
                set_bit(BTRFS_ORDERED_IOERR, &entry->flags);
 
        if (entry->bytes_left == 0) {
-               ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
+               /*
+                * Ensure only one caller can set the flag and finished_ret
+                * accordingly
+                */
+               finished = !test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
                /* test_and_set_bit implies a barrier */
                cond_wake_up_nomb(&entry->wait);
-       } else {
-               ret = 1;
        }
 out:
-       if (!ret && cached && entry) {
+       if (finished && cached && entry) {
                *cached = entry;
                refcount_inc(&entry->refs);
        }
        spin_unlock_irqrestore(&tree->lock, flags);
-       return ret == 0;
+       return finished;
 }
 
 /*
index 0bfa82b58e237e39656f08334eec11035c4c713e..46194c2c05d40e58d805b9bac11e3ba0b4b2cbb1 100644 (file)
@@ -152,11 +152,11 @@ btrfs_ordered_inode_tree_init(struct btrfs_ordered_inode_tree *t)
 void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry);
 void btrfs_remove_ordered_extent(struct btrfs_inode *btrfs_inode,
                                struct btrfs_ordered_extent *entry);
-int btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
-                                  struct btrfs_ordered_extent **cached,
-                                  u64 file_offset, u64 io_size, int uptodate);
-int btrfs_dec_test_first_ordered_pending(struct btrfs_inode *inode,
-                                  struct btrfs_ordered_extent **cached,
+bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
+                                   struct btrfs_ordered_extent **cached,
+                                   u64 file_offset, u64 io_size, int uptodate);
+bool btrfs_dec_test_first_ordered_pending(struct btrfs_inode *inode,
+                                  struct btrfs_ordered_extent **finished_ret,
                                   u64 *file_offset, u64 io_size,
                                   int uptodate);
 int btrfs_add_ordered_extent(struct btrfs_inode *inode, u64 file_offset,