From 794c74cebd9ecbd82e7431f424af8f631b75de89 Mon Sep 17 00:00:00 2001 From: Venky Shankar Date: Mon, 19 Sep 2022 07:38:36 -0400 Subject: [PATCH] client: refresh snapdir attrs on parent inode updation Snapdir attrs (ui, gid, etc..) are set its respective parent attributes, however, those are never updated when the attributes of the parent inode get updated. There seems to be no reason to no to update snapdir attributes. This change also updates POSIX ACLs. Fixes: http://tracker.ceph.com/issues/57084 Signed-off-by: Venky Shankar --- src/client/Client.cc | 67 +++++++++++++++++++++++++++++--------------- src/client/Client.h | 1 + 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 997f147fec7f8..2a4ae51da5307 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -1046,6 +1046,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, issued |= in->caps_dirty(); int new_issued = ~issued & (int)st->cap.caps; + bool need_snapdir_attr_refresh = false; if ((new_version || (new_issued & CEPH_CAP_AUTH_SHARED)) && !(issued & CEPH_CAP_AUTH_EXCL)) { in->mode = st->mode; @@ -1055,6 +1056,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, in->snap_btime = st->snap_btime; in->snap_metadata = st->snap_metadata; in->fscrypt_auth = st->fscrypt_auth; + need_snapdir_attr_refresh = true; } if ((new_version || (new_issued & CEPH_CAP_LINK_SHARED)) && @@ -1063,6 +1065,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, } if (new_version || (new_issued & CEPH_CAP_ANY_RD)) { + need_snapdir_attr_refresh = true; update_inode_file_time(in, issued, st->time_warp_seq, st->ctime, st->mtime, st->atime); } @@ -1100,6 +1103,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, auto p = st->xattrbl.cbegin(); decode(in->xattrs, p); in->xattr_version = st->xattr_version; + need_snapdir_attr_refresh = true; } if (st->inline_version > in->inline_version) { @@ -1152,6 +1156,13 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, in->snap_caps |= st->cap.caps; } + if (need_snapdir_attr_refresh && in->is_dir() && in->snapid == CEPH_NOSNAP) { + vinodeno_t vino(in->ino, CEPH_SNAPDIR); + if (inode_map.count(vino)) { + refresh_snapdir_attrs(inode_map[vino], in); + } + } + return in; } @@ -7994,6 +8005,12 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, if (!mask) { in->change_attr++; + if (in->is_dir() && in->snapid == CEPH_NOSNAP) { + vinodeno_t vino(in->ino, CEPH_SNAPDIR); + if (inode_map.count(vino)) { + refresh_snapdir_attrs(inode_map[vino], in); + } + } return 0; } @@ -11914,34 +11931,40 @@ int Client::get_caps_issued(const char *path, const UserPerm& perms) // ========================================= // low level +void Client::refresh_snapdir_attrs(Inode *in, Inode *diri) { + ldout(cct, 10) << __func__ << ": snapdir inode=" << *in + << ", inode=" << *diri << dendl; + in->ino = diri->ino; + in->snapid = CEPH_SNAPDIR; + in->mode = diri->mode; + in->uid = diri->uid; + in->gid = diri->gid; + in->nlink = 1; + in->mtime = diri->mtime; + in->ctime = diri->ctime; + in->btime = diri->btime; + in->atime = diri->atime; + in->size = diri->size; + in->change_attr = diri->change_attr; + + in->dirfragtree.clear(); + in->snapdir_parent = diri; + // copy posix acls to snapshotted inode + in->xattrs.clear(); + for (auto &[xattr_key, xattr_value] : diri->xattrs) { + if (xattr_key.rfind("system.", 0) == 0) { + in->xattrs[xattr_key] = xattr_value; + } + } +} + Inode *Client::open_snapdir(Inode *diri) { Inode *in; vinodeno_t vino(diri->ino, CEPH_SNAPDIR); if (!inode_map.count(vino)) { in = new Inode(this, vino, &diri->layout); - - in->ino = diri->ino; - in->snapid = CEPH_SNAPDIR; - in->mode = diri->mode; - in->uid = diri->uid; - in->gid = diri->gid; - in->nlink = 1; - in->mtime = diri->mtime; - in->ctime = diri->ctime; - in->btime = diri->btime; - in->atime = diri->atime; - in->size = diri->size; - in->change_attr = diri->change_attr; - - in->dirfragtree.clear(); - in->snapdir_parent = diri; - // copy posix acls to snapshotted inode - for (auto &[xattr_key, xattr_value] : diri->xattrs) { - if (xattr_key.rfind("system.", 0) == 0) { - in->xattrs[xattr_key] = xattr_value; - } - } + refresh_snapdir_attrs(in, diri); diri->flags |= I_SNAPDIR_OPEN; inode_map[vino] = in; if (use_faked_inos()) diff --git a/src/client/Client.h b/src/client/Client.h index a1e63d7d5b6d9..6c1132f75883e 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -985,6 +985,7 @@ protected: void update_snap_trace(const bufferlist& bl, SnapRealm **realm_ret, bool must_flush=true); void invalidate_snaprealm_and_children(SnapRealm *realm); + void refresh_snapdir_attrs(Inode *in, Inode *diri); Inode *open_snapdir(Inode *diri); int get_fd() { -- 2.39.5