Commit 57510c58 authored by Mateusz Guzik's avatar Mateusz Guzik Committed by Christian Brauner
Browse files

vfs: drop one lock trip in evict()



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: default avatarMateusz Guzik <mjguzik@gmail.com>
Link: https://lore.kernel.org/r/20240813143626.1573445-1-mjguzik@gmail.com


Reviewed-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 3a987b88
Loading
Loading
Loading
Loading
+3 −14
Original line number Diff line number Diff line
@@ -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);
	/*
+3 −2
Original line number Diff line number Diff line
@@ -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);