X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fmdt%2Fmdt_lib.c;h=a5cc6929cb3e3f0aeb2014f8d33b41bb99100ddf;hp=08d4809a2e1fbce0b2c9a05c1267c4ee9fbbb360;hb=85bd36cc69563d7a79e3ed34f8fadb4ed1a72b7c;hpb=5f3e926ac9ff8ad134ad920d0e8545e16395ef3b diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 08d4809..a5cc692 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -27,7 +27,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2013, Intel Corporation. + * Copyright (c) 2011, 2014, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -48,9 +48,13 @@ #define DEBUG_SUBSYSTEM S_MDS +#include +#ifdef HAVE_UIDGID_HEADER +# include +#endif #include "mdt_internal.h" -#include - +#include +#include typedef enum ucred_init_type { NONE_INIT = 0, @@ -80,7 +84,7 @@ void mdt_exit_ucred(struct mdt_thread_info *info) } static int match_nosquash_list(struct rw_semaphore *sem, - cfs_list_t *nidlist, + struct list_head *nidlist, lnet_nid_t peernid) { int rc; @@ -95,28 +99,28 @@ static int match_nosquash_list(struct rw_semaphore *sem, static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid) { struct lu_ucred *ucred = mdt_ucred(info); + struct root_squash_info *squash = &info->mti_mdt->mdt_squash; ENTRY; LASSERT(ucred != NULL); - if (!info->mti_mdt->mdt_squash_uid || ucred->uc_fsuid) + if (!squash->rsi_uid || ucred->uc_fsuid) RETURN(0); - if (match_nosquash_list(&info->mti_mdt->mdt_squash_sem, - &info->mti_mdt->mdt_nosquash_nids, - peernid)) { - CDEBUG(D_OTHER, "%s is in nosquash_nids list\n", - libcfs_nid2str(peernid)); - RETURN(0); - } + if (match_nosquash_list(&squash->rsi_sem, + &squash->rsi_nosquash_nids, + peernid)) { + CDEBUG(D_OTHER, "%s is in nosquash_nids list\n", + libcfs_nid2str(peernid)); + RETURN(0); + } CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n", libcfs_nid2str(peernid), ucred->uc_fsuid, ucred->uc_fsgid, ucred->uc_cap, - info->mti_mdt->mdt_squash_uid, info->mti_mdt->mdt_squash_gid, - 0); + squash->rsi_uid, squash->rsi_gid, 0); - ucred->uc_fsuid = info->mti_mdt->mdt_squash_uid; - ucred->uc_fsgid = info->mti_mdt->mdt_squash_gid; + ucred->uc_fsuid = squash->rsi_uid; + ucred->uc_fsgid = squash->rsi_gid; ucred->uc_cap = 0; ucred->uc_suppgids[0] = -1; ucred->uc_suppgids[1] = -1; @@ -124,6 +128,18 @@ static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid) RETURN(0); } +static void ucred_set_jobid(struct mdt_thread_info *info, struct lu_ucred *uc) +{ + struct ptlrpc_request *req = mdt_info_req(info); + const char *jobid = mdt_req_get_jobid(req); + + /* set jobid if specified. */ + if (jobid) + strlcpy(uc->uc_jobid, jobid, sizeof(uc->uc_jobid)); + else + uc->uc_jobid[0] = '\0'; +} + static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, void *buf) { @@ -155,19 +171,19 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, if (type == BODY_INIT) { struct mdt_body *body = (struct mdt_body *)buf; - ucred->uc_suppgids[0] = body->suppgid; + ucred->uc_suppgids[0] = body->mbo_suppgid; ucred->uc_suppgids[1] = -1; } - /* sanity check: we expect the uid which client claimed is true */ - if (remote) { - if (req->rq_auth_mapped_uid == INVALID_UID) { - CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); - RETURN(-EACCES); - } + /* sanity check: we expect the uid which client claimed is true */ + if (remote) { + if (!uid_valid(make_kuid(&init_user_ns, req->rq_auth_mapped_uid))) { + CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); + RETURN(-EACCES); + } - if (ptlrpc_user_desc_do_idmap(req, pud)) - RETURN(-EACCES); + if (ptlrpc_user_desc_do_idmap(req, pud)) + RETURN(-EACCES); if (req->rq_auth_mapped_uid != pud->pud_uid) { CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u " @@ -286,6 +302,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, ucred->uc_cap &= ~(CFS_CAP_SYS_RESOURCE_MASK | CFS_CAP_CHOWN_MASK); ucred->uc_valid = UCRED_NEW; + ucred_set_jobid(info, ucred); EXIT; @@ -305,6 +322,43 @@ out: return rc; } +/** + * Check whether allow the client to set supplementary group IDs or not. + * + * \param[in] info pointer to the thread context + * \param[in] uc pointer to the RPC user descriptor + * + * \retval true if allow to set supplementary group IDs + * \retval false for other cases + */ +bool allow_client_chgrp(struct mdt_thread_info *info, struct lu_ucred *uc) +{ + __u32 remote = exp_connect_rmtclient(info->mti_exp); + __u32 perm; + + /* 1. If identity_upcall is disabled, then forbid remote client to set + * supplementary group IDs, but permit local client to do that. */ + if (is_identity_get_disabled(info->mti_mdt->mdt_identity_cache)) { + if (remote) + return false; + + return true; + } + + /* 2. If fail to get related identities, then forbid any client to + * set supplementary group IDs. */ + if (uc->uc_identity == NULL) + return false; + + /* 3. Check the permission in the identities. */ + perm = mdt_identity_get_perm(uc->uc_identity, remote, + mdt_info_req(info)->rq_peer.nid); + if (perm & CFS_SETGRP_PERM) + return true; + + return false; +} + int mdt_check_ucred(struct mdt_thread_info *info) { struct ptlrpc_request *req = mdt_info_req(info); @@ -331,7 +385,7 @@ int mdt_check_ucred(struct mdt_thread_info *info) /* sanity check: if we use strong authentication, we expect the * uid which client claimed is true */ if (remote) { - if (req->rq_auth_mapped_uid == INVALID_UID) { + if (!uid_valid(make_kuid(&init_user_ns, req->rq_auth_mapped_uid))) { CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); RETURN(-EACCES); } @@ -409,22 +463,45 @@ out: return rc; } +static void mdt_squash_nodemap_id(struct lu_ucred *ucred, + struct lu_nodemap *nodemap) +{ + if (ucred->uc_o_uid == nodemap->nm_squash_uid) { + ucred->uc_fsuid = nodemap->nm_squash_uid; + ucred->uc_fsgid = nodemap->nm_squash_gid; + ucred->uc_cap = 0; + ucred->uc_suppgids[0] = -1; + ucred->uc_suppgids[1] = -1; + } +} + + static int old_init_ucred(struct mdt_thread_info *info, struct mdt_body *body) { - struct lu_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - struct md_identity *identity = NULL; - + struct lu_ucred *uc = mdt_ucred(info); + struct mdt_device *mdt = info->mti_mdt; + struct md_identity *identity = NULL; + struct lu_nodemap *nodemap = + info->mti_exp->exp_target_data.ted_nodemap; ENTRY; + body->mbo_uid = nodemap_map_id(nodemap, NODEMAP_UID, + NODEMAP_CLIENT_TO_FS, body->mbo_uid); + body->mbo_gid = nodemap_map_id(nodemap, NODEMAP_GID, + NODEMAP_CLIENT_TO_FS, body->mbo_gid); + body->mbo_fsuid = nodemap_map_id(nodemap, NODEMAP_UID, + NODEMAP_CLIENT_TO_FS, body->mbo_fsuid); + body->mbo_fsgid = nodemap_map_id(nodemap, NODEMAP_GID, + NODEMAP_CLIENT_TO_FS, body->mbo_fsgid); + LASSERT(uc != NULL); uc->uc_valid = UCRED_INVALID; - uc->uc_o_uid = uc->uc_uid = body->uid; - uc->uc_o_gid = uc->uc_gid = body->gid; - uc->uc_o_fsuid = uc->uc_fsuid = body->fsuid; - uc->uc_o_fsgid = uc->uc_fsgid = body->fsgid; - uc->uc_suppgids[0] = body->suppgid; + uc->uc_o_uid = uc->uc_uid = body->mbo_uid; + uc->uc_o_gid = uc->uc_gid = body->mbo_gid; + uc->uc_o_fsuid = uc->uc_fsuid = body->mbo_fsuid; + uc->uc_o_fsgid = uc->uc_fsgid = body->mbo_fsgid; + uc->uc_suppgids[0] = body->mbo_suppgid; uc->uc_suppgids[1] = -1; uc->uc_ginfo = NULL; if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { @@ -442,32 +519,43 @@ static int old_init_ucred(struct mdt_thread_info *info, } uc->uc_identity = identity; + mdt_squash_nodemap_id(uc, nodemap); + /* process root_squash here. */ mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); /* remove fs privilege for non-root user. */ if (uc->uc_fsuid) - uc->uc_cap = body->capability & ~CFS_CAP_FS_MASK; + uc->uc_cap = body->mbo_capability & ~CFS_CAP_FS_MASK; else - uc->uc_cap = body->capability; + uc->uc_cap = body->mbo_capability; uc->uc_valid = UCRED_OLD; + ucred_set_jobid(info, uc); RETURN(0); } static int old_init_ucred_reint(struct mdt_thread_info *info) { - struct lu_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - struct md_identity *identity = NULL; - + struct lu_ucred *uc = mdt_ucred(info); + struct mdt_device *mdt = info->mti_mdt; + struct md_identity *identity = NULL; + struct lu_nodemap *nodemap = + info->mti_exp->exp_target_data.ted_nodemap; ENTRY; LASSERT(uc != NULL); + + uc->uc_fsuid = nodemap_map_id(nodemap, NODEMAP_UID, + NODEMAP_CLIENT_TO_FS, uc->uc_fsuid); + uc->uc_fsgid = nodemap_map_id(nodemap, NODEMAP_GID, + NODEMAP_CLIENT_TO_FS, uc->uc_fsgid); + uc->uc_valid = UCRED_INVALID; uc->uc_o_uid = uc->uc_o_fsuid = uc->uc_uid = uc->uc_fsuid; uc->uc_o_gid = uc->uc_o_fsgid = uc->uc_gid = uc->uc_fsgid; uc->uc_ginfo = NULL; + if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { identity = mdt_identity_get(mdt->mdt_identity_cache, uc->uc_fsuid); @@ -490,6 +578,7 @@ static int old_init_ucred_reint(struct mdt_thread_info *info) if (uc->uc_fsuid) uc->uc_cap &= ~CFS_CAP_FS_MASK; uc->uc_valid = UCRED_OLD; + ucred_set_jobid(info, uc); RETURN(0); } @@ -529,32 +618,64 @@ int mdt_init_ucred_reint(struct mdt_thread_info *info) } /* copied from lov/lov_ea.c, just for debugging, will be removed later */ -void mdt_dump_lmm(int level, const struct lov_mds_md *lmm) +void mdt_dump_lmm(int level, const struct lov_mds_md *lmm, __u64 valid) { - const struct lov_ost_data_v1 *lod; - int i; - __u16 count; + const struct lov_ost_data_v1 *lod; + int i; + __u16 count; + + if (likely(!cfs_cdebug_show(level, DEBUG_SUBSYSTEM))) + return; - count = le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count); + count = le16_to_cpu(((struct lov_user_md *)lmm)->lmm_stripe_count); CDEBUG(level, "objid "DOSTID", magic 0x%08X, pattern %#X\n", POSTID(&lmm->lmm_oi), le32_to_cpu(lmm->lmm_magic), le32_to_cpu(lmm->lmm_pattern)); - CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n", - le32_to_cpu(lmm->lmm_stripe_size), count); - if (count == LOV_ALL_STRIPES || + CDEBUG(level, "stripe_size=0x%x, stripe_count=0x%x\n", + le32_to_cpu(lmm->lmm_stripe_size), count); + + /* If it's a directory or a released file, then there are + * no actual objects to print, so bail out. */ + if (valid & OBD_MD_FLDIREA || le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) - return; + return; LASSERT(count <= LOV_MAX_STRIPE_COUNT); for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++) { - struct ost_id oi; + struct ost_id oi; + ostid_le_to_cpu(&lod->l_ost_oi, &oi); CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n", i, le32_to_cpu(lod->l_ost_idx), POSTID(&oi)); } } +void mdt_dump_lmv(unsigned int level, const union lmv_mds_md *lmv) +{ + const struct lmv_mds_md_v1 *lmm1; + int i; + + if (likely(!cfs_cdebug_show(level, DEBUG_SUBSYSTEM))) + return; + + lmm1 = &lmv->lmv_md_v1; + CDEBUG(level, "magic 0x%08X, master %#X stripe_count %#x\n", + le32_to_cpu(lmm1->lmv_magic), + le32_to_cpu(lmm1->lmv_master_mdt_index), + le32_to_cpu(lmm1->lmv_stripe_count)); + + if (le32_to_cpu(lmm1->lmv_magic) == LMV_MAGIC_STRIPE) + return; + + for (i = 0; i < le32_to_cpu(lmm1->lmv_stripe_count); i++) { + struct lu_fid fid; + + fid_le_to_cpu(&fid, &lmm1->lmv_stripe_fids[i]); + CDEBUG(level, "idx %u subobj "DFID"\n", i, PFID(&fid)); + } +} + /* Shrink and/or grow reply buffers */ int mdt_fix_reply(struct mdt_thread_info *info) { @@ -568,12 +689,13 @@ int mdt_fix_reply(struct mdt_thread_info *info) body = req_capsule_server_get(pill, &RMF_MDT_BODY); LASSERT(body != NULL); - if (body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | OBD_MD_LINKNAME)) - md_size = body->eadatasize; - else - md_size = 0; + if (body->mbo_valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | + OBD_MD_LINKNAME)) + md_size = body->mbo_eadatasize; + else + md_size = 0; - acl_size = body->aclsize; + acl_size = body->mbo_aclsize; /* this replay - not send info to client */ if (info->mti_spec.no_create) { @@ -581,11 +703,8 @@ int mdt_fix_reply(struct mdt_thread_info *info) acl_size = 0; } - CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d" - " MDSCAPA = %llx, OSSCAPA = %llx\n", - md_size, acl_size, - (unsigned long long)(body->valid & OBD_MD_FLMDSCAPA), - (unsigned long long)(body->valid & OBD_MD_FLOSSCAPA)); + CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d\n", + md_size, acl_size); /* &RMF_MDT_BODY, &RMF_MDT_MD, @@ -598,17 +717,21 @@ int mdt_fix_reply(struct mdt_thread_info *info) /* MDT_MD buffer may be bigger than packed value, let's shrink all * buffers before growing it */ if (info->mti_big_lmm_used) { - LASSERT(req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)); - md_packed = req_capsule_get_size(pill, &RMF_MDT_MD, - RCL_SERVER); - LASSERT(md_packed > 0); - /* buffer must be allocated separately */ - LASSERT(info->mti_attr.ma_lmm != - req_capsule_server_get(pill, &RMF_MDT_MD)); - req_capsule_shrink(pill, &RMF_MDT_MD, 0, RCL_SERVER); - /* free big lmm if md_size is not needed */ - if (md_size == 0) + /* big_lmm buffer may be used even without packing the result + * into reply, just for internal server needs */ + if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)) + md_packed = req_capsule_get_size(pill, &RMF_MDT_MD, + RCL_SERVER); + + /* free big lmm if md_size is not needed */ + if (md_size == 0 || md_packed == 0) { info->mti_big_lmm_used = 0; + } else { + /* buffer must be allocated separately */ + LASSERT(info->mti_attr.ma_lmm != + req_capsule_server_get(pill, &RMF_MDT_MD)); + req_capsule_shrink(pill, &RMF_MDT_MD, 0, RCL_SERVER); + } } else if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)) { req_capsule_shrink(pill, &RMF_MDT_MD, md_size, RCL_SERVER); } @@ -620,12 +743,12 @@ int mdt_fix_reply(struct mdt_thread_info *info) acl_size, RCL_SERVER); if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) && - !(body->valid & OBD_MD_FLMDSCAPA)) - req_capsule_shrink(pill, &RMF_CAPA1, 0, RCL_SERVER); + !(body->mbo_valid & OBD_MD_FLMDSCAPA)) + req_capsule_shrink(pill, &RMF_CAPA1, 0, RCL_SERVER); - if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && - !(body->valid & OBD_MD_FLOSSCAPA)) - req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER); + if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && + !(body->mbo_valid & OBD_MD_FLOSSCAPA)) + req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER); /* * Some more field should be shrinked if needed. @@ -644,7 +767,7 @@ int mdt_fix_reply(struct mdt_thread_info *info) /* we can't answer with proper LOV EA, drop flags, * the rc is also returned so this request is * considered as failed */ - body->valid &= ~(OBD_MD_FLDIREA | OBD_MD_FLEASIZE); + body->mbo_valid &= ~(OBD_MD_FLDIREA | OBD_MD_FLEASIZE); /* don't return transno along with error */ lustre_msg_set_transno(pill->rc_req->rq_repmsg, 0); } else { @@ -681,7 +804,6 @@ int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo, { struct mdt_body *repbody; const struct lu_attr *la = &ma->ma_attr; - int rc; ENTRY; repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY); @@ -694,27 +816,7 @@ int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo, CERROR("No need in LOV EA upon unlink\n"); dump_stack(); } - repbody->eadatasize = 0; - - if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) { - repbody->aclsize = ma->ma_cookie_size; - repbody->valid |= OBD_MD_FLCOOKIE; - } - - if (info->mti_mdt->mdt_lut.lut_oss_capa && - exp_connect_flags(info->mti_exp) & OBD_CONNECT_OSS_CAPA && - repbody->valid & OBD_MD_FLEASIZE) { - struct lustre_capa *capa; - - capa = req_capsule_server_get(info->mti_pill, &RMF_CAPA2); - LASSERT(capa); - capa->lc_opc = CAPA_OPC_OSS_DESTROY; - rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa, 0); - if (rc) - RETURN(rc); - - repbody->valid |= OBD_MD_FLOSSCAPA; - } + repbody->mbo_eadatasize = 0; RETURN(0); } @@ -766,47 +868,6 @@ static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr, return out; } -void mdt_set_capainfo(struct mdt_thread_info *info, int offset, - const struct lu_fid *fid, struct lustre_capa *capa) -{ - struct lu_capainfo *lci; - - LASSERT(offset >= 0 && offset < LU_CAPAINFO_MAX); - if (!info->mti_mdt->mdt_lut.lut_mds_capa || - !(exp_connect_flags(info->mti_exp) & OBD_CONNECT_MDS_CAPA)) - return; - - lci = lu_capainfo_get(info->mti_env); - LASSERT(lci); - lci->lci_fid[offset] = *fid; - lci->lci_capa[offset] = capa; -} - -#ifdef DEBUG_CAPA -void mdt_dump_capainfo(struct mdt_thread_info *info) -{ - struct lu_capainfo *lci = lu_capainfo_get(info->mti_env); - int i; - - if (lci == NULL) - return; - - for (i = 0; i < LU_CAPAINFO_MAX; i++) { - if (lci->lci_capa[i] == NULL) { - CERROR("no capa for index %d "DFID"\n", - i, PFID(&lci->lci_fid[i])); - continue; - } - if (lci->lci_capa[i] == BYPASS_CAPA) { - CERROR("bypass for index %d "DFID"\n", - i, PFID(&lci->lci_fid[i])); - continue; - } - DEBUG_CAPA(D_ERROR, lci->lci_capa[i], "index %d", i); - } -} -#endif /* DEBUG_CAPA */ - /* unpacking */ int mdt_name_unpack(struct req_capsule *pill, @@ -838,12 +899,14 @@ int mdt_name_unpack(struct req_capsule *pill, static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) { - struct lu_ucred *uc = mdt_ucred(info); - struct md_attr *ma = &info->mti_attr; - struct lu_attr *la = &ma->ma_attr; - struct req_capsule *pill = info->mti_pill; - struct mdt_reint_record *rr = &info->mti_rr; - struct mdt_rec_setattr *rec; + struct lu_ucred *uc = mdt_ucred(info); + struct md_attr *ma = &info->mti_attr; + struct lu_attr *la = &ma->ma_attr; + struct req_capsule *pill = info->mti_pill; + struct mdt_reint_record *rr = &info->mti_rr; + struct mdt_rec_setattr *rec; + struct lu_nodemap *nodemap = + info->mti_exp->exp_target_data.ted_nodemap; ENTRY; CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint)); @@ -860,30 +923,18 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) rr->rr_fid1 = &rec->sa_fid; la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma); - /* If MDS_ATTR_xTIME is set without MDS_ATTR_xTIME_SET and - * the client does not have OBD_CONNECT_FULL20, convert it - * to LA_xTIME. LU-3036 */ - if (!(exp_connect_flags(info->mti_exp) & OBD_CONNECT_FULL20)) { - if (!(rec->sa_valid & MDS_ATTR_ATIME_SET) && - (rec->sa_valid & MDS_ATTR_ATIME)) - la->la_valid |= LA_ATIME; - if (!(rec->sa_valid & MDS_ATTR_MTIME_SET) && - (rec->sa_valid & MDS_ATTR_MTIME)) - la->la_valid |= LA_MTIME; - if (!(rec->sa_valid & MDS_ATTR_CTIME_SET) && - (rec->sa_valid & MDS_ATTR_CTIME)) - la->la_valid |= LA_CTIME; - } - la->la_mode = rec->sa_mode; - la->la_flags = rec->sa_attr_flags; - la->la_uid = rec->sa_uid; - la->la_gid = rec->sa_gid; - la->la_size = rec->sa_size; - la->la_blocks = rec->sa_blocks; - la->la_ctime = rec->sa_ctime; - la->la_atime = rec->sa_atime; - la->la_mtime = rec->sa_mtime; - ma->ma_valid = MA_INODE; + la->la_mode = rec->sa_mode; + la->la_flags = rec->sa_attr_flags; + la->la_uid = nodemap_map_id(nodemap, NODEMAP_UID, + NODEMAP_CLIENT_TO_FS, rec->sa_uid); + la->la_gid = nodemap_map_id(nodemap, NODEMAP_GID, + NODEMAP_CLIENT_TO_FS, rec->sa_gid); + la->la_size = rec->sa_size; + la->la_blocks = rec->sa_blocks; + la->la_ctime = rec->sa_ctime; + la->la_atime = rec->sa_atime; + la->la_mtime = rec->sa_mtime; + ma->ma_valid = MA_INODE; if (rec->sa_bias & MDS_DATA_MODIFIED) ma->ma_attr_flags |= MDS_DATA_MODIFIED; @@ -895,24 +946,31 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) else ma->ma_attr_flags &= ~MDS_HSM_RELEASE; - if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) - mdt_set_capainfo(info, 0, rr->rr_fid1, - req_capsule_client_get(pill, &RMF_CAPA1)); + if (rec->sa_bias & MDS_CLOSE_LAYOUT_SWAP) + ma->ma_attr_flags |= MDS_CLOSE_LAYOUT_SWAP; + else + ma->ma_attr_flags &= ~MDS_CLOSE_LAYOUT_SWAP; RETURN(0); } -static int mdt_ioepoch_unpack(struct mdt_thread_info *info) +static int mdt_close_handle_unpack(struct mdt_thread_info *info) { - struct req_capsule *pill = info->mti_pill; - ENTRY; + struct req_capsule *pill = info->mti_pill; + struct mdt_ioepoch *ioepoch; + ENTRY; - if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT)) - info->mti_ioepoch = - req_capsule_client_get(pill, &RMF_MDT_EPOCH); - else - info->mti_ioepoch = NULL; - RETURN(info->mti_ioepoch == NULL ? -EFAULT : 0); + if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT)) + ioepoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH); + else + ioepoch = NULL; + + if (ioepoch == NULL) + RETURN(-EPROTO); + + info->mti_close_handle = ioepoch->mio_handle; + + RETURN(0); } static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) { @@ -939,34 +997,42 @@ static int mdt_setattr_unpack(struct mdt_thread_info *info) if (rc) RETURN(rc); - /* Epoch may be absent */ - mdt_ioepoch_unpack(info); - if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) { rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA); rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); - ma->ma_lmm_size = rr->rr_eadatalen; - if (ma->ma_lmm_size > 0) { - ma->ma_lmm = (void *)rr->rr_eadata; - ma->ma_valid |= MA_LOV; - } - } + if (rr->rr_eadatalen > 0) { + const struct lmv_user_md *lum; + + lum = rr->rr_eadata; + /* Sigh ma_valid(from req) does not indicate whether + * it will set LOV/LMV EA, so we have to check magic */ + if (le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC) { + ma->ma_valid |= MA_LMV; + ma->ma_lmv = (void *)rr->rr_eadata; + ma->ma_lmv_size = rr->rr_eadatalen; + } else { + ma->ma_valid |= MA_LOV; + ma->ma_lmm = (void *)rr->rr_eadata; + ma->ma_lmm_size = rr->rr_eadatalen; + } + } + } - rc = mdt_dlmreq_unpack(info); - RETURN(rc); + rc = mdt_dlmreq_unpack(info); + RETURN(rc); } -static int mdt_hsm_release_unpack(struct mdt_thread_info *info) +static int mdt_intent_close_unpack(struct mdt_thread_info *info) { struct md_attr *ma = &info->mti_attr; - struct req_capsule *pill = info->mti_pill; + struct req_capsule *pill = info->mti_pill; ENTRY; - if (!(ma->ma_attr_flags & MDS_HSM_RELEASE)) + if (!(ma->ma_attr_flags & (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP))) RETURN(0); - req_capsule_extend(pill, &RQF_MDS_RELEASE_CLOSE); + req_capsule_extend(pill, &RQF_MDS_INTENT_CLOSE); if (!(req_capsule_has_field(pill, &RMF_CLOSE_DATA, RCL_CLIENT) && req_capsule_field_present(pill, &RMF_CLOSE_DATA, RCL_CLIENT))) @@ -977,10 +1043,10 @@ static int mdt_hsm_release_unpack(struct mdt_thread_info *info) int mdt_close_unpack(struct mdt_thread_info *info) { - int rc; - ENTRY; + int rc; + ENTRY; - rc = mdt_ioepoch_unpack(info); + rc = mdt_close_handle_unpack(info); if (rc) RETURN(rc); @@ -988,7 +1054,7 @@ int mdt_close_unpack(struct mdt_thread_info *info) if (rc) RETURN(rc); - rc = mdt_hsm_release_unpack(info); + rc = mdt_intent_close_unpack(info); if (rc) RETURN(rc); @@ -1033,11 +1099,6 @@ static int mdt_create_unpack(struct mdt_thread_info *info) memset(&sp->u, 0, sizeof(sp->u)); sp->sp_cr_flags = get_mrc_cr_flags(rec); - if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) - mdt_set_capainfo(info, 0, rr->rr_fid1, - req_capsule_client_get(pill, &RMF_CAPA1)); - mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA); - rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0); if (rc < 0) RETURN(rc); @@ -1099,13 +1160,6 @@ static int mdt_link_unpack(struct mdt_thread_info *info) attr->la_mtime = rec->lk_time; attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME; - if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) - mdt_set_capainfo(info, 0, rr->rr_fid1, - req_capsule_client_get(pill, &RMF_CAPA1)); - if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) - mdt_set_capainfo(info, 1, rr->rr_fid2, - req_capsule_client_get(pill, &RMF_CAPA2)); - rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0); if (rc < 0) RETURN(rc); @@ -1147,10 +1201,6 @@ static int mdt_unlink_unpack(struct mdt_thread_info *info) attr->la_mode = rec->ul_mode; attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE; - if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) - mdt_set_capainfo(info, 0, rr->rr_fid1, - req_capsule_client_get(pill, &RMF_CAPA1)); - rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0); if (rc < 0) RETURN(rc); @@ -1205,13 +1255,6 @@ static int mdt_rename_unpack(struct mdt_thread_info *info) attr->la_mode = rec->rn_mode; attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE; - if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) - mdt_set_capainfo(info, 0, rr->rr_fid1, - req_capsule_client_get(pill, &RMF_CAPA1)); - if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) - mdt_set_capainfo(info, 1, rr->rr_fid2, - req_capsule_client_get(pill, &RMF_CAPA2)); - rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0); if (rc < 0) RETURN(rc); @@ -1227,8 +1270,10 @@ static int mdt_rename_unpack(struct mdt_thread_info *info) info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info)); - rc = mdt_dlmreq_unpack(info); - RETURN(rc); + + rc = mdt_dlmreq_unpack(info); + + RETURN(rc); } /* @@ -1296,28 +1341,9 @@ static int mdt_open_unpack(struct mdt_thread_info *info) /* Do not trigger ASSERTION if client miss to set such flags. */ if (unlikely(info->mti_spec.sp_cr_flags == 0)) RETURN(-EPROTO); - info->mti_replayepoch = rec->cr_ioepoch; info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF); - if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) - mdt_set_capainfo(info, 0, rr->rr_fid1, - req_capsule_client_get(pill, &RMF_CAPA1)); - if (req_is_replay(req) && - req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) { -#if 0 - mdt_set_capainfo(info, 1, rr->rr_fid2, - req_capsule_client_get(pill, &RMF_CAPA2)); -#else - /* - * FIXME: capa in replay open request might have expired, - * bypass capa check. Security hole? - */ - mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA); - mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA); -#endif - } - mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, MNF_FIX_ANON); if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) { @@ -1377,12 +1403,6 @@ static int mdt_setxattr_unpack(struct mdt_thread_info *info) attr->la_size = rec->sx_size; attr->la_flags = rec->sx_flags; - if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) - mdt_set_capainfo(info, 0, rr->rr_fid1, - req_capsule_client_get(pill, &RMF_CAPA1)); - else - mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA); - rc = mdt_name_unpack(pill, &RMF_NAME, &rr->rr_name, 0); if (rc < 0) RETURN(rc); @@ -1421,6 +1441,7 @@ static reint_unpacker mdt_reint_unpackers[REINT_MAX] = { [REINT_OPEN] = mdt_open_unpack, [REINT_SETXATTR] = mdt_setxattr_unpack, [REINT_RMENTRY] = mdt_rmentry_unpack, + [REINT_MIGRATE] = mdt_rename_unpack, }; int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)