From: Ramana Raja Date: Thu, 22 Sep 2022 15:41:50 +0000 (-0400) Subject: src/mds: increment directory inode's change attr by one X-Git-Tag: v18.1.0~1000^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=05fdd6c800875c537966540933c8b13e08a2cb17;p=ceph.git 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 --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 2617880e07b9..e286f24d940e 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 d3ae45aca648..b2e77edff948 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