]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
src/mds: increment directory inode's change attr by one
authorRamana Raja <rraja@redhat.com>
Thu, 22 Sep 2022 15:41:50 +0000 (11:41 -0400)
committerRamana Raja <rraja@redhat.com>
Fri, 14 Oct 2022 23:25:40 +0000 (19:25 -0400)
... 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 <rraja@redhat.com>
src/mds/CInode.cc
src/mds/MDCache.cc

index 2617880e07b9169fd1fafbd9b6eb807ead7a837c..e286f24d940ee927b2359b6d7db947948651f7d5 100644 (file)
@@ -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)) {
index d3ae45aca6486fb415fb3590af1ddd698008b343..b2e77edff94852484a0152c1d2e27c36cad57fa2 100644 (file)
@@ -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