inode: port __I_NEW to var event
authorChristian Brauner <brauner@kernel.org>
Fri, 23 Aug 2024 12:47:38 +0000 (14:47 +0200)
committerChristian Brauner <brauner@kernel.org>
Fri, 30 Aug 2024 06:22:39 +0000 (08:22 +0200)
Port the __I_NEW mechanism to use the new var event mechanism.

Link: https://lore.kernel.org/r/20240823-work-i_state-v3-4-5cd5fd207a57@kernel.org
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/bcachefs/fs.c
fs/dcache.c
fs/inode.c
include/linux/writeback.h

index 94c392abef65cdda64624c9eeec5c56875611e1e..c0900c0c0f8a04d20c77e583112c4a1e6ce5e752 100644 (file)
@@ -1644,14 +1644,16 @@ again:
                                break;
                        }
                } else if (clean_pass && this_pass_clean) {
-                       wait_queue_head_t *wq = bit_waitqueue(&inode->v.i_state, __I_NEW);
-                       DEFINE_WAIT_BIT(wait, &inode->v.i_state, __I_NEW);
+                       struct wait_bit_queue_entry wqe;
+                       struct wait_queue_head *wq_head;
 
-                       prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
+                       wq_head = inode_bit_waitqueue(&wqe, &inode->v, __I_NEW);
+                       prepare_to_wait_event(wq_head, &wqe.wq_entry,
+                                             TASK_UNINTERRUPTIBLE);
                        mutex_unlock(&c->vfs_inodes_lock);
 
                        schedule();
-                       finish_wait(wq, &wait.wq_entry);
+                       finish_wait(wq_head, &wqe.wq_entry);
                        goto again;
                }
        }
index 1af75fa68638a0034a3959e31340f20f1c26197d..894e38cdf4d0cda475b246f9e114fdca2bac59a9 100644 (file)
@@ -1908,8 +1908,13 @@ void d_instantiate_new(struct dentry *entry, struct inode *inode)
        __d_instantiate(entry, inode);
        WARN_ON(!(inode->i_state & I_NEW));
        inode->i_state &= ~I_NEW & ~I_CREATING;
+       /*
+        * Pairs with the barrier in prepare_to_wait_event() to make sure
+        * ___wait_var_event() either sees the bit cleared or
+        * waitqueue_active() check in wake_up_var() sees the waiter.
+        */
        smp_mb();
-       wake_up_bit(&inode->i_state, __I_NEW);
+       inode_wake_up_bit(inode, __I_NEW);
        spin_unlock(&inode->i_lock);
 }
 EXPORT_SYMBOL(d_instantiate_new);
index 1b0f52ebae27997333762cf82a3e474e8db8c70b..1aa785421f1349423777979a825df761b99b278e 100644 (file)
@@ -734,7 +734,13 @@ static void evict(struct inode *inode)
         * used as an indicator whether blocking on it is safe.
         */
        spin_lock(&inode->i_lock);
-       wake_up_bit(&inode->i_state, __I_NEW);
+       /*
+        * Pairs with the barrier in prepare_to_wait_event() to make sure
+        * ___wait_var_event() either sees the bit cleared or
+        * waitqueue_active() check in wake_up_var() sees the waiter.
+        */
+       smp_mb();
+       inode_wake_up_bit(inode, __I_NEW);
        BUG_ON(inode->i_state != (I_FREEING | I_CLEAR));
        spin_unlock(&inode->i_lock);
 
@@ -1146,8 +1152,13 @@ void unlock_new_inode(struct inode *inode)
        spin_lock(&inode->i_lock);
        WARN_ON(!(inode->i_state & I_NEW));
        inode->i_state &= ~I_NEW & ~I_CREATING;
+       /*
+        * Pairs with the barrier in prepare_to_wait_event() to make sure
+        * ___wait_var_event() either sees the bit cleared or
+        * waitqueue_active() check in wake_up_var() sees the waiter.
+        */
        smp_mb();
-       wake_up_bit(&inode->i_state, __I_NEW);
+       inode_wake_up_bit(inode, __I_NEW);
        spin_unlock(&inode->i_lock);
 }
 EXPORT_SYMBOL(unlock_new_inode);
@@ -1158,8 +1169,13 @@ void discard_new_inode(struct inode *inode)
        spin_lock(&inode->i_lock);
        WARN_ON(!(inode->i_state & I_NEW));
        inode->i_state &= ~I_NEW;
+       /*
+        * Pairs with the barrier in prepare_to_wait_event() to make sure
+        * ___wait_var_event() either sees the bit cleared or
+        * waitqueue_active() check in wake_up_var() sees the waiter.
+        */
        smp_mb();
-       wake_up_bit(&inode->i_state, __I_NEW);
+       inode_wake_up_bit(inode, __I_NEW);
        spin_unlock(&inode->i_lock);
        iput(inode);
 }
@@ -2348,8 +2364,8 @@ EXPORT_SYMBOL(inode_needs_sync);
  */
 static void __wait_on_freeing_inode(struct inode *inode, bool is_inode_hash_locked)
 {
-       wait_queue_head_t *wq;
-       DEFINE_WAIT_BIT(wait, &inode->i_state, __I_NEW);
+       struct wait_bit_queue_entry wqe;
+       struct wait_queue_head *wq_head;
 
        /*
         * Handle racing against evict(), see that routine for more details.
@@ -2360,14 +2376,14 @@ static void __wait_on_freeing_inode(struct inode *inode, bool is_inode_hash_lock
                return;
        }
 
-       wq = bit_waitqueue(&inode->i_state, __I_NEW);
-       prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
+       wq_head = inode_bit_waitqueue(&wqe, inode, __I_NEW);
+       prepare_to_wait_event(wq_head, &wqe.wq_entry, TASK_UNINTERRUPTIBLE);
        spin_unlock(&inode->i_lock);
        rcu_read_unlock();
        if (is_inode_hash_locked)
                spin_unlock(&inode_hash_lock);
        schedule();
-       finish_wait(wq, &wait.wq_entry);
+       finish_wait(wq_head, &wqe.wq_entry);
        if (is_inode_hash_locked)
                spin_lock(&inode_hash_lock);
        rcu_read_lock();
index 56b85841ae4c11ac25cb7164192c94320172e103..8f651bb0a1a5d5da5d06069e8a985877e3750c6f 100644 (file)
@@ -200,7 +200,8 @@ void inode_io_list_del(struct inode *inode);
 /* writeback.h requires fs.h; it, too, is not included from here. */
 static inline void wait_on_inode(struct inode *inode)
 {
-       wait_on_bit(&inode->i_state, __I_NEW, TASK_UNINTERRUPTIBLE);
+       wait_var_event(inode_state_wait_address(inode, __I_NEW),
+                      !(READ_ONCE(inode->i_state) & I_NEW));
 }
 
 #ifdef CONFIG_CGROUP_WRITEBACK