struct req_capsule *pill = info->mti_pill ;
struct ptlrpc_request *req = mdt_info_req(info);
char *xattr_name;
- __u64 valid = info->mti_body->valid;
+ __u64 valid;
static const char user_string[] = "user.";
int size, rc;
ENTRY;
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETXATTR_PACK))
RETURN(-ENOMEM);
+ valid = info->mti_body->valid & (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS);
+
/* Determine how many bytes we need */
- if (valid & OBD_MD_FLXATTR) {
+ if (valid == OBD_MD_FLXATTR) {
xattr_name = req_capsule_client_get(pill, &RMF_NAME);
if (!xattr_name)
RETURN(-EFAULT);
size = mo_xattr_get(info->mti_env,
mdt_object_child(info->mti_object),
&LU_BUF_NULL, xattr_name);
- } else if (valid & OBD_MD_FLXATTRLS) {
+ } else if (valid == OBD_MD_FLXATTRLS) {
size = mo_xattr_list(info->mti_env,
mdt_object_child(info->mti_object),
&LU_BUF_NULL);
+ } else if (valid == OBD_MD_FLXATTRALL) {
+ /* N.B. eadatasize = 0 is not valid for FLXATTRALL */
+ /* We could calculate accurate sizes, but this would
+ * introduce a lot of overhead, let's do it later... */
+ size = info->mti_body->eadatasize;
+ req_capsule_set_size(pill, &RMF_EAVALS, RCL_SERVER, size);
+ req_capsule_set_size(pill, &RMF_EAVALS_LENS, RCL_SERVER, size);
} else {
CDEBUG(D_INFO, "Valid bits: "LPX64"\n", info->mti_body->valid);
RETURN(-EINVAL);
RETURN(size);
}
-int mdt_getxattr(struct mdt_thread_info *info)
+static int
+mdt_getxattr_one(struct mdt_thread_info *info,
+ char *xattr_name, struct md_object *next,
+ struct lu_buf *buf, struct mdt_export_data *med,
+ struct lu_ucred *uc)
{
- struct ptlrpc_request *req = mdt_info_req(info);
- struct mdt_export_data *med = mdt_req2med(req);
+ __u32 remote = exp_connect_rmtclient(info->mti_exp);
+ int flags = CFS_IC_NOTHING, rc;
+
+ ENTRY;
+
+ CDEBUG(D_INODE, "getxattr %s\n", xattr_name);
+
+ rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
+ if (rc < 0) {
+ CERROR("getxattr failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ if (info->mti_body->valid &
+ (OBD_MD_FLRMTLSETFACL | OBD_MD_FLRMTLGETFACL))
+ flags = CFS_IC_ALL;
+ else if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL)
+ flags = CFS_IC_MAPPED;
+
+ if (rc > 0 && flags != CFS_IC_NOTHING) {
+ int rc1;
+
+ if (unlikely(!remote))
+ GOTO(out, rc = -EINVAL);
+
+ rc1 = lustre_posix_acl_xattr_id2client(uc,
+ med->med_idmap,
+ (posix_acl_xattr_header *)(buf->lb_buf),
+ rc, flags);
+ if (unlikely(rc1 < 0))
+ rc = rc1;
+ }
+
+out:
+ return rc;
+}
+
+static int mdt_getxattr_all(struct mdt_thread_info *info,
+ struct mdt_body *reqbody, struct mdt_body *repbody,
+ struct lu_buf *buf, struct md_object *next)
+{
+ const struct lu_env *env = info->mti_env;
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct mdt_export_data *med = mdt_req2med(req);
struct lu_ucred *uc = mdt_ucred(info);
+ char *v, *b, *eadatahead, *eadatatail;
+ __u32 *sizes;
+ int eadatasize, eavallen = 0, eavallens = 0, rc;
+
+ ENTRY;
+
+ /*
+ * The format of the pill is the following:
+ * EADATA: attr1\0attr2\0...attrn\0
+ * EAVALS: val1val2...valn
+ * EAVALS_LENS: 4,4,...4
+ */
+
+ eadatahead = buf->lb_buf;
+
+ /* Fill out EADATA first */
+ eadatasize = mo_xattr_list(env, next, buf);
+ if (eadatasize < 0)
+ GOTO(out, rc = eadatasize);
+
+ eadatatail = eadatahead + eadatasize;
+
+ v = req_capsule_server_get(info->mti_pill, &RMF_EAVALS);
+ sizes = req_capsule_server_get(info->mti_pill, &RMF_EAVALS_LENS);
+
+ /* Fill out EAVALS and EAVALS_LENS */
+ for (b = eadatahead; b < eadatatail; b += strlen(b) + 1, v += rc) {
+ buf->lb_buf = v;
+ buf->lb_len = reqbody->eadatasize - eavallen;
+ rc = mdt_getxattr_one(info, b, next, buf, med, uc);
+ if (rc < 0)
+ GOTO(out, rc);
+
+ sizes[eavallens] = rc;
+ eavallens++;
+ eavallen += rc;
+ }
+
+ repbody->aclsize = eavallen;
+ repbody->max_mdsize = eavallens;
+
+ req_capsule_shrink(info->mti_pill, &RMF_EAVALS, eavallen, RCL_SERVER);
+ req_capsule_shrink(info->mti_pill, &RMF_EAVALS_LENS,
+ eavallens * sizeof(__u32), RCL_SERVER);
+ req_capsule_shrink(info->mti_pill, &RMF_EADATA, eadatasize, RCL_SERVER);
+
+ GOTO(out, rc = eadatasize);
+out:
+ return rc;
+}
+
+int mdt_getxattr(struct mdt_thread_info *info)
+{
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct mdt_export_data *med = mdt_req2med(req);
+ struct lu_ucred *uc = lu_ucred(info->mti_env);
struct mdt_body *reqbody;
struct mdt_body *repbody = NULL;
struct md_object *next;
__u32 remote = exp_connect_rmtclient(info->mti_exp);
__u32 perm;
int easize, rc;
+ obd_valid valid;
ENTRY;
LASSERT(info->mti_object != NULL);
if (easize == 0 || reqbody->eadatasize == 0)
GOTO(out, rc = easize);
-
buf = &info->mti_buf;
buf->lb_buf = req_capsule_server_get(info->mti_pill, &RMF_EADATA);
buf->lb_len = easize;
- if (info->mti_body->valid & OBD_MD_FLXATTR) {
- int flags = CFS_IC_NOTHING;
- char *xattr_name = req_capsule_client_get(info->mti_pill,
- &RMF_NAME);
- CDEBUG(D_INODE, "getxattr %s\n", xattr_name);
-
- rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
- if (rc < 0) {
- CERROR("getxattr failed: %d\n", rc);
- GOTO(out, rc);
- }
-
- if (info->mti_body->valid &
- (OBD_MD_FLRMTLSETFACL | OBD_MD_FLRMTLGETFACL))
- flags = CFS_IC_ALL;
- else if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL)
- flags = CFS_IC_MAPPED;
-
- if (rc > 0 && flags != CFS_IC_NOTHING) {
- int rc1;
-
- if (unlikely(!remote))
- GOTO(out, rc = -EINVAL);
-
- rc1 = lustre_posix_acl_xattr_id2client(uc,
- med->med_idmap,
- (posix_acl_xattr_header *)(buf->lb_buf),
- rc, flags);
- if (unlikely(rc1 < 0))
- rc = rc1;
- }
- } else if (info->mti_body->valid & OBD_MD_FLXATTRLS) {
- CDEBUG(D_INODE, "listxattr\n");
-
- rc = mo_xattr_list(info->mti_env, next, buf);
- if (rc < 0)
- CDEBUG(D_INFO, "listxattr failed: %d\n", rc);
- } else
- LBUG();
-
- EXIT;
+ valid = info->mti_body->valid & (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS);
+
+ if (valid == OBD_MD_FLXATTR) {
+ char *xattr_name = req_capsule_client_get(info->mti_pill,
+ &RMF_NAME);
+ rc = mdt_getxattr_one(info, xattr_name, next, buf, med, uc);
+ } else if (valid == OBD_MD_FLXATTRLS) {
+ CDEBUG(D_INODE, "listxattr\n");
+
+ rc = mo_xattr_list(info->mti_env, next, buf);
+ if (rc < 0)
+ CDEBUG(D_INFO, "listxattr failed: %d\n", rc);
+ } else if (valid == OBD_MD_FLXATTRALL) {
+ rc = mdt_getxattr_all(info, reqbody, repbody,
+ buf, next);
+ } else
+ LBUG();
+
+ EXIT;
out:
- if (rc >= 0) {
+ if (rc >= 0) {
mdt_counter_incr(req, LPROC_MDT_GETXATTR);
- repbody->eadatasize = rc;
- rc = 0;
- }
- mdt_exit_ucred(info);
- return rc;
+ repbody->eadatasize = rc;
+ rc = 0;
+ }
+ mdt_exit_ucred(info);
+ return rc;
}
static int mdt_rmtlsetfacl(struct mdt_thread_info *info,
int mdt_reint_setxattr(struct mdt_thread_info *info,
struct mdt_lock_handle *unused)
{
- struct ptlrpc_request *req = mdt_info_req(info);
- struct lu_ucred *uc = mdt_ucred(info);
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct lu_ucred *uc = lu_ucred(info->mti_env);
struct mdt_lock_handle *lh;
const struct lu_env *env = info->mti_env;
struct lu_buf *buf = &info->mti_buf;
struct mdt_object *obj;
struct md_object *child;
__u64 valid = attr->la_valid;
- const char *xattr_name = rr->rr_name;
+ const char *xattr_name = rr->rr_name.ln_name;
int xattr_len = rr->rr_eadatalen;
__u64 lockpart;
int rc;
CDEBUG(D_INODE, "setxattr for "DFID"\n", PFID(rr->rr_fid1));
+ if (info->mti_dlm_req)
+ ldlm_request_cancel(req, info->mti_dlm_req, 0);
+
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SETXATTR))
RETURN(err_serious(-ENOMEM));
perm = mdt_identity_get_perm(uc->uc_identity, remote,
req->rq_peer.nid);
- if (!(perm & CFS_RMTACL_PERM))
- GOTO(out, rc = err_serious(-EPERM));
- }
+ if (!(perm & CFS_RMTACL_PERM))
+ GOTO(out, rc = err_serious(-EPERM));
+ }
- if (strncmp(xattr_name, XATTR_USER_PREFIX,
- sizeof(XATTR_USER_PREFIX) - 1) == 0) {
+ if (strncmp(xattr_name, XATTR_USER_PREFIX,
+ sizeof(XATTR_USER_PREFIX) - 1) == 0) {
if (!(exp_connect_flags(req->rq_export) & OBD_CONNECT_XATTR))
GOTO(out, rc = -EOPNOTSUPP);
- if (strcmp(xattr_name, XATTR_NAME_LOV) == 0)
- GOTO(out, rc = -EACCES);
- if (strcmp(xattr_name, XATTR_NAME_LMA) == 0)
- GOTO(out, rc = 0);
- if (strcmp(xattr_name, XATTR_NAME_LINK) == 0)
- GOTO(out, rc = 0);
- } else if ((valid & OBD_MD_FLXATTR) &&
- (strncmp(xattr_name, XATTR_NAME_ACL_ACCESS,
- sizeof(XATTR_NAME_ACL_ACCESS) - 1) == 0 ||
- strncmp(xattr_name, XATTR_NAME_ACL_DEFAULT,
- sizeof(XATTR_NAME_ACL_DEFAULT) - 1) == 0)) {
- /* currently lustre limit acl access size */
- if (xattr_len > LUSTRE_POSIX_ACL_MAX_SIZE)
- GOTO(out, -ERANGE);
- }
+ } else if (strncmp(xattr_name, XATTR_TRUSTED_PREFIX,
+ sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0) {
+
+ if (!md_capable(mdt_ucred(info), CFS_CAP_SYS_ADMIN))
+ GOTO(out, rc = -EPERM);
+
+ if (strcmp(xattr_name, XATTR_NAME_LOV) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_LMA) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_LMV) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_LINK) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_FID) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_VERSION) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_SOM) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_HSM) == 0 ||
+ strcmp(xattr_name, XATTR_NAME_LFSCK_NAMESPACE) == 0)
+ GOTO(out, rc = 0);
+ } else if ((valid & OBD_MD_FLXATTR) &&
+ (strncmp(xattr_name, XATTR_NAME_ACL_ACCESS,
+ sizeof(XATTR_NAME_ACL_ACCESS) - 1) == 0 ||
+ strncmp(xattr_name, XATTR_NAME_ACL_DEFAULT,
+ sizeof(XATTR_NAME_ACL_DEFAULT) - 1) == 0)) {
+ /* currently lustre limit acl access size */
+ if (xattr_len > LUSTRE_POSIX_ACL_MAX_SIZE)
+ GOTO(out, rc = -ERANGE);
+ }
lockpart = MDS_INODELOCK_UPDATE;
/* Revoke all clients' lookup lock, since the access
/* We need revoke both LOOKUP|PERM lock here, see mdt_attr_set. */
if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS))
lockpart |= MDS_INODELOCK_PERM | MDS_INODELOCK_LOOKUP;
+ /* We need to take the lock on behalf of old clients so that newer
+ * clients flush their xattr caches */
+ else
+ lockpart |= MDS_INODELOCK_XATTR;
lh = &info->mti_lh[MDT_LH_PARENT];
/* ACLs were sent to clients under LCK_CR locks, so taking LCK_EX
if (IS_ERR(obj))
GOTO(out, rc = PTR_ERR(obj));
- info->mti_mos = obj;
- rc = mdt_version_get_check_save(info, obj, 0);
- if (rc)
- GOTO(out_unlock, rc);
+ tgt_vbr_obj_set(env, mdt_obj2dt(obj));
+ rc = mdt_version_get_check_save(info, obj, 0);
+ if (rc)
+ GOTO(out_unlock, rc);
if (unlikely(!(valid & OBD_MD_FLCTIME))) {
/* This isn't strictly an error, but all current clients