]> git.hungrycats.org Git - linux/commitdiff
btrfs: add wrapper for transaction abort predicate
authorDavid Sterba <dsterba@suse.com>
Wed, 5 Feb 2020 16:34:34 +0000 (17:34 +0100)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Tue, 1 Sep 2020 04:44:29 +0000 (00:44 -0400)
[ Upstream commit bf31f87f71cc7a89871ab0a451c047a0c0144bf1 ]

The status of aborted transaction can change between calls and it needs
to be accessed by READ_ONCE. Add a helper that also wraps the unlikely
hint.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
(cherry picked from commit 84bfb4b10d6ffe98d33ebe2be8fef20d3e0385c9)

fs/btrfs/block-group.c
fs/btrfs/delayed-inode.c
fs/btrfs/extent-tree.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h

index cf90bb2b4e3c03eb2656db3e6149cf88b021a0e0..da17e343574fcf3deb6c892f382b0932dc61e6bb 100644 (file)
@@ -2187,7 +2187,7 @@ static int cache_save_setup(struct btrfs_block_group *block_group,
                return 0;
        }
 
-       if (trans->aborted)
+       if (TRANS_ABORTED(trans))
                return 0;
 again:
        inode = lookup_free_space_inode(block_group, path);
index 18509746208bbe9344c3b1eeddd1ec0ddae4f64d..9d1e381483a99123acb07148c832b4cdacb718f1 100644 (file)
@@ -1152,7 +1152,7 @@ static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, int nr)
        int ret = 0;
        bool count = (nr > 0);
 
-       if (trans->aborted)
+       if (TRANS_ABORTED(trans))
                return -EIO;
 
        path = btrfs_alloc_path();
index fcaf59e36fd06f327a31c6be1ff8c668d2d2c817..bede405d4cdac9c06349a90697b5339bcf093d8a 100644 (file)
@@ -1580,7 +1580,7 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
        int err = 0;
        int metadata = !extent_op->is_data;
 
-       if (trans->aborted)
+       if (TRANS_ABORTED(trans))
                return 0;
 
        if (metadata && !btrfs_fs_incompat(fs_info, SKINNY_METADATA))
