Commit 8eeae5ba authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'vfs-5.8-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull DAX updates part two from Darrick Wong:
 "This time around, we're hoisting the DONTCACHE flag from XFS into the
  VFS so that we can make the incore DAX mode changes become effective
  sooner.

  We can't change the file data access mode on a live inode because we
  don't have a safe way to change the file ops pointers. The incore
  state change becomes effective at inode loading time, which can happen
  if the inode is evicted. Therefore, we're making it so that
  filesystems can ask the VFS to evict the inode as soon as the last
  holder drops.

  The per-fs changes to make this call this will be in subsequent pull
  requests from Ted and myself.

  Summary:

   - Introduce DONTCACHE flags for dentries and inodes. This hint will
     cause the VFS to drop the associated objects immediately after the
     last put, so that we can change the file access mode (DAX or page
     cache) on the fly"

* tag 'vfs-5.8-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  fs: Introduce DCACHE_DONTCACHE
  fs: Lift XFS_IDONTCACHE to the VFS layer
parents 96ed320d 2c567af4
...@@ -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.
......
...@@ -479,7 +479,7 @@ xfs_iget_cache_hit( ...@@ -479,7 +479,7 @@ xfs_iget_cache_hit(
xfs_ilock(ip, lock_flags); xfs_ilock(ip, lock_flags);
if (!(flags & XFS_IGET_INCORE)) if (!(flags & XFS_IGET_INCORE))
xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE); xfs_iflags_clear(ip, XFS_ISTALE);
XFS_STATS_INC(mp, xs_ig_found); XFS_STATS_INC(mp, xs_ig_found);
return 0; return 0;
...@@ -585,7 +585,7 @@ xfs_iget_cache_miss( ...@@ -585,7 +585,7 @@ xfs_iget_cache_miss(
*/ */
iflags = XFS_INEW; iflags = XFS_INEW;
if (flags & XFS_IGET_DONTCACHE) if (flags & XFS_IGET_DONTCACHE)
iflags |= XFS_IDONTCACHE; 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;
......
...@@ -215,8 +215,7 @@ static inline bool xfs_inode_has_cow_data(struct xfs_inode *ip) ...@@ -215,8 +215,7 @@ static inline bool xfs_inode_has_cow_data(struct xfs_inode *ip)
#define XFS_IFLOCK (1 << __XFS_IFLOCK_BIT) #define XFS_IFLOCK (1 << __XFS_IFLOCK_BIT)
#define __XFS_IPINNED_BIT 8 /* wakeup key for zero pin count */ #define __XFS_IPINNED_BIT 8 /* wakeup key for zero pin count */
#define XFS_IPINNED (1 << __XFS_IPINNED_BIT) #define XFS_IPINNED (1 << __XFS_IPINNED_BIT)
#define XFS_IDONTCACHE (1 << 9) /* don't cache the inode long term */ #define XFS_IEOFBLOCKS (1 << 9) /* has the preallocblocks tag set */
#define XFS_IEOFBLOCKS (1 << 10)/* has the preallocblocks tag set */
/* /*
* If this unlinked inode is in the middle of recovery, don't let drop_inode * If this unlinked inode is in the middle of recovery, don't let drop_inode
* truncate and free the inode. This can happen if we iget the inode during * truncate and free the inode. This can happen if we iget the inode during
......
...@@ -737,7 +737,7 @@ xfs_fs_drop_inode( ...@@ -737,7 +737,7 @@ xfs_fs_drop_inode(
return 0; return 0;
} }
return generic_drop_inode(inode) || (ip->i_flags & XFS_IDONTCACHE); return generic_drop_inode(inode);
} }
static void static void
......
...@@ -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
......
...@@ -2166,6 +2166,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, ...@@ -2166,6 +2166,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src,
* *
* I_CREATING New object's inode in the middle of setting up. * I_CREATING New object's inode in the middle of setting up.
* *
* I_DONTCACHE Evict inode as soon as it is not used anymore.
*
* Q: What is the difference between I_WILL_FREE and I_FREEING? * Q: What is the difference between I_WILL_FREE and I_FREEING?
*/ */
#define I_DIRTY_SYNC (1 << 0) #define I_DIRTY_SYNC (1 << 0)
...@@ -2188,6 +2190,7 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, ...@@ -2188,6 +2190,7 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src,
#define I_WB_SWITCH (1 << 13) #define I_WB_SWITCH (1 << 13)
#define I_OVL_INUSE (1 << 14) #define I_OVL_INUSE (1 << 14)
#define I_CREATING (1 << 15) #define I_CREATING (1 << 15)
#define I_DONTCACHE (1 << 16)
#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
...@@ -3068,8 +3071,10 @@ extern int inode_needs_sync(struct inode *inode); ...@@ -3068,8 +3071,10 @@ extern int inode_needs_sync(struct inode *inode);
extern int generic_delete_inode(struct inode *inode); extern int generic_delete_inode(struct inode *inode);
static inline int generic_drop_inode(struct inode *inode) 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);
} }
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