Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+31 -6
+19
fs/dcache.c
··· 647 647 if (dentry->d_op->d_delete(dentry)) 648 648 return false; 649 649 } 650 + 651 + if (unlikely(dentry->d_flags & DCACHE_DONTCACHE)) 652 + return false; 653 + 650 654 /* retain; LRU fodder */ 651 655 dentry->d_lockref.count--; 652 656 if (unlikely(!(dentry->d_flags & DCACHE_LRU_LIST))) ··· 659 655 dentry->d_flags |= DCACHE_REFERENCED; 660 656 return true; 661 657 } 658 + 659 + void d_mark_dontcache(struct inode *inode) 660 + { 661 + struct dentry *de; 662 + 663 + spin_lock(&inode->i_lock); 664 + hlist_for_each_entry(de, &inode->i_dentry, d_u.d_alias) { 665 + spin_lock(&de->d_lock); 666 + de->d_flags |= DCACHE_DONTCACHE; 667 + spin_unlock(&de->d_lock); 668 + } 669 + inode->i_state |= I_DONTCACHE; 670 + spin_unlock(&inode->i_lock); 671 + } 672 + EXPORT_SYMBOL(d_mark_dontcache); 662 673 663 674 /* 664 675 * Finish off a dentry we've decided to kill.
+2 -2
fs/xfs/xfs_icache.c
··· 479 479 xfs_ilock(ip, lock_flags); 480 480 481 481 if (!(flags & XFS_IGET_INCORE)) 482 - xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE); 482 + xfs_iflags_clear(ip, XFS_ISTALE); 483 483 XFS_STATS_INC(mp, xs_ig_found); 484 484 485 485 return 0; ··· 585 585 */ 586 586 iflags = XFS_INEW; 587 587 if (flags & XFS_IGET_DONTCACHE) 588 - iflags |= XFS_IDONTCACHE; 588 + d_mark_dontcache(VFS_I(ip)); 589 589 ip->i_udquot = NULL; 590 590 ip->i_gdquot = NULL; 591 591 ip->i_pdquot = NULL;
+1 -2
fs/xfs/xfs_inode.h
··· 215 215 #define XFS_IFLOCK (1 << __XFS_IFLOCK_BIT) 216 216 #define __XFS_IPINNED_BIT 8 /* wakeup key for zero pin count */ 217 217 #define XFS_IPINNED (1 << __XFS_IPINNED_BIT) 218 - #define XFS_IDONTCACHE (1 << 9) /* don't cache the inode long term */ 219 - #define XFS_IEOFBLOCKS (1 << 10)/* has the preallocblocks tag set */ 218 + #define XFS_IEOFBLOCKS (1 << 9) /* has the preallocblocks tag set */ 220 219 /* 221 220 * If this unlinked inode is in the middle of recovery, don't let drop_inode 222 221 * truncate and free the inode. This can happen if we iget the inode during
+1 -1
fs/xfs/xfs_super.c
··· 737 737 return 0; 738 738 } 739 739 740 - return generic_drop_inode(inode) || (ip->i_flags & XFS_IDONTCACHE); 740 + return generic_drop_inode(inode); 741 741 } 742 742 743 743 static void
+2
include/linux/dcache.h
··· 177 177 178 178 #define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */ 179 179 180 + #define DCACHE_DONTCACHE 0x00000080 /* Purge from memory on final dput() */ 181 + 180 182 #define DCACHE_CANT_MOUNT 0x00000100 181 183 #define DCACHE_GENOCIDE 0x00000200 182 184 #define DCACHE_SHRINK_LIST 0x00000400
+6 -1
include/linux/fs.h
··· 2166 2166 * 2167 2167 * I_CREATING New object's inode in the middle of setting up. 2168 2168 * 2169 + * I_DONTCACHE Evict inode as soon as it is not used anymore. 2170 + * 2169 2171 * Q: What is the difference between I_WILL_FREE and I_FREEING? 2170 2172 */ 2171 2173 #define I_DIRTY_SYNC (1 << 0) ··· 2190 2188 #define I_WB_SWITCH (1 << 13) 2191 2189 #define I_OVL_INUSE (1 << 14) 2192 2190 #define I_CREATING (1 << 15) 2191 + #define I_DONTCACHE (1 << 16) 2193 2192 2194 2193 #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) 2195 2194 #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) ··· 3071 3068 extern int generic_delete_inode(struct inode *inode); 3072 3069 static inline int generic_drop_inode(struct inode *inode) 3073 3070 { 3074 - return !inode->i_nlink || inode_unhashed(inode); 3071 + return !inode->i_nlink || inode_unhashed(inode) || 3072 + (inode->i_state & I_DONTCACHE); 3075 3073 } 3074 + extern void d_mark_dontcache(struct inode *inode); 3076 3075 3077 3076 extern struct inode *ilookup5_nowait(struct super_block *sb, 3078 3077 unsigned long hashval, int (*test)(struct inode *, void *),