From: Venky Shankar Date: Mon, 19 Oct 2020 09:13:01 +0000 (-0400) Subject: mds: include snap metadata on-disk on snapshot creation X-Git-Tag: v17.0.0~216^2~4 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=bee70498a55965769d9136d876dc46467b755d02;p=ceph-ci.git mds: include snap metadata on-disk on snapshot creation Signed-off-by: Venky Shankar --- diff --git a/src/client/Client.cc b/src/client/Client.cc index dd1ca8f7a7b..ec109470a0d 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -11053,7 +11053,8 @@ int Client::lazyio_synchronize(int fd, loff_t offset, size_t count) // ============================= // snaps -int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm) +int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm, + mode_t mode, const std::map &metadata) { RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); if (!mref_reader.is_state_satisfied()) @@ -11072,7 +11073,7 @@ int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm) return r; } Inode *snapdir = open_snapdir(in.get()); - return _mkdir(snapdir, name, 0, perm); + return _mkdir(snapdir, name, mode, perm, nullptr, metadata); } int Client::rmsnap(const char *relpath, const char *name, const UserPerm& perms) @@ -12798,9 +12799,8 @@ int Client::_create(Inode *dir, const char *name, int flags, mode_t mode, return res; } - int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm, - InodeRef *inp) + InodeRef *inp, const std::map &metadata) { ldout(cct, 8) << "_mkdir(" << dir->ino << " " << name << ", 0" << oct << mode << dec << ", uid " << perm.uid() @@ -12815,7 +12815,9 @@ int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& pe if (is_quota_files_exceeded(dir, perm)) { return -EDQUOT; } - MetaRequest *req = new MetaRequest(dir->snapid == CEPH_SNAPDIR ? + + bool is_snap_op = dir->snapid == CEPH_SNAPDIR; + MetaRequest *req = new MetaRequest(is_snap_op ? CEPH_MDS_OP_MKSNAP : CEPH_MDS_OP_MKDIR); filepath path; @@ -12827,13 +12829,23 @@ int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& pe req->dentry_unless = CEPH_CAP_FILE_EXCL; mode |= S_IFDIR; - bufferlist xattrs_bl; - int res = _posix_acl_create(dir, &mode, xattrs_bl, perm); + bufferlist bl; + int res = _posix_acl_create(dir, &mode, bl, perm); if (res < 0) goto fail; req->head.args.mkdir.mode = mode; - if (xattrs_bl.length() > 0) - req->set_data(xattrs_bl); + if (is_snap_op) { + SnapPayload payload; + // clear the bufferlist that may have been populated by the call + // to _posix_acl_create(). MDS mksnap does not make use of it. + // So, reuse it to pass metadata payload. + bl.clear(); + payload.metadata = metadata; + encode(payload, bl); + } + if (bl.length() > 0) { + req->set_data(bl); + } Dentry *de; res = get_or_create(dir, name, &de); diff --git a/src/client/Client.h b/src/client/Client.h index c61c090485e..a2f3a021aed 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -466,7 +466,8 @@ public: int enumerate_layout(int fd, vector& result, loff_t length, loff_t offset); - int mksnap(const char *path, const char *name, const UserPerm& perm); + int mksnap(const char *path, const char *name, const UserPerm& perm, + mode_t mode=0, const std::map &metadata={}); int rmsnap(const char *path, const char *name, const UserPerm& perm); // Inode permission checking @@ -1215,7 +1216,7 @@ private: int _unlink(Inode *dir, const char *name, const UserPerm& perm); int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, const UserPerm& perm); int _mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm, - InodeRef *inp = 0); + InodeRef *inp = 0, const std::map &metadata={}); int _rmdir(Inode *dir, const char *name, const UserPerm& perms); int _symlink(Inode *dir, const char *name, const char *target, const UserPerm& perms, InodeRef *inp = 0); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index cbc31013f1f..7b25e4ff981 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -10226,12 +10226,25 @@ void Server::handle_client_mksnap(MDRequestRef& mdr) ceph_assert(mds->snapclient->get_cached_version() >= stid); + SnapPayload payload; + if (req->get_data().length()) { + try { + auto iter = req->get_data().cbegin(); + decode(payload, iter); + } catch (const ceph::buffer::error &e) { + // backward compat -- client sends xattr bufferlist. however, + // that is not used anywhere -- so (log and) ignore. + dout(20) << ": no metadata in payload (old client?)" << dendl; + } + } + // journal SnapInfo info; info.ino = diri->ino(); info.snapid = snapid; info.name = snapname; info.stamp = mdr->get_op_stamp(); + info.metadata = payload.metadata; auto pi = diri->project_inode(mdr, false, true); pi.inode->ctime = info.stamp; diff --git a/src/messages/MClientRequest.h b/src/messages/MClientRequest.h index a1abb8688af..9517126fc68 100644 --- a/src/messages/MClientRequest.h +++ b/src/messages/MClientRequest.h @@ -45,6 +45,23 @@ #include #include +struct SnapPayload { + std::map metadata; + + void encode(ceph::buffer::list &bl) const { + ENCODE_START(1, 1, bl); + encode(metadata, bl); + ENCODE_FINISH(bl); + } + + void decode(ceph::buffer::list::const_iterator &iter) { + DECODE_START(1, iter); + decode(metadata, iter); + DECODE_FINISH(iter); + } +}; + +WRITE_CLASS_ENCODER(SnapPayload) // metadata ops.