On 2020/8/27 14:37, Dave Chinner wrote: > On Fri, Aug 21, 2020 at 09:59:53AM +0800, Hao Li wrote: >> Currently, DCACHE_REFERENCED prevents the dentry with DCACHE_DONTCACHE >> set from being killed, so the corresponding inode can't be evicted. If >> the DAX policy of an inode is changed, we can't make policy changing >> take effects unless dropping caches manually. >> >> This patch fixes this problem and flushes the inode to disk to prepare >> for evicting it. >> >> Signed-off-by: Hao Li <lihao2018.fnst@xxxxxxxxxxxxxx> >> --- >> fs/dcache.c | 3 ++- >> fs/inode.c | 2 +- >> 2 files changed, 3 insertions(+), 2 deletions(-) >> >> diff --git a/fs/dcache.c b/fs/dcache.c >> index ea0485861d93..486c7409dc82 100644 >> --- a/fs/dcache.c >> +++ b/fs/dcache.c >> @@ -796,7 +796,8 @@ static inline bool fast_dput(struct dentry *dentry) >> */ >> smp_rmb(); >> d_flags = READ_ONCE(dentry->d_flags); >> - d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED; >> + d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED >> + | DCACHE_DONTCACHE; > Seems reasonable, but you need to update the comment above as to > how this flag fits into this code.... Yes. I will change it. Thanks. > >> /* Nothing to do? Dropping the reference was all we needed? */ >> if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) >> diff --git a/fs/inode.c b/fs/inode.c >> index 72c4c347afb7..5218a8aebd7f 100644 >> --- a/fs/inode.c >> +++ b/fs/inode.c >> @@ -1632,7 +1632,7 @@ static void iput_final(struct inode *inode) >> } >> >> state = inode->i_state; >> - if (!drop) { >> + if (!drop || (drop && (inode->i_state & I_DONTCACHE))) { >> WRITE_ONCE(inode->i_state, state | I_WILL_FREE); >> spin_unlock(&inode->i_lock); > What's this supposed to do? We'll only get here with drop set if the > filesystem is mounting or unmounting. The variable drop will also be set to True if I_DONTCACHE is set on inode->i_state. Although mounting/unmounting will set the drop variable, it won't set I_DONTCACHE if I understand correctly. As a result, drop && (inode->i_state & I_DONTCACHE) will filter out mounting/unmounting. > In either case, why does > having I_DONTCACHE set require the inode to be written back here > before it is evicted from the cache? Mounting/unmounting won't execute the code snippet which is in that if statement, as I have explained above. However, If I_DONTCACHE is set, we have to execute this snippet to write back inode. I_DONTCACHE is set in d_mark_dontcache() which will be called in two situations: 1. DAX policy is changed. 2. The inode is read through bulkstat in XFS. See commit 5132ba8f2b77 ("xfs: don't cache inodes read through bulkstat") for more details. For the first case, we have to write back the inode together with its dirty pages before evicting. For the second case, I think it's also necessary to write back inode before evicting. Thanks, Hao Li > > Cheers, > > Dave.