Commit 2c567af4 authored by Ira Weiny's avatar Ira Weiny Committed by Darrick J. Wong

fs: Introduce DCACHE_DONTCACHE

DCACHE_DONTCACHE indicates a dentry should not be cached on final
dput().

Also add a helper function to mark DCACHE_DONTCACHE on all dentries
pointing to a specific inode when that inode is being set I_DONTCACHE.

This facilitates dropping dentry references to inodes sooner which
require eviction to swap S_DAX mode.

Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarIra Weiny <ira.weiny@intel.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent dae2f8ed
...@@ -647,6 +647,10 @@ static inline bool retain_dentry(struct dentry *dentry) ...@@ -647,6 +647,10 @@ static inline bool retain_dentry(struct dentry *dentry)
if (dentry->d_op->d_delete(dentry)) if (dentry->d_op->d_delete(dentry))
return false; return false;
} }
if (unlikely(dentry->d_flags & DCACHE_DONTCACHE))
return false;
/* retain; LRU fodder */ /* retain; LRU fodder */
dentry->d_lockref.count--; dentry->d_lockref.count--;
if (unlikely(!(dentry->d_flags & DCACHE_LRU_LIST))) if (unlikely(!(dentry->d_flags & DCACHE_LRU_LIST)))
...@@ -656,6 +660,21 @@ static inline bool retain_dentry(struct dentry *dentry) ...@@ -656,6 +660,21 @@ static inline bool retain_dentry(struct dentry *dentry)
return true; return true;
} }
void d_mark_dontcache(struct inode *inode)
{
struct dentry *de;
spin_lock(&inode->i_lock);
hlist_for_each_entry(de, &inode->i_dentry, d_u.d_alias) {
spin_lock(&de->d_lock);
de->d_flags |= DCACHE_DONTCACHE;
spin_unlock(&de->d_lock);
}
inode->i_state |= I_DONTCACHE;
spin_unlock(&inode->i_lock);
}
EXPORT_SYMBOL(d_mark_dontcache);
/* /*
* Finish off a dentry we've decided to kill. * Finish off a dentry we've decided to kill.
* dentry->d_lock must be held, returns with it unlocked. * dentry->d_lock must be held, returns with it unlocked.
......
...@@ -561,7 +561,7 @@ xfs_iget_cache_miss( ...@@ -561,7 +561,7 @@ xfs_iget_cache_miss(
*/ */
iflags = XFS_INEW; iflags = XFS_INEW;
if (flags & XFS_IGET_DONTCACHE) if (flags & XFS_IGET_DONTCACHE)
VFS_I(ip)->i_state |= I_DONTCACHE; d_mark_dontcache(VFS_I(ip));
ip->i_udquot = NULL; ip->i_udquot = NULL;
ip->i_gdquot = NULL; ip->i_gdquot = NULL;
ip->i_pdquot = NULL; ip->i_pdquot = NULL;
......
...@@ -177,6 +177,8 @@ struct dentry_operations { ...@@ -177,6 +177,8 @@ struct dentry_operations {
#define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */ #define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */
#define DCACHE_DONTCACHE 0x00000080 /* Purge from memory on final dput() */
#define DCACHE_CANT_MOUNT 0x00000100 #define DCACHE_CANT_MOUNT 0x00000100
#define DCACHE_GENOCIDE 0x00000200 #define DCACHE_GENOCIDE 0x00000200
#define DCACHE_SHRINK_LIST 0x00000400 #define DCACHE_SHRINK_LIST 0x00000400
......
...@@ -3055,6 +3055,7 @@ static inline int generic_drop_inode(struct inode *inode) ...@@ -3055,6 +3055,7 @@ static inline int generic_drop_inode(struct inode *inode)
return !inode->i_nlink || inode_unhashed(inode) || return !inode->i_nlink || inode_unhashed(inode) ||
(inode->i_state & I_DONTCACHE); (inode->i_state & I_DONTCACHE);
} }
extern void d_mark_dontcache(struct inode *inode);
extern struct inode *ilookup5_nowait(struct super_block *sb, extern struct inode *ilookup5_nowait(struct super_block *sb,
unsigned long hashval, int (*test)(struct inode *, void *), unsigned long hashval, int (*test)(struct inode *, void *),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment