]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
vfs: drop one lock trip in evict()
authorMateusz Guzik <mjguzik@gmail.com>
Tue, 13 Aug 2024 14:36:26 +0000 (16:36 +0200)
committerChristian Brauner <brauner@kernel.org>
Fri, 30 Aug 2024 06:22:38 +0000 (08:22 +0200)
Most commonly neither I_LRU_ISOLATING nor I_SYNC are set, but the stock
kernel takes a back-to-back relock trip to check for them.

It probably can be avoided altogether, but for now massage things back
to just one lock acquire.

Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Link: https://lore.kernel.org/r/20240813143626.1573445-1-mjguzik@gmail.com
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/fs-writeback.c
fs/inode.c

index 4451ecff37c4461ef8dc3a74ee5affbedf6ca0e2..1a5006329f6f03bd0f8c6fb6cb21aa46e34f44c3 100644 (file)
@@ -1510,13 +1510,12 @@ static int write_inode(struct inode *inode, struct writeback_control *wbc)
  * Wait for writeback on an inode to complete. Called with i_lock held.
  * Caller must make sure inode cannot go away when we drop i_lock.
  */
-static void __inode_wait_for_writeback(struct inode *inode)
-       __releases(inode->i_lock)
-       __acquires(inode->i_lock)
+void inode_wait_for_writeback(struct inode *inode)
 {
        DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC);
        wait_queue_head_t *wqh;
 
+       lockdep_assert_held(&inode->i_lock);
        wqh = bit_waitqueue(&inode->i_state, __I_SYNC);
        while (inode->i_state & I_SYNC) {
                spin_unlock(&inode->i_lock);
@@ -1526,16 +1525,6 @@ static void __inode_wait_for_writeback(struct inode *inode)
        }
 }
 
-/*
- * Wait for writeback on an inode to complete. Caller must have inode pinned.
- */
-void inode_wait_for_writeback(struct inode *inode)
-{
-       spin_lock(&inode->i_lock);
-       __inode_wait_for_writeback(inode);
-       spin_unlock(&inode->i_lock);
-}
-
 /*
  * Sleep until I_SYNC is cleared. This function must be called with i_lock
  * held and drops it. It is aimed for callers not holding any inode reference
@@ -1757,7 +1746,7 @@ static int writeback_single_inode(struct inode *inode,
                 */
                if (wbc->sync_mode != WB_SYNC_ALL)
                        goto out;
-               __inode_wait_for_writeback(inode);
+               inode_wait_for_writeback(inode);
        }
        WARN_ON(inode->i_state & I_SYNC);
        /*
index 248a131a02c3b2a72cecb9de4bca7a2c0d386d46..154f8689457f0c4cfda1ea002ebf5c1f4036fb97 100644 (file)
@@ -507,7 +507,7 @@ static void inode_unpin_lru_isolating(struct inode *inode)
 
 static void inode_wait_for_lru_isolating(struct inode *inode)
 {
-       spin_lock(&inode->i_lock);
+       lockdep_assert_held(&inode->i_lock);
        if (inode->i_state & I_LRU_ISOLATING) {
                DEFINE_WAIT_BIT(wq, &inode->i_state, __I_LRU_ISOLATING);
                wait_queue_head_t *wqh;
@@ -518,7 +518,6 @@ static void inode_wait_for_lru_isolating(struct inode *inode)
                spin_lock(&inode->i_lock);
                WARN_ON(inode->i_state & I_LRU_ISOLATING);
        }
-       spin_unlock(&inode->i_lock);
 }
 
 /**
@@ -690,6 +689,7 @@ static void evict(struct inode *inode)
 
        inode_sb_list_del(inode);
 
+       spin_lock(&inode->i_lock);
        inode_wait_for_lru_isolating(inode);
 
        /*
@@ -699,6 +699,7 @@ static void evict(struct inode *inode)
         * the inode.  We just have to wait for running writeback to finish.
         */
        inode_wait_for_writeback(inode);
+       spin_unlock(&inode->i_lock);
 
        if (op->evict_inode) {
                op->evict_inode(inode);