req->set_filepath2(request->get_filepath2());
req->set_alternate_name(request->alternate_name);
req->set_data(request->data);
+ req->fscrypt_auth = request->fscrypt_auth;
+ req->fscrypt_file = request->fscrypt_file;
req->set_retry_attempt(request->retry_attempt++);
req->head.num_fwd = request->num_fwd;
const gid_t *_gids;
m->btime = in->btime;
m->time_warp_seq = in->time_warp_seq;
m->change_attr = in->change_attr;
+ m->fscrypt_auth = in->fscrypt_auth;
+ m->fscrypt_file = in->fscrypt_file;
if (!(flags & MClientCaps::FLAG_PENDING_CAPSNAP) &&
!in->cap_snaps.empty() &&
}
int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask,
- const UserPerm& perms, InodeRef *inp)
+ const UserPerm& perms, InodeRef *inp,
+ std::vector<uint8_t>* aux)
{
int issued = in->caps_issued();
union ceph_mds_request_args args;
bool kill_sguid = false;
int inode_drop = 0;
+ size_t auxsize = 0;
+
+ if (aux)
+ auxsize = aux->size();
ldout(cct, 10) << __func__ << " mask " << mask << " issued " <<
- ccap_string(issued) << dendl;
+ ccap_string(issued) << " aux size " << auxsize << dendl;
if (in->snapid != CEPH_NOSNAP) {
return -CEPHFS_EROFS;
return -CEPHFS_EDQUOT;
}
+ // Can't set fscrypt_auth and file at the same time!
+ if ((mask & (CEPH_SETATTR_FSCRYPT_AUTH|CEPH_SETATTR_FSCRYPT_FILE)) ==
+ (CEPH_SETATTR_FSCRYPT_AUTH|CEPH_SETATTR_FSCRYPT_FILE))
+ return -CEPHFS_EINVAL;
+
+ if (!aux && (mask & (CEPH_SETATTR_FSCRYPT_AUTH|CEPH_SETATTR_FSCRYPT_FILE)))
+ return -CEPHFS_EINVAL;
+
memset(&args, 0, sizeof(args));
// make the change locally?
}
}
+ if (mask & CEPH_SETATTR_FSCRYPT_AUTH) {
+ ldout(cct,10) << "resetting cached fscrypt_auth field. size now "
+ << in->fscrypt_auth.size() << dendl;
+
+ if (in->caps_issued_mask(CEPH_CAP_AUTH_EXCL)) {
+ in->ctime = ceph_clock_now();
+ in->cap_dirtier_uid = perms.uid();
+ in->cap_dirtier_gid = perms.gid();
+ in->fscrypt_auth = *aux;
+ in->mark_caps_dirty(CEPH_CAP_AUTH_EXCL);
+ mask &= ~CEPH_SETATTR_FSCRYPT_AUTH;
+ } else if (!in->caps_issued_mask(CEPH_CAP_AUTH_SHARED) ||
+ in->fscrypt_auth != *aux) {
+ inode_drop |= CEPH_CAP_AUTH_SHARED;
+ } else {
+ mask &= ~CEPH_SETATTR_FSCRYPT_AUTH;
+ }
+ }
+
if (mask & CEPH_SETATTR_SIZE) {
if ((uint64_t)stx->stx_size >= mdsmap->get_max_filesize()) {
//too big!
}
}
+ if (mask & CEPH_SETATTR_FSCRYPT_FILE) {
+ ldout(cct,10) << "resetting cached fscrypt_file field. size now "
+ << in->fscrypt_file.size() << dendl;
+
+ if (in->caps_issued_mask(CEPH_CAP_FILE_EXCL)) {
+ in->ctime = ceph_clock_now();
+ in->cap_dirtier_uid = perms.uid();
+ in->cap_dirtier_gid = perms.gid();
+ in->fscrypt_file = *aux;
+ in->mark_caps_dirty(CEPH_CAP_FILE_EXCL);
+ mask &= ~CEPH_SETATTR_FSCRYPT_FILE;
+ } else if (!in->caps_issued_mask(CEPH_CAP_FILE_SHARED) ||
+ in->fscrypt_file != *aux) {
+ inode_drop |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
+ } else {
+ mask &= ~CEPH_SETATTR_FSCRYPT_FILE;
+ }
+ }
+
if (mask & CEPH_SETATTR_MTIME) {
if (in->caps_issued_mask(CEPH_CAP_FILE_EXCL)) {
in->mtime = utime_t(stx->stx_mtime);
req->head.args = args;
req->inode_drop = inode_drop;
+ if (mask & CEPH_SETATTR_FSCRYPT_AUTH) {
+ req->fscrypt_auth = *aux;
+ } else if (mask & CEPH_SETATTR_FSCRYPT_FILE) {
+ req->fscrypt_file = *aux;
+ }
req->head.args.setattr.mask = mask;
req->regetattr_mask = mask;
if (new_mode != in->mode) {
struct ceph_statx stx;
stx.stx_mode = new_mode;
- ret = _do_setattr(in, &stx, CEPH_SETATTR_MODE, perms, NULL);
+ ret = _do_setattr(in, &stx, CEPH_SETATTR_MODE, perms, nullptr);
if (ret < 0)
return ret;
}
if (vxattr) {
if (vxattr->readonly)
return -CEPHFS_EOPNOTSUPP;
+ if (vxattr->setxattr_cb)
+ return (this->*(vxattr->setxattr_cb))(in, value, size, perms);
if (vxattr->name.compare(0, 10, "ceph.quota") == 0 && value)
check_realm = true;
}
return _removexattr(in, name, perms);
}
+bool Client::_vxattrcb_fscrypt_auth_exists(Inode *in)
+{
+ bool exists = !in->fscrypt_auth.empty();
+
+ ldout(cct, 10) << "fscrypt_auth exists " << exists << dendl;
+ return exists;
+}
+
+size_t Client::_vxattrcb_fscrypt_auth(Inode *in, char *val, size_t size)
+{
+ size_t count = in->fscrypt_auth.size();
+
+ if (count <= size)
+ memcpy(val, in->fscrypt_auth.data(), count);
+ return count;
+}
+
+int Client::_vxattrcb_fscrypt_auth_set(Inode *in, const void *val, size_t size,
+ const UserPerm& perms)
+{
+ struct ceph_statx stx = { 0 };
+ std::vector<uint8_t> aux;
+
+ aux.resize(size);
+ memcpy(aux.data(), val, size);
+
+ return _do_setattr(in, &stx, CEPH_SETATTR_FSCRYPT_AUTH, perms, nullptr, &aux);
+}
+
+bool Client::_vxattrcb_fscrypt_file_exists(Inode *in)
+{
+ return !in->fscrypt_file.empty();
+}
+
+size_t Client::_vxattrcb_fscrypt_file(Inode *in, char *val, size_t size)
+{
+ size_t count = in->fscrypt_file.size();
+
+ if (count <= size)
+ memcpy(val, in->fscrypt_file.data(), count);
+ return count;
+}
+
+int Client::_vxattrcb_fscrypt_file_set(Inode *in, const void *val, size_t size,
+ const UserPerm& perms)
+{
+ struct ceph_statx stx = { 0 };
+ std::vector<uint8_t> aux;
+
+ aux.resize(size);
+ memcpy(aux.data(), val, size);
+
+ return _do_setattr(in, &stx, CEPH_SETATTR_FSCRYPT_FILE, perms, nullptr, &aux);
+}
+
bool Client::_vxattrcb_quota_exists(Inode *in)
{
return in->quota.is_enable() &&
exists_cb: nullptr,
flags: 0,
},
+ {
+ name: "ceph.fscrypt.auth",
+ getxattr_cb: &Client::_vxattrcb_fscrypt_auth,
+ setxattr_cb: &Client::_vxattrcb_fscrypt_auth_set,
+ readonly: false,
+ exists_cb: &Client::_vxattrcb_fscrypt_auth_exists,
+ flags: 0,
+ },
+ {
+ name: "ceph.fscrypt.file",
+ getxattr_cb: &Client::_vxattrcb_fscrypt_file,
+ setxattr_cb: &Client::_vxattrcb_fscrypt_file_set,
+ readonly: false,
+ exists_cb: &Client::_vxattrcb_fscrypt_file_exists,
+ flags: 0,
+ },
{ name: "" } /* Required table terminator */
};
struct VXattr {
const std::string name;
size_t (Client::*getxattr_cb)(Inode *in, char *val, size_t size);
+ int (Client::*setxattr_cb)(Inode *in, const void *val, size_t size,
+ const UserPerm& perms);
bool readonly;
bool (Client::*exists_cb)(Inode *in);
unsigned int flags;
int _mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev,
const UserPerm& perms, InodeRef *inp = 0);
int _do_setattr(Inode *in, struct ceph_statx *stx, int mask,
- const UserPerm& perms, InodeRef *inp);
+ const UserPerm& perms, InodeRef *inp,
+ std::vector<uint8_t>* aux=nullptr);
void stat_to_statx(struct stat *st, struct ceph_statx *stx);
int __setattrx(Inode *in, struct ceph_statx *stx, int mask,
const UserPerm& perms, InodeRef *inp = 0);
vinodeno_t _get_vino(Inode *in);
+ bool _vxattrcb_fscrypt_auth_exists(Inode *in);
+ size_t _vxattrcb_fscrypt_auth(Inode *in, char *val, size_t size);
+ int _vxattrcb_fscrypt_auth_set(Inode *in, const void *val, size_t size, const UserPerm& perms);
+ bool _vxattrcb_fscrypt_file_exists(Inode *in);
+ size_t _vxattrcb_fscrypt_file(Inode *in, char *val, size_t size);
+ int _vxattrcb_fscrypt_file_set(Inode *in, const void *val, size_t size, const UserPerm& perms);
bool _vxattrcb_quota_exists(Inode *in);
size_t _vxattrcb_quota(Inode *in, char *val, size_t size);
size_t _vxattrcb_quota_max_bytes(Inode *in, char *val, size_t size);