Unverified Commit c146a1f1 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11585 vfs: Don't evict inode under the inode lru traversing context

parents 7df4077a 8f1f1e94
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -486,6 +486,39 @@ static void inode_lru_list_del(struct inode *inode)
		this_cpu_dec(nr_unused);
}

static void inode_pin_lru_isolating(struct inode *inode)
{
	lockdep_assert_held(&inode->i_lock);
	WARN_ON(inode->i_state & (I_LRU_ISOLATING | I_FREEING | I_WILL_FREE));
	inode->i_state |= I_LRU_ISOLATING;
}

static void inode_unpin_lru_isolating(struct inode *inode)
{
	spin_lock(&inode->i_lock);
	WARN_ON(!(inode->i_state & I_LRU_ISOLATING));
	inode->i_state &= ~I_LRU_ISOLATING;
	smp_mb();
	wake_up_bit(&inode->i_state, __I_LRU_ISOLATING);
	spin_unlock(&inode->i_lock);
}

static void inode_wait_for_lru_isolating(struct inode *inode)
{
	spin_lock(&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;

		wqh = bit_waitqueue(&inode->i_state, __I_LRU_ISOLATING);
		spin_unlock(&inode->i_lock);
		__wait_on_bit(wqh, &wq, bit_wait, TASK_UNINTERRUPTIBLE);
		spin_lock(&inode->i_lock);
		WARN_ON(inode->i_state & I_LRU_ISOLATING);
	}
	spin_unlock(&inode->i_lock);
}

/**
 * inode_sb_list_add - add inode to the superblock list of inodes
 * @inode: inode to add
@@ -655,6 +688,8 @@ static void evict(struct inode *inode)

	inode_sb_list_del(inode);

	inode_wait_for_lru_isolating(inode);

	/*
	 * Wait for flusher thread to be done with the inode so that filesystem
	 * does not start destroying it while writeback is still running. Since
@@ -843,7 +878,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
	 * be under pressure before the cache inside the highmem zone.
	 */
	if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) {
		__iget(inode);
		inode_pin_lru_isolating(inode);
		spin_unlock(&inode->i_lock);
		spin_unlock(lru_lock);
		if (remove_inode_buffers(inode)) {
@@ -855,7 +890,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
				__count_vm_events(PGINODESTEAL, reap);
			mm_account_reclaimed_pages(reap);
		}
		iput(inode);
		inode_unpin_lru_isolating(inode);
		spin_lock(lru_lock);
		return LRU_RETRY;
	}
+5 −0
Original line number Diff line number Diff line
@@ -2334,6 +2334,9 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src,
 *
 * I_PINNING_FSCACHE_WB	Inode is pinning an fscache object for writeback.
 *
 * I_LRU_ISOLATING	Inode is pinned being isolated from LRU without holding
 *			i_count.
 *
 * Q: What is the difference between I_WILL_FREE and I_FREEING?
 */
#define I_DIRTY_SYNC		(1 << 0)
@@ -2357,6 +2360,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src,
#define I_DONTCACHE		(1 << 16)
#define I_SYNC_QUEUED		(1 << 17)
#define I_PINNING_FSCACHE_WB	(1 << 18)
#define __I_LRU_ISOLATING	19
#define I_LRU_ISOLATING		(1 << __I_LRU_ISOLATING)

#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)