From 05fdd6c800875c537966540933c8b13e08a2cb17 Mon Sep 17 00:00:00 2001 From: Ramana Raja Date: Thu, 22 Sep 2022 11:41:50 -0400 Subject: [PATCH] src/mds: increment directory inode's change attr by one ... whenever the mtime or ctime of the directory inode is modified. In CephFS subvolume clones exported using NFS-Ganesha, newly created files using `touch` were not being listed. It was identified that the create request sent to the Ceph MDS via NFS-Ganesha's libcephfs client modified the mtime and ctime of the parent directory, but did not modify the change_attr of the parent directory. Since the NFS client didn't see a modification of the change attribute in the reply, it didn't invalidate its readdir cache. The subsequent directory `ls` was satisfied from the NFS client's stale readdir cache. Whenever parent directory inode's mtime was modified in MDCache::predirty_journal_parents(), the parent inode's change_attr was set to its dirstat->change_attr. The parent inode's dirstat->change_attr doesn't track changes to parent's *ctime only* changes such as setattr, setvxattr, etc. on the parent directory. See commit 0d441dcd6af553d11d6be6df56d577c5659904a0 for more details. This caused the directory inode's change_attr to not be updated when an operation to change only its ctime was followed by an operation to change its mtime and ctime. Fix this by making changes to MDCache::predirty_journal_parents() and CInode::finish_scatter_gather_update() to increment the directory inode's change_attr by one instead of setting it to its dirstat->change_attr. Fixes: https://tracker.ceph.com/issues/57210 Signed-off-by: Ramana Raja --- src/mds/CInode.cc | 3 ++- src/mds/MDCache.cc | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 2617880e07b91..e286f24d940ee 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -2543,7 +2543,8 @@ void CInode::finish_scatter_gather_update(int type, MutationRef& mut) if (touched_mtime) pi->mtime = pi->ctime = pi->dirstat.mtime; if (touched_chattr) - pi->change_attr = pi->dirstat.change_attr; + pi->change_attr++; + dout(20) << " final dirstat " << pi->dirstat << dendl; if (dirstat_valid && !dirstat.same_sums(pi->dirstat)) { diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index d3ae45aca6486..b2e77edff9485 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -2162,7 +2162,7 @@ void MDCache::predirty_journal_parents(MutationRef mut, EMetaBlob *blob, if (do_parent_mtime) { pf->fragstat.mtime = mut->get_op_stamp(); pf->fragstat.change_attr++; - dout(10) << "predirty_journal_parents bumping change_attr to " << pf->fragstat.change_attr << " on " << parent << dendl; + dout(10) << "predirty_journal_parents bumping fragstat change_attr to " << pf->fragstat.change_attr << " on " << parent << dendl; if (pf->fragstat.mtime > pf->rstat.rctime) { dout(10) << "predirty_journal_parents updating mtime on " << *parent << dendl; pf->rstat.rctime = pf->fragstat.mtime; @@ -2288,7 +2288,7 @@ void MDCache::predirty_journal_parents(MutationRef mut, EMetaBlob *blob, if (touched_mtime) pi.inode->mtime = pi.inode->ctime = pi.inode->dirstat.mtime; if (touched_chattr) - pi.inode->change_attr = pi.inode->dirstat.change_attr; + pi.inode->change_attr++; dout(20) << "predirty_journal_parents gives " << pi.inode->dirstat << " on " << *pin << dendl; if (parent->get_frag() == frag_t()) { // i.e., we are the only frag -- 2.39.5