* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, Intel Corporation.
+ * Copyright (c) 2011, 2013, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
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);
}
+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)
+{
+ __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);
__u32 remote = exp_connect_rmtclient(info->mti_exp);
__u32 perm;
int easize, rc;
+ obd_valid valid;
ENTRY;
LASSERT(info->mti_object != NULL);
- LASSERT(lu_object_assert_exists(&info->mti_object->mot_obj.mo_lu));
+ LASSERT(lu_object_assert_exists(&info->mti_object->mot_obj));
CDEBUG(D_INODE, "getxattr "DFID"\n", PFID(&info->mti_body->fid1));
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,
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));
/* 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