// =============================
// 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<std::string, std::string> &metadata)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied())
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)
return res;
}
-
int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm,
- InodeRef *inp)
+ InodeRef *inp, const std::map<std::string, std::string> &metadata)
{
ldout(cct, 8) << "_mkdir(" << dir->ino << " " << name << ", 0" << oct
<< mode << dec << ", uid " << perm.uid()
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;
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);
int enumerate_layout(int fd, vector<ObjectExtent>& 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<std::string, std::string> &metadata={});
int rmsnap(const char *path, const char *name, const UserPerm& perm);
// Inode permission checking
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<std::string, std::string> &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);
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;