@@ -1699,7 +1699,7 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
 {
        int ret = 0;
 
-       if (trans->aborted) {
+       if (TRANS_ABORTED(trans)) {
                if (insert_reserved)
                        btrfs_pin_extent(trans->fs_info, node->bytenr,
                                         node->num_bytes, 1);
@@ -2200,7 +2200,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
        int run_all = count == (unsigned long)-1;
 
        /* We'll clean this up in btrfs_cleanup_transaction */
-       if (trans->aborted)
+       if (TRANS_ABORTED(trans))
                return 0;
 
        if (test_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags))
@@ -2922,7 +2922,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
        else
                unpin = &fs_info->freed_extents[0];
 
-       while (!trans->aborted) {
+       while (!TRANS_ABORTED(trans)) {
                struct extent_state *cached_state = NULL;
 
                mutex_lock(&fs_info->unused_bg_unpin_mutex);
@@ -2954,7 +2954,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
                u64 trimmed = 0;
 
                ret = -EROFS;
-               if (!trans->aborted)
+               if (!TRANS_ABORTED(trans))
                        ret = btrfs_discard_extent(fs_info,
                                                   block_group->start,
                                                   block_group->length,
index 6d9a9f877ddbd9213ee35428cdf35d0d37980036..57bde66b150fba12f22cfbce10fcaf70c2990ddc 100644 (file)
@@ -241,7 +241,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
 
-       trans->aborted = errno;
+       WRITE_ONCE(trans->aborted, errno);
        /* Nothing used. The other threads that have joined this
         * transaction may be able to continue. */
        if (!trans->dirty && list_empty(&trans->new_bgs)) {
index b3ed9012c332fabc073ee90841ffbc06f82e6bcf..8c3c5b2d5de48f674b073cfa9b34a358b46c3bda 100644 (file)
@@ -244,7 +244,7 @@ loop:
 
        cur_trans = fs_info->running_transaction;
        if (cur_trans) {
-               if (cur_trans->aborted) {
+               if (TRANS_ABORTED(cur_trans)) {
                        spin_unlock(&fs_info->trans_lock);
                        return cur_trans->aborted;
                }
@@ -460,7 +460,7 @@ static inline int is_transaction_blocked(struct btrfs_transaction *trans)
 {
        return (trans->state >= TRANS_STATE_COMMIT_START &&
                trans->state < TRANS_STATE_UNBLOCKED &&
-               !trans->aborted);
+               !TRANS_ABORTED(trans));
 }
 
 /* wait for commit against the current transaction to become unblocked
@@ -479,7 +479,7 @@ static void wait_current_trans(struct btrfs_fs_info *fs_info)
 
                wait_event(fs_info->transaction_wait,
                           cur_trans->state >= TRANS_STATE_UNBLOCKED ||
-                          cur_trans->aborted);
+                          TRANS_ABORTED(cur_trans));
                btrfs_put_transaction(cur_trans);
        } else {
                spin_unlock(&fs_info->trans_lock);
@@ -932,7 +932,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
        if (throttle)
                btrfs_run_delayed_iputs(info);
 
-       if (trans->aborted ||
+       if (TRANS_ABORTED(trans) ||
            test_bit(BTRFS_FS_STATE_ERROR, &info->fs_state)) {
                wake_up_process(info->transaction_kthread);
                if (TRANS_ABORTED(trans))
@@ -1792,7 +1792,8 @@ static void wait_current_trans_commit_start(struct btrfs_fs_info *fs_info,
                                            struct btrfs_transaction *trans)
 {
        wait_event(fs_info->transaction_blocked_wait,
-                  trans->state >= TRANS_STATE_COMMIT_START || trans->aborted);
+                  trans->state >= TRANS_STATE_COMMIT_START ||
+                  TRANS_ABORTED(trans));
 }
 
 /*
@@ -1804,7 +1805,8 @@ static void wait_current_trans_commit_start_and_unblock(
                                        struct btrfs_transaction *trans)
 {
        wait_event(fs_info->transaction_wait,
-                  trans->state >= TRANS_STATE_UNBLOCKED || trans->aborted);
+                  trans->state >= TRANS_STATE_UNBLOCKED ||
+                  TRANS_ABORTED(trans));
 }
 
 /*
@@ -2024,7 +2026,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
        trans->dirty = true;
 
        /* Stop the commit early if ->aborted is set */
-       if (unlikely(READ_ONCE(cur_trans->aborted))) {
+       if (TRANS_ABORTED(cur_trans)) {
                ret = cur_trans->aborted;
                btrfs_end_transaction(trans);
                return ret;
@@ -2098,7 +2100,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 
                wait_for_commit(cur_trans);
 
-               if (unlikely(cur_trans->aborted))
+               if (TRANS_ABORTED(cur_trans))
                        ret = cur_trans->aborted;
 
                btrfs_put_transaction(cur_trans);
@@ -2117,7 +2119,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                        spin_unlock(&fs_info->trans_lock);
 
                        wait_for_commit(prev_trans);
-                       ret = prev_trans->aborted;
+                       ret = READ_ONCE(prev_trans->aborted);
 
                        btrfs_put_transaction(prev_trans);
                        if (ret)
@@ -2171,8 +2173,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
        wait_event(cur_trans->writer_wait,
                   atomic_read(&cur_trans->num_writers) == 1);
 
-       /* ->aborted might be set after the previous check, so check it */
-       if (unlikely(READ_ONCE(cur_trans->aborted))) {
+       if (TRANS_ABORTED(cur_trans)) {
                ret = cur_trans->aborted;
                goto scrub_continue;
        }
@@ -2290,7 +2291,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
         * The tasks which save the space cache and inode cache may also
         * update ->aborted, check it.
         */
-       if (unlikely(READ_ONCE(cur_trans->aborted))) {
+       if (TRANS_ABORTED(cur_trans)) {
                ret = cur_trans->aborted;
                mutex_unlock(&fs_info->tree_log_mutex);
                mutex_unlock(&fs_info->reloc_mutex);
index 972c38e6b197455d22bfe69fa8046c97fdec590b..228e8b560e42a379dce63473a2f2de905af6f4e0 100644 (file)
@@ -115,6 +115,10 @@ struct btrfs_trans_handle {
        struct btrfs_block_rsv *orig_rsv;
        refcount_t use_count;
        unsigned int type;
+       /*
+        * Error code of transaction abort, set outside of locks and must use
+        * the READ_ONCE/WRITE_ONCE access
+        */
        short aborted;
        bool adding_csums;
        bool allocating_chunk;
@@ -126,6 +130,14 @@ struct btrfs_trans_handle {
        struct list_head new_bgs;
 };
 
+/*
+ * The abort status can be changed between calls and is not protected by locks.
+ * This accepts btrfs_transaction and btrfs_trans_handle as types. Once it's
+ * set to a non-zero value it does not change, so the macro should be in checks
+ * but is not necessary for further reads of the value.
+ */
+#define TRANS_ABORTED(trans)           (unlikely(READ_ONCE((trans)->aborted)))
+
 struct btrfs_pending_snapshot {
        struct dentry *dentry;
        struct inode *dir;