static int mdt_setattr_unpack(struct mdt_thread_info *info) { struct md_attr *ma = &info->mti_attr; struct req_capsule *pill = info->mti_pill; int rc; ENTRY; rc = mdt_setattr_unpack_rec(info); if (rc) RETURN(rc); /* Epoch may be absent */ mdt_ioepoch_unpack(info); ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); if (ma->ma_lmm_size) { ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA); ma->ma_valid |= MA_LOV; } ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES, RCL_CLIENT); if (ma->ma_cookie_size) { ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES); ma->ma_valid |= MA_COOKIE; } rc = mdt_dlmreq_unpack(info); RETURN(rc); }
static int mdt_rename_unpack(struct mdt_thread_info *info) { struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_rename *rec; struct md_attr *ma = &info->mti_attr; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; struct req_capsule *pill = info->mti_pill; int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_rename) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); /* This prior initialization is needed for old_init_ucred_reint() */ uc->uc_fsuid = rec->rn_fsuid; uc->uc_fsgid = rec->rn_fsgid; uc->uc_cap = rec->rn_cap; uc->uc_suppgids[0] = rec->rn_suppgid1; uc->uc_suppgids[1] = rec->rn_suppgid2; attr->la_uid = rec->rn_fsuid; attr->la_gid = rec->rn_fsgid; rr->rr_fid1 = &rec->rn_fid1; rr->rr_fid2 = &rec->rn_fid2; attr->la_ctime = rec->rn_time; attr->la_mtime = rec->rn_time; /* rename_tgt contains the mode already */ 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); rc = mdt_name_unpack(pill, &RMF_SYMTGT, &rr->rr_tgt_name, 0); if (rc < 0) RETURN(rc); if (rec->rn_bias & MDS_VTX_BYPASS) ma->ma_attr_flags |= MDS_VTX_BYPASS; else ma->ma_attr_flags &= ~MDS_VTX_BYPASS; info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info)); rc = mdt_dlmreq_unpack(info); RETURN(rc); }
static int mdt_rename_unpack(struct mdt_thread_info *info) { struct md_ucred *uc = mdt_ucred(info); struct mdt_rec_rename *rec; struct md_attr *ma = &info->mti_attr; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; struct req_capsule *pill = info->mti_pill; int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_rename) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); uc->mu_fsuid = rec->rn_fsuid; uc->mu_fsgid = rec->rn_fsgid; uc->mu_cap = rec->rn_cap; uc->mu_suppgids[0] = rec->rn_suppgid1; uc->mu_suppgids[1] = rec->rn_suppgid2; attr->la_uid = rec->rn_fsuid; attr->la_gid = rec->rn_fsgid; rr->rr_fid1 = &rec->rn_fid1; rr->rr_fid2 = &rec->rn_fid2; attr->la_ctime = rec->rn_time; attr->la_mtime = rec->rn_time; /* rename_tgt contains the mode already */ 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)); info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT); info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF); rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT); if (rr->rr_name == NULL || rr->rr_tgt == NULL) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1; if (!info->mti_cross_ref) LASSERT(rr->rr_namelen > 0 && rr->rr_tgtlen > 0); if (rec->rn_bias & MDS_VTX_BYPASS) ma->ma_attr_flags |= MDS_VTX_BYPASS; else ma->ma_attr_flags &= ~MDS_VTX_BYPASS; info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info)); rc = mdt_dlmreq_unpack(info); RETURN(rc); }
static int mdt_setxattr_unpack(struct mdt_thread_info *info) { struct mdt_reint_record *rr = &info->mti_rr; struct md_ucred *uc = mdt_ucred(info); struct lu_attr *attr = &info->mti_attr.ma_attr; struct req_capsule *pill = info->mti_pill; struct mdt_rec_setxattr *rec; ENTRY; CLASSERT(sizeof(struct mdt_rec_setxattr) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); uc->mu_fsuid = rec->sx_fsuid; uc->mu_fsgid = rec->sx_fsgid; uc->mu_cap = rec->sx_cap; uc->mu_suppgids[0] = rec->sx_suppgid1; uc->mu_suppgids[1] = -1; rr->rr_opcode = rec->sx_opcode; rr->rr_fid1 = &rec->sx_fid; attr->la_valid = rec->sx_valid; attr->la_ctime = rec->sx_time; 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); rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); if (rr->rr_name == NULL) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; LASSERT(rr->rr_namelen > 0); rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); if (rr->rr_eadatalen > 0) { rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA); if (rr->rr_eadata == NULL) RETURN(-EFAULT); } RETURN(0); }
static int mdt_link_unpack(struct mdt_thread_info *info) { struct md_ucred *uc = mdt_ucred(info); struct mdt_rec_link *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; struct req_capsule *pill = info->mti_pill; int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_link) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); uc->mu_fsuid = rec->lk_fsuid; uc->mu_fsgid = rec->lk_fsgid; uc->mu_cap = rec->lk_cap; uc->mu_suppgids[0] = rec->lk_suppgid1; uc->mu_suppgids[1] = rec->lk_suppgid2; attr->la_uid = rec->lk_fsuid; attr->la_gid = rec->lk_fsgid; rr->rr_fid1 = &rec->lk_fid1; rr->rr_fid2 = &rec->lk_fid2; attr->la_ctime = rec->lk_time; 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)); info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT); info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF); rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); if (rr->rr_name == NULL) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; if (!info->mti_cross_ref) LASSERT(rr->rr_namelen > 0); rc = mdt_dlmreq_unpack(info); RETURN(rc); }
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; ENTRY; CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); /* This prior initialization is needed for old_init_ucred_reint() */ uc->uc_fsuid = rec->sa_fsuid; uc->uc_fsgid = rec->sa_fsgid; uc->uc_cap = rec->sa_cap; uc->uc_suppgids[0] = rec->sa_suppgid; uc->uc_suppgids[1] = -1; 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; if (rec->sa_bias & MDS_DATA_MODIFIED) ma->ma_attr_flags |= MDS_DATA_MODIFIED; else ma->ma_attr_flags &= ~MDS_DATA_MODIFIED; 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)); RETURN(0); }
static int mdt_setattr_unpack(struct mdt_thread_info *info) { struct mdt_reint_record *rr = &info->mti_rr; struct md_attr *ma = &info->mti_attr; struct req_capsule *pill = info->mti_pill; int rc; ENTRY; rc = mdt_setattr_unpack_rec(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; } } rc = mdt_dlmreq_unpack(info); RETURN(rc); }
int mdt_name_unpack(struct req_capsule *pill, const struct req_msg_field *field, struct lu_name *ln, enum mdt_name_flags flags) { ln->ln_name = req_capsule_client_get(pill, field); ln->ln_namelen = req_capsule_get_size(pill, field, RCL_CLIENT) - 1; if (!lu_name_is_valid(ln)) { ln->ln_name = NULL; ln->ln_namelen = 0; return -EPROTO; } if ((flags & MNF_FIX_ANON) && ln->ln_namelen == 1 && ln->ln_name[0] == '/') { /* Newer (3.x) kernels use a name of "/" for the * "anonymous" disconnected dentries from NFS * filehandle conversion. See d_obtain_alias(). */ ln->ln_name = NULL; ln->ln_namelen = 0; } return 0; }
static inline void mdt_reint_init_ma(struct mdt_thread_info *info, struct md_attr *ma) { ma->ma_lmm = req_capsule_server_get(info->mti_pill, &RMF_MDT_MD); ma->ma_lmm_size = req_capsule_get_size(info->mti_pill, &RMF_MDT_MD, RCL_SERVER); ma->ma_cookie = req_capsule_server_get(info->mti_pill, &RMF_LOGCOOKIES); ma->ma_cookie_size = req_capsule_get_size(info->mti_pill, &RMF_LOGCOOKIES, RCL_SERVER); ma->ma_need = MA_INODE | MA_LOV | MA_COOKIE; ma->ma_valid = 0; }
static int mdt_link_unpack(struct mdt_thread_info *info) { struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_link *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; struct req_capsule *pill = info->mti_pill; int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_link) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); /* This prior initialization is needed for old_init_ucred_reint() */ uc->uc_fsuid = rec->lk_fsuid; uc->uc_fsgid = rec->lk_fsgid; uc->uc_cap = rec->lk_cap; uc->uc_suppgids[0] = rec->lk_suppgid1; uc->uc_suppgids[1] = rec->lk_suppgid2; attr->la_uid = rec->lk_fsuid; attr->la_gid = rec->lk_fsgid; rr->rr_fid1 = &rec->lk_fid1; rr->rr_fid2 = &rec->lk_fid2; attr->la_ctime = rec->lk_time; 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)); rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); if (rr->rr_name == NULL) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; LASSERT(rr->rr_namelen > 0); rc = mdt_dlmreq_unpack(info); RETURN(rc); }
static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) { struct req_capsule *pill = info->mti_pill; if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) { info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ); if (info->mti_dlm_req == NULL) RETURN(-EFAULT); } RETURN(0); }
/* Setinfo coming from Server (eg MDT) to Client (eg MDC)! */ static int ldlm_handle_setinfo(struct ptlrpc_request *req) { struct obd_device *obd = req->rq_export->exp_obd; char *key; void *val; int keylen, vallen; int rc = -ENOSYS; DEBUG_REQ(D_HSM, req, "%s: handle setinfo\n", obd->obd_name); req_capsule_set(&req->rq_pill, &RQF_OBD_SET_INFO); key = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY); if (key == NULL) { DEBUG_REQ(D_IOCTL, req, "no set_info key"); return -EFAULT; } keylen = req_capsule_get_size(&req->rq_pill, &RMF_SETINFO_KEY, RCL_CLIENT); val = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_VAL); if (val == NULL) { DEBUG_REQ(D_IOCTL, req, "no set_info val"); return -EFAULT; } vallen = req_capsule_get_size(&req->rq_pill, &RMF_SETINFO_VAL, RCL_CLIENT); /* We are responsible for swabbing contents of val */ if (KEY_IS(KEY_HSM_COPYTOOL_SEND)) /* Pass it on to mdc (the "export" in this case) */ rc = obd_set_info_async(req->rq_svc_thread->t_env, req->rq_export, sizeof(KEY_HSM_COPYTOOL_SEND), KEY_HSM_COPYTOOL_SEND, vallen, val, NULL); else DEBUG_REQ(D_WARNING, req, "ignoring unknown key %s", key); return rc; }
static int mdt_ioepoch_unpack(struct mdt_thread_info *info) { struct req_capsule *pill = info->mti_pill; 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); }
void mdc_file_secctx_pack(struct ptlrpc_request *req, const char *secctx_name, const void *secctx, size_t secctx_size) { void *buf; size_t buf_size; if (secctx_name == NULL) return; buf = req_capsule_client_get(&req->rq_pill, &RMF_FILE_SECCTX_NAME); buf_size = req_capsule_get_size(&req->rq_pill, &RMF_FILE_SECCTX_NAME, RCL_CLIENT); LASSERT(buf_size == strlen(secctx_name) + 1); memcpy(buf, secctx_name, buf_size); buf = req_capsule_client_get(&req->rq_pill, &RMF_FILE_SECCTX); buf_size = req_capsule_get_size(&req->rq_pill, &RMF_FILE_SECCTX, RCL_CLIENT); LASSERT(buf_size == secctx_size); memcpy(buf, secctx, buf_size); }
void mdc_file_sepol_pack(struct ptlrpc_request *req) { void *buf; size_t buf_size; if (strlen(req->rq_sepol) == 0) return; buf = req_capsule_client_get(&req->rq_pill, &RMF_SELINUX_POL); buf_size = req_capsule_get_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT); LASSERT(buf_size == strlen(req->rq_sepol) + 1); snprintf(buf, strlen(req->rq_sepol) + 1, "%s", req->rq_sepol); }
void mdc_pack_capa(struct ptlrpc_request *req, const struct req_msg_field *field, struct obd_capa *oc) { struct req_capsule *pill = &req->rq_pill; struct lustre_capa *c; if (oc == NULL) { LASSERT(req_capsule_get_size(pill, field, RCL_CLIENT) == 0); return; } c = req_capsule_client_get(pill, field); LASSERT(c != NULL); capa_cpy(c, oc); DEBUG_CAPA(D_SEC, c, "pack"); }
/** * Pack a name (path component) into a request * * \param[in] req request * \param[in] field request field (usually RMF_NAME) * \param[in] name path component * \param[in] name_len length of path component * * \a field must be present in \a req and of size \a name_len + 1. * * \a name must be '\0' terminated of length \a name_len and represent * a single path component (not contain '/'). */ static void mdc_pack_name(struct ptlrpc_request *req, const struct req_msg_field *field, const char *name, size_t name_len) { char *buf; size_t buf_size; size_t cpy_len; buf = req_capsule_client_get(&req->rq_pill, field); buf_size = req_capsule_get_size(&req->rq_pill, field, RCL_CLIENT); LASSERT(name != NULL && name_len != 0 && buf != NULL && buf_size == name_len + 1); cpy_len = strlcpy(buf, name, buf_size); LASSERT(cpy_len == name_len && lu_name_is_valid_2(buf, cpy_len)); }
static int mdt_setattr_unpack(struct mdt_thread_info *info) { struct mdt_reint_record *rr = &info->mti_rr; struct md_attr *ma = &info->mti_attr; struct req_capsule *pill = info->mti_pill; int rc; ENTRY; rc = mdt_setattr_unpack_rec(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); 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); }
static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) { struct md_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; ENTRY; CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); uc->mu_fsuid = rec->sa_fsuid; uc->mu_fsgid = rec->sa_fsgid; uc->mu_cap = rec->sa_cap; uc->mu_suppgids[0] = rec->sa_suppgid; uc->mu_suppgids[1] = -1; rr->rr_fid1 = &rec->sa_fid; la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma); 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; 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)); RETURN(0); }
/** * Pack a name (path component) into a request * * \param[in] req request * \param[in] field request field (usually RMF_NAME) * \param[in] name path component * \param[in] name_len length of path component * * \a field must be present in \a req and of size \a name_len + 1. * * \a name must be '\0' terminated of length \a name_len and represent * a single path component (not contain '/'). */ static void mdc_pack_name(struct ptlrpc_request *req, const struct req_msg_field *field, const char *name, size_t name_len) { char *buf; size_t buf_size; size_t cpy_len; buf = req_capsule_client_get(&req->rq_pill, field); buf_size = req_capsule_get_size(&req->rq_pill, field, RCL_CLIENT); LASSERT(name != NULL && name_len != 0 && buf != NULL && buf_size == name_len + 1); cpy_len = strlcpy(buf, name, buf_size); LASSERT(lu_name_is_valid_2(buf, cpy_len)); if (cpy_len != name_len) CDEBUG(D_DENTRY, "%s: %s len %zd != %zd, concurrent rename?\n", req->rq_export->exp_obd->obd_name, buf, name_len, cpy_len); }
/** * Object updates between Targets. Because all the updates has been * dis-assemblied into object updates at sender side, so OUT will * call OSD API directly to execute these updates. * * In DNE phase I all of the updates in the request need to be executed * in one transaction, and the transaction has to be synchronously. * * Please refer to lustre/include/lustre/lustre_idl.h for req/reply * format. */ int out_handle(struct tgt_session_info *tsi) { const struct lu_env *env = tsi->tsi_env; struct tgt_thread_info *tti = tgt_th_info(env); struct thandle_exec_args *ta = &tti->tti_tea; struct req_capsule *pill = tsi->tsi_pill; struct dt_device *dt = tsi->tsi_tgt->lut_bottom; struct update_buf *ubuf; struct update *update; struct update_reply *update_reply; int bufsize; int count; int old_batchid = -1; unsigned off; int i; int rc = 0; int rc1 = 0; ENTRY; req_capsule_set(pill, &RQF_UPDATE_OBJ); bufsize = req_capsule_get_size(pill, &RMF_UPDATE, RCL_CLIENT); if (bufsize != UPDATE_BUFFER_SIZE) { CERROR("%s: invalid bufsize %d: rc = %d\n", tgt_name(tsi->tsi_tgt), bufsize, -EPROTO); RETURN(err_serious(-EPROTO)); } ubuf = req_capsule_client_get(pill, &RMF_UPDATE); if (ubuf == NULL) { CERROR("%s: No buf!: rc = %d\n", tgt_name(tsi->tsi_tgt), -EPROTO); RETURN(err_serious(-EPROTO)); } if (le32_to_cpu(ubuf->ub_magic) != UPDATE_BUFFER_MAGIC) { CERROR("%s: invalid magic %x expect %x: rc = %d\n", tgt_name(tsi->tsi_tgt), le32_to_cpu(ubuf->ub_magic), UPDATE_BUFFER_MAGIC, -EPROTO); RETURN(err_serious(-EPROTO)); } count = le32_to_cpu(ubuf->ub_count); if (count <= 0) { CERROR("%s: No update!: rc = %d\n", tgt_name(tsi->tsi_tgt), -EPROTO); RETURN(err_serious(-EPROTO)); } req_capsule_set_size(pill, &RMF_UPDATE_REPLY, RCL_SERVER, UPDATE_BUFFER_SIZE); rc = req_capsule_server_pack(pill); if (rc != 0) { CERROR("%s: Can't pack response: rc = %d\n", tgt_name(tsi->tsi_tgt), rc); RETURN(rc); } /* Prepare the update reply buffer */ update_reply = req_capsule_server_get(pill, &RMF_UPDATE_REPLY); if (update_reply == NULL) RETURN(err_serious(-EPROTO)); update_init_reply_buf(update_reply, count); tti->tti_u.update.tti_update_reply = update_reply; rc = out_tx_start(env, dt, ta); if (rc != 0) RETURN(rc); tti->tti_mult_trans = !req_is_replay(tgt_ses_req(tsi)); /* Walk through updates in the request to execute them synchronously */ off = cfs_size_round(offsetof(struct update_buf, ub_bufs[0])); for (i = 0; i < count; i++) { struct tgt_handler *h; struct dt_object *dt_obj; update = (struct update *)((char *)ubuf + off); if (old_batchid == -1) { old_batchid = update->u_batchid; } else if (old_batchid != update->u_batchid) { /* Stop the current update transaction, * create a new one */ rc = out_tx_end(env, ta); if (rc != 0) RETURN(rc); rc = out_tx_start(env, dt, ta); if (rc != 0) RETURN(rc); old_batchid = update->u_batchid; } fid_le_to_cpu(&update->u_fid, &update->u_fid); if (!fid_is_sane(&update->u_fid)) { CERROR("%s: invalid FID "DFID": rc = %d\n", tgt_name(tsi->tsi_tgt), PFID(&update->u_fid), -EPROTO); GOTO(out, rc = err_serious(-EPROTO)); } dt_obj = dt_locate(env, dt, &update->u_fid); if (IS_ERR(dt_obj)) GOTO(out, rc = PTR_ERR(dt_obj)); tti->tti_u.update.tti_dt_object = dt_obj; tti->tti_u.update.tti_update = update; tti->tti_u.update.tti_update_reply_index = i; h = out_handler_find(update->u_type); if (likely(h != NULL)) { /* For real modification RPC, check if the update * has been executed */ if (h->th_flags & MUTABOR) { struct ptlrpc_request *req = tgt_ses_req(tsi); if (out_check_resent(env, dt, dt_obj, req, out_reconstruct, update_reply, i)) GOTO(next, rc); } rc = h->th_act(tsi); } else { CERROR("%s: The unsupported opc: 0x%x\n", tgt_name(tsi->tsi_tgt), update->u_type); lu_object_put(env, &dt_obj->do_lu); GOTO(out, rc = -ENOTSUPP); } next: lu_object_put(env, &dt_obj->do_lu); if (rc < 0) GOTO(out, rc); off += cfs_size_round(update_size(update)); } out: rc1 = out_tx_end(env, ta); if (rc == 0) rc = rc1; RETURN(rc); }
/** * Process the HSM actions described in a struct hsm_user_request. * * The action described in hur will be send to coordinator to be saved and * processed later or either handled directly if hur.hur_action is HUA_RELEASE. * * This is MDS_HSM_REQUEST RPC handler. */ int mdt_hsm_request(struct tgt_session_info *tsi) { struct mdt_thread_info *info; struct req_capsule *pill = tsi->tsi_pill; struct hsm_request *hr; struct hsm_user_item *hui; struct hsm_action_list *hal; struct hsm_action_item *hai; const void *data; int hui_list_size; int data_size; enum hsm_copytool_action action = HSMA_NONE; __u64 compound_id; int hal_size, i, rc; ENTRY; hr = req_capsule_client_get(pill, &RMF_MDS_HSM_REQUEST); hui = req_capsule_client_get(pill, &RMF_MDS_HSM_USER_ITEM); data = req_capsule_client_get(pill, &RMF_GENERIC_DATA); if (tsi->tsi_mdt_body == NULL || hr == NULL || hui == NULL || data == NULL) RETURN(-EPROTO); /* Sanity check. Nothing to do with an empty list */ if (hr->hr_itemcount == 0) RETURN(0); hui_list_size = req_capsule_get_size(pill, &RMF_MDS_HSM_USER_ITEM, RCL_CLIENT); if (hui_list_size < hr->hr_itemcount * sizeof(*hui)) RETURN(-EPROTO); data_size = req_capsule_get_size(pill, &RMF_GENERIC_DATA, RCL_CLIENT); if (data_size != hr->hr_data_len) RETURN(-EPROTO); info = tsi2mdt_info(tsi); /* Only valid if client is remote */ rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body); if (rc) GOTO(out, rc); switch (hr->hr_action) { /* code to be removed in hsm1_merge and final patch */ case HUA_RELEASE: CERROR("Release action is not working in hsm1_coord\n"); GOTO(out_ucred, rc = -EINVAL); break; /* end of code to be removed */ case HUA_ARCHIVE: action = HSMA_ARCHIVE; break; case HUA_RESTORE: action = HSMA_RESTORE; break; case HUA_REMOVE: action = HSMA_REMOVE; break; case HUA_CANCEL: action = HSMA_CANCEL; break; default: CERROR("Unknown hsm action: %d\n", hr->hr_action); GOTO(out_ucred, rc = -EINVAL); } hal_size = sizeof(*hal) + cfs_size_round(MTI_NAME_MAXLEN) /* fsname */ + (sizeof(*hai) + cfs_size_round(hr->hr_data_len)) * hr->hr_itemcount; MDT_HSM_ALLOC(hal, hal_size); if (hal == NULL) GOTO(out_ucred, rc = -ENOMEM); hal->hal_version = HAL_VERSION; hal->hal_archive_id = hr->hr_archive_id; hal->hal_flags = hr->hr_flags; obd_uuid2fsname(hal->hal_fsname, mdt_obd_name(info->mti_mdt), MTI_NAME_MAXLEN); hal->hal_count = 0; hai = hai_first(hal); for (i = 0; i < hr->hr_itemcount; i++, hai = hai_next(hai)) { /* Get rid of duplicate entries. Otherwise we get * duplicated work in the llog. */ if (is_fid_in_hal(hal, &hui[i].hui_fid)) continue; hai->hai_action = action; hai->hai_cookie = 0; hai->hai_gid = 0; hai->hai_fid = hui[i].hui_fid; hai->hai_extent = hui[i].hui_extent; memcpy(hai->hai_data, data, hr->hr_data_len); hai->hai_len = sizeof(*hai) + hr->hr_data_len; hal->hal_count++; } rc = mdt_hsm_add_actions(info, hal, &compound_id); MDT_HSM_FREE(hal, hal_size); GOTO(out_ucred, rc); out_ucred: mdt_exit_ucred(info); out: mdt_thread_info_fini(info); return rc; }
/** * Object updates between Targets. Because all the updates has been * dis-assemblied into object updates at sender side, so OUT will * call OSD API directly to execute these updates. * * In DNE phase I all of the updates in the request need to be executed * in one transaction, and the transaction has to be synchronously. * * Please refer to lustre/include/lustre/lustre_idl.h for req/reply * format. */ int out_handle(struct tgt_session_info *tsi) { const struct lu_env *env = tsi->tsi_env; struct tgt_thread_info *tti = tgt_th_info(env); struct thandle_exec_args *ta = &tti->tti_tea; struct req_capsule *pill = tsi->tsi_pill; struct dt_device *dt = tsi->tsi_tgt->lut_bottom; struct out_update_header *ouh; struct out_update_buffer *oub = NULL; struct object_update *update; struct object_update_reply *reply; struct ptlrpc_bulk_desc *desc = NULL; struct l_wait_info lwi; void **update_bufs; int current_batchid = -1; __u32 update_buf_count; unsigned int i; unsigned int reply_index = 0; int rc = 0; int rc1 = 0; int ouh_size, reply_size; int updates; ENTRY; req_capsule_set(pill, &RQF_OUT_UPDATE); ouh_size = req_capsule_get_size(pill, &RMF_OUT_UPDATE_HEADER, RCL_CLIENT); if (ouh_size <= 0) RETURN(err_serious(-EPROTO)); ouh = req_capsule_client_get(pill, &RMF_OUT_UPDATE_HEADER); if (ouh == NULL) RETURN(err_serious(-EPROTO)); if (ouh->ouh_magic != OUT_UPDATE_HEADER_MAGIC) { CERROR("%s: invalid update buffer magic %x expect %x: " "rc = %d\n", tgt_name(tsi->tsi_tgt), ouh->ouh_magic, UPDATE_REQUEST_MAGIC, -EPROTO); RETURN(err_serious(-EPROTO)); } update_buf_count = ouh->ouh_count; if (update_buf_count == 0) RETURN(err_serious(-EPROTO)); OBD_ALLOC(update_bufs, sizeof(*update_bufs) * update_buf_count); if (update_bufs == NULL) RETURN(err_serious(-ENOMEM)); if (ouh->ouh_inline_length > 0) { update_bufs[0] = ouh->ouh_inline_data; } else { struct out_update_buffer *tmp; oub = req_capsule_client_get(pill, &RMF_OUT_UPDATE_BUF); if (oub == NULL) GOTO(out_free, rc = err_serious(-EPROTO)); desc = ptlrpc_prep_bulk_exp(pill->rc_req, update_buf_count, PTLRPC_BULK_OPS_COUNT, PTLRPC_BULK_GET_SINK | PTLRPC_BULK_BUF_KVEC, MDS_BULK_PORTAL, &ptlrpc_bulk_kvec_ops); if (desc == NULL) GOTO(out_free, rc = err_serious(-ENOMEM)); tmp = oub; for (i = 0; i < update_buf_count; i++, tmp++) { if (tmp->oub_size >= OUT_MAXREQSIZE) GOTO(out_free, rc = err_serious(-EPROTO)); OBD_ALLOC(update_bufs[i], tmp->oub_size); if (update_bufs[i] == NULL) GOTO(out_free, rc = err_serious(-ENOMEM)); desc->bd_frag_ops->add_iov_frag(desc, update_bufs[i], tmp->oub_size); } pill->rc_req->rq_bulk_write = 1; rc = sptlrpc_svc_prep_bulk(pill->rc_req, desc); if (rc != 0) GOTO(out_free, rc = err_serious(rc)); rc = target_bulk_io(pill->rc_req->rq_export, desc, &lwi); if (rc < 0) GOTO(out_free, rc = err_serious(rc)); } /* validate the request and calculate the total update count and * set it to reply */ reply_size = 0; updates = 0; for (i = 0; i < update_buf_count; i++) { struct object_update_request *our; int j; our = update_bufs[i]; if (ptlrpc_req_need_swab(pill->rc_req)) lustre_swab_object_update_request(our); if (our->ourq_magic != UPDATE_REQUEST_MAGIC) { CERROR("%s: invalid update buffer magic %x" " expect %x: rc = %d\n", tgt_name(tsi->tsi_tgt), our->ourq_magic, UPDATE_REQUEST_MAGIC, -EPROTO); GOTO(out_free, rc = err_serious(-EPROTO)); } updates += our->ourq_count; /* need to calculate reply size */ for (j = 0; j < our->ourq_count; j++) { update = object_update_request_get(our, j, NULL); if (update == NULL) GOTO(out, rc = err_serious(-EPROTO)); if (ptlrpc_req_need_swab(pill->rc_req)) lustre_swab_object_update(update); if (!fid_is_sane(&update->ou_fid)) { CERROR("%s: invalid FID "DFID": rc = %d\n", tgt_name(tsi->tsi_tgt), PFID(&update->ou_fid), -EPROTO); GOTO(out, rc = err_serious(-EPROTO)); } /* XXX: what ou_result_size can be considered safe? */ reply_size += sizeof(reply->ourp_lens[0]); reply_size += sizeof(struct object_update_result); reply_size += update->ou_result_size; } } reply_size += sizeof(*reply); if (unlikely(reply_size > ouh->ouh_reply_size)) { CERROR("%s: too small reply buf %u for %u, need %u at least\n", tgt_name(tsi->tsi_tgt), ouh->ouh_reply_size, updates, reply_size); GOTO(out_free, rc = err_serious(-EPROTO)); } req_capsule_set_size(pill, &RMF_OUT_UPDATE_REPLY, RCL_SERVER, ouh->ouh_reply_size); rc = req_capsule_server_pack(pill); if (rc != 0) { CERROR("%s: Can't pack response: rc = %d\n", tgt_name(tsi->tsi_tgt), rc); GOTO(out_free, rc = err_serious(-EPROTO)); } /* Prepare the update reply buffer */ reply = req_capsule_server_get(pill, &RMF_OUT_UPDATE_REPLY); if (reply == NULL) GOTO(out_free, rc = -EPROTO); reply->ourp_magic = UPDATE_REPLY_MAGIC; reply->ourp_count = updates; tti->tti_u.update.tti_update_reply = reply; tti->tti_mult_trans = !req_is_replay(tgt_ses_req(tsi)); /* Walk through updates in the request to execute them */ for (i = 0; i < update_buf_count; i++) { struct tgt_handler *h; struct dt_object *dt_obj; int update_count; struct object_update_request *our; int j; our = update_bufs[i]; update_count = our->ourq_count; for (j = 0; j < update_count; j++) { update = object_update_request_get(our, j, NULL); dt_obj = dt_locate(env, dt, &update->ou_fid); if (IS_ERR(dt_obj)) GOTO(out, rc = PTR_ERR(dt_obj)); if (dt->dd_record_fid_accessed) { lfsck_pack_rfa(&tti->tti_lr, lu_object_fid(&dt_obj->do_lu), LE_FID_ACCESSED, LFSCK_TYPE_LAYOUT); tgt_lfsck_in_notify(env, dt, &tti->tti_lr, NULL); } tti->tti_u.update.tti_dt_object = dt_obj; tti->tti_u.update.tti_update = update; tti->tti_u.update.tti_update_reply_index = reply_index; h = out_handler_find(update->ou_type); if (unlikely(h == NULL)) { CERROR("%s: unsupported opc: 0x%x\n", tgt_name(tsi->tsi_tgt), update->ou_type); GOTO(next, rc = -ENOTSUPP); } /* Check resend case only for modifying RPC */ if (h->th_flags & MUTABOR) { struct ptlrpc_request *req = tgt_ses_req(tsi); if (out_check_resent(env, dt, dt_obj, req, out_reconstruct, reply, reply_index)) GOTO(next, rc = 0); } /* start transaction for modification RPC only */ if (h->th_flags & MUTABOR && current_batchid == -1) { current_batchid = update->ou_batchid; rc = out_tx_start(env, dt, ta, tsi->tsi_exp); if (rc != 0) GOTO(next, rc); if (update->ou_flags & UPDATE_FL_SYNC) ta->ta_handle->th_sync = 1; } /* Stop the current update transaction, if the update * has different batchid, or read-only update */ if (((current_batchid != update->ou_batchid) || !(h->th_flags & MUTABOR)) && ta->ta_handle != NULL) { rc = out_tx_end(env, ta, rc); current_batchid = -1; if (rc != 0) GOTO(next, rc); /* start a new transaction if needed */ if (h->th_flags & MUTABOR) { rc = out_tx_start(env, dt, ta, tsi->tsi_exp); if (rc != 0) GOTO(next, rc); if (update->ou_flags & UPDATE_FL_SYNC) ta->ta_handle->th_sync = 1; current_batchid = update->ou_batchid; } } rc = h->th_act(tsi); next: reply_index++; lu_object_put(env, &dt_obj->do_lu); if (rc < 0) GOTO(out, rc); } } out: if (current_batchid != -1) { rc1 = out_tx_end(env, ta, rc); if (rc == 0) rc = rc1; } out_free: if (update_bufs != NULL) { if (oub != NULL) { for (i = 0; i < update_buf_count; i++, oub++) { if (update_bufs[i] != NULL) OBD_FREE(update_bufs[i], oub->oub_size); } } OBD_FREE(update_bufs, sizeof(*update_bufs) * update_buf_count); } if (desc != NULL) ptlrpc_free_bulk(desc); RETURN(rc); }
static int mdt_create_unpack(struct mdt_thread_info *info) { struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; struct req_capsule *pill = info->mti_pill; struct md_op_spec *sp = &info->mti_spec; int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); /* This prior initialization is needed for old_init_ucred_reint() */ uc->uc_fsuid = rec->cr_fsuid; uc->uc_fsgid = rec->cr_fsgid; uc->uc_cap = rec->cr_cap; uc->uc_suppgids[0] = rec->cr_suppgid1; uc->uc_suppgids[1] = -1; uc->uc_umask = rec->cr_umask; rr->rr_fid1 = &rec->cr_fid1; rr->rr_fid2 = &rec->cr_fid2; attr->la_mode = rec->cr_mode; attr->la_rdev = rec->cr_rdev; attr->la_uid = rec->cr_fsuid; attr->la_gid = rec->cr_fsgid; attr->la_ctime = rec->cr_time; attr->la_mtime = rec->cr_time; attr->la_atime = rec->cr_time; attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | LA_TYPE | LA_CTIME | LA_MTIME | LA_ATIME; 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); if (S_ISLNK(attr->la_mode)) { const char *tgt = NULL; req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM); if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) { tgt = req_capsule_client_get(pill, &RMF_SYMTGT); sp->u.sp_symname = tgt; } if (tgt == NULL) RETURN(-EFAULT); } else { req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL); if (S_ISDIR(attr->la_mode) && req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT) > 0) { sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA); sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); sp->sp_cr_flags |= MDS_OPEN_HAS_EA; } } rc = mdt_dlmreq_unpack(info); RETURN(rc); }
static int mdt_open_unpack(struct mdt_thread_info *info) { struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct req_capsule *pill = info->mti_pill; struct mdt_reint_record *rr = &info->mti_rr; struct ptlrpc_request *req = mdt_info_req(info); struct md_op_spec *sp = &info->mti_spec; ENTRY; CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); /* This prior initialization is needed for old_init_ucred_reint() */ uc->uc_fsuid = rec->cr_fsuid; uc->uc_fsgid = rec->cr_fsgid; uc->uc_cap = rec->cr_cap; uc->uc_suppgids[0] = rec->cr_suppgid1; uc->uc_suppgids[1] = rec->cr_suppgid2; uc->uc_umask = rec->cr_umask; rr->rr_fid1 = &rec->cr_fid1; rr->rr_fid2 = &rec->cr_fid2; rr->rr_handle = &rec->cr_old_handle; attr->la_mode = rec->cr_mode; attr->la_rdev = rec->cr_rdev; attr->la_uid = rec->cr_fsuid; attr->la_gid = rec->cr_fsgid; attr->la_ctime = rec->cr_time; attr->la_mtime = rec->cr_time; attr->la_atime = rec->cr_time; attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_ATIME; memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u)); info->mti_spec.sp_cr_flags = get_mrc_cr_flags(rec); /* 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)) { rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); if (rr->rr_eadatalen > 0) { rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA); sp->u.sp_ea.eadatalen = rr->rr_eadatalen; sp->u.sp_ea.eadata = rr->rr_eadata; sp->no_create = !!req_is_replay(req); mdt_fix_lov_magic(info); } /* * Client default md_size may be 0 right after client start, * until all osc are connected, set here just some reasonable * value to prevent misbehavior. */ if (rr->rr_eadatalen == 0 && !(info->mti_spec.sp_cr_flags & MDS_OPEN_DELAY_CREATE)) rr->rr_eadatalen = MIN_MD_SIZE; } RETURN(0); }
static int mdt_setxattr_unpack(struct mdt_thread_info *info) { struct mdt_reint_record *rr = &info->mti_rr; struct lu_ucred *uc = mdt_ucred(info); struct lu_attr *attr = &info->mti_attr.ma_attr; struct req_capsule *pill = info->mti_pill; struct mdt_rec_setxattr *rec; int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_setxattr) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); /* This prior initialization is needed for old_init_ucred_reint() */ uc->uc_fsuid = rec->sx_fsuid; uc->uc_fsgid = rec->sx_fsgid; uc->uc_cap = rec->sx_cap; uc->uc_suppgids[0] = rec->sx_suppgid1; uc->uc_suppgids[1] = -1; rr->rr_opcode = rec->sx_opcode; rr->rr_fid1 = &rec->sx_fid; attr->la_valid = rec->sx_valid; attr->la_ctime = rec->sx_time; 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); if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) { rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); if (rr->rr_eadatalen > 0) { rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA); if (rr->rr_eadata == NULL) RETURN(-EFAULT); } else { rr->rr_eadata = NULL; } } else if (!(attr->la_valid & OBD_MD_FLXATTRRM)) { CDEBUG(D_INFO, "no xattr data supplied\n"); RETURN(-EFAULT); } if (mdt_dlmreq_unpack(info) < 0) RETURN(-EPROTO); RETURN(0); }
/** * Callback handler for receiving incoming completion ASTs. * * This only can happen on client side. */ static void ldlm_handle_cp_callback(struct ptlrpc_request *req, struct ldlm_namespace *ns, struct ldlm_request *dlm_req, struct ldlm_lock *lock) { int lvb_len; LIST_HEAD(ast_list); int rc = 0; LDLM_DEBUG(lock, "client completion callback handler START"); if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CANCEL_BL_CB_RACE)) { int to = cfs_time_seconds(1); while (to > 0) { schedule_timeout_and_set_state( TASK_INTERRUPTIBLE, to); if (lock->l_granted_mode == lock->l_req_mode || lock->l_flags & LDLM_FL_DESTROYED) break; } } lvb_len = req_capsule_get_size(&req->rq_pill, &RMF_DLM_LVB, RCL_CLIENT); if (lvb_len < 0) { LDLM_ERROR(lock, "Fail to get lvb_len, rc = %d", lvb_len); GOTO(out, rc = lvb_len); } else if (lvb_len > 0) { if (lock->l_lvb_len > 0) { /* for extent lock, lvb contains ost_lvb{}. */ LASSERT(lock->l_lvb_data != NULL); if (unlikely(lock->l_lvb_len < lvb_len)) { LDLM_ERROR(lock, "Replied LVB is larger than " "expectation, expected = %d, " "replied = %d", lock->l_lvb_len, lvb_len); GOTO(out, rc = -EINVAL); } } else if (ldlm_has_layout(lock)) { /* for layout lock, lvb has * variable length */ void *lvb_data; OBD_ALLOC(lvb_data, lvb_len); if (lvb_data == NULL) { LDLM_ERROR(lock, "No memory: %d.\n", lvb_len); GOTO(out, rc = -ENOMEM); } lock_res_and_lock(lock); LASSERT(lock->l_lvb_data == NULL); lock->l_lvb_data = lvb_data; lock->l_lvb_len = lvb_len; unlock_res_and_lock(lock); } } lock_res_and_lock(lock); if ((lock->l_flags & LDLM_FL_DESTROYED) || lock->l_granted_mode == lock->l_req_mode) { /* bug 11300: the lock has already been granted */ unlock_res_and_lock(lock); LDLM_DEBUG(lock, "Double grant race happened"); GOTO(out, rc = 0); } /* If we receive the completion AST before the actual enqueue returned, * then we might need to switch lock modes, resources, or extents. */ if (dlm_req->lock_desc.l_granted_mode != lock->l_req_mode) { lock->l_req_mode = dlm_req->lock_desc.l_granted_mode; LDLM_DEBUG(lock, "completion AST, new lock mode"); } if (lock->l_resource->lr_type != LDLM_PLAIN) { ldlm_convert_policy_to_local(req->rq_export, dlm_req->lock_desc.l_resource.lr_type, &dlm_req->lock_desc.l_policy_data, &lock->l_policy_data); LDLM_DEBUG(lock, "completion AST, new policy data"); } ldlm_resource_unlink_lock(lock); if (memcmp(&dlm_req->lock_desc.l_resource.lr_name, &lock->l_resource->lr_name, sizeof(lock->l_resource->lr_name)) != 0) { unlock_res_and_lock(lock); rc = ldlm_lock_change_resource(ns, lock, &dlm_req->lock_desc.l_resource.lr_name); if (rc < 0) { LDLM_ERROR(lock, "Failed to allocate resource"); GOTO(out, rc); } LDLM_DEBUG(lock, "completion AST, new resource"); CERROR("change resource!\n"); lock_res_and_lock(lock); } if (dlm_req->lock_flags & LDLM_FL_AST_SENT) { /* BL_AST locks are not needed in LRU. * Let ldlm_cancel_lru() be fast. */ ldlm_lock_remove_from_lru(lock); lock->l_flags |= LDLM_FL_CBPENDING | LDLM_FL_BL_AST; LDLM_DEBUG(lock, "completion AST includes blocking AST"); } if (lock->l_lvb_len > 0) { rc = ldlm_fill_lvb(lock, &req->rq_pill, RCL_CLIENT, lock->l_lvb_data, lvb_len); if (rc < 0) { unlock_res_and_lock(lock); GOTO(out, rc); } } ldlm_grant_lock(lock, &ast_list); unlock_res_and_lock(lock); LDLM_DEBUG(lock, "callback handler finished, about to run_ast_work"); /* Let Enqueue to call osc_lock_upcall() and initialize * l_ast_data */ OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_CP_ENQ_RACE, 2); ldlm_run_ast_work(ns, &ast_list, LDLM_WORK_CP_AST); LDLM_DEBUG_NOLOCK("client completion callback handler END (lock %p)", lock); GOTO(out, rc); out: if (rc < 0) { lock_res_and_lock(lock); lock->l_flags |= LDLM_FL_FAILED; unlock_res_and_lock(lock); wake_up(&lock->l_waitq); } LDLM_LOCK_RELEASE(lock); }
static int mdt_create_unpack(struct mdt_thread_info *info) { struct md_ucred *uc = mdt_ucred(info); struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; struct req_capsule *pill = info->mti_pill; struct md_op_spec *sp = &info->mti_spec; int rc; ENTRY; CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); uc->mu_fsuid = rec->cr_fsuid; uc->mu_fsgid = rec->cr_fsgid; uc->mu_cap = rec->cr_cap; uc->mu_suppgids[0] = rec->cr_suppgid1; uc->mu_suppgids[1] = -1; rr->rr_fid1 = &rec->cr_fid1; rr->rr_fid2 = &rec->cr_fid2; attr->la_mode = rec->cr_mode; attr->la_rdev = rec->cr_rdev; attr->la_uid = rec->cr_fsuid; attr->la_gid = rec->cr_fsgid; attr->la_ctime = rec->cr_time; attr->la_mtime = rec->cr_time; attr->la_atime = rec->cr_time; attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_ATIME; memset(&sp->u, 0, sizeof(sp->u)); sp->sp_cr_flags = get_mrc_cr_flags(rec); sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT); 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)); mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA); if (!info->mti_cross_ref) { rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; LASSERT(rr->rr_name && rr->rr_namelen > 0); } else { rr->rr_name = NULL; rr->rr_namelen = 0; } #ifdef CONFIG_FS_POSIX_ACL if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) { if (S_ISDIR(attr->la_mode)) sp->u.sp_pfid = rr->rr_fid1; req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL); LASSERT(req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)); sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA); sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); sp->u.sp_ea.fid = rr->rr_fid1; RETURN(0); } #endif if (S_ISDIR(attr->la_mode)) { /* pass parent fid for cross-ref cases */ sp->u.sp_pfid = rr->rr_fid1; if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) { /* create salve object req, need * unpack split ea here */ req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE); LASSERT(req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)); sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA); sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); sp->u.sp_ea.fid = rr->rr_fid1; RETURN(0); } req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL); } else if (S_ISLNK(attr->la_mode)) { const char *tgt = NULL; req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM); if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) { tgt = req_capsule_client_get(pill, &RMF_SYMTGT); sp->u.sp_symname = tgt; } if (tgt == NULL) RETURN(-EFAULT); } else { req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL); } rc = mdt_dlmreq_unpack(info); RETURN(rc); }
static int mdt_open_unpack(struct mdt_thread_info *info) { struct md_ucred *uc = mdt_ucred(info); struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct req_capsule *pill = info->mti_pill; struct mdt_reint_record *rr = &info->mti_rr; struct ptlrpc_request *req = mdt_info_req(info); struct md_op_spec *sp = &info->mti_spec; ENTRY; CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(pill, &RMF_REC_REINT); if (rec == NULL) RETURN(-EFAULT); uc->mu_fsuid = rec->cr_fsuid; uc->mu_fsgid = rec->cr_fsgid; uc->mu_cap = rec->cr_cap; uc->mu_suppgids[0] = rec->cr_suppgid1; uc->mu_suppgids[1] = rec->cr_suppgid2; rr->rr_fid1 = &rec->cr_fid1; rr->rr_fid2 = &rec->cr_fid2; rr->rr_handle = &rec->cr_old_handle; attr->la_mode = rec->cr_mode; attr->la_rdev = rec->cr_rdev; attr->la_uid = rec->cr_fsuid; attr->la_gid = rec->cr_fsgid; attr->la_ctime = rec->cr_time; attr->la_mtime = rec->cr_time; attr->la_atime = rec->cr_time; attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_ATIME; memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u)); info->mti_spec.sp_cr_flags = get_mrc_cr_flags(rec); /* 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_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT); 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 } rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); if (rr->rr_name == NULL) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); if (sp->u.sp_ea.eadatalen) { sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA); sp->no_create = !!req_is_replay(req); } RETURN(0); }
/* Shrink and/or grow reply buffers */ int mdt_fix_reply(struct mdt_thread_info *info) { struct req_capsule *pill = info->mti_pill; struct mdt_body *body; int md_size, md_packed = 0; int acl_size; int rc = 0; ENTRY; 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; acl_size = body->aclsize; /* this replay - not send info to client */ if (info->mti_spec.no_create) { md_size = 0; 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)); /* &RMF_MDT_BODY, &RMF_MDT_MD, &RMF_ACL, or &RMF_LOGCOOKIES (optional) &RMF_CAPA1, (optional) &RMF_CAPA2, (optional) something else */ /* 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)); /* free big lmm if md_size is not needed */ if (md_size == 0) { info->mti_big_lmm_used = 0; } else { 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); } } else if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)) { req_capsule_shrink(pill, &RMF_MDT_MD, md_size, RCL_SERVER); } if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER)) req_capsule_shrink(pill, &RMF_ACL, acl_size, RCL_SERVER); else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER)) req_capsule_shrink(pill, &RMF_LOGCOOKIES, 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); if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && !(body->valid & OBD_MD_FLOSSCAPA)) req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER); /* * Some more field should be shrinked if needed. * This should be done by those who added fields to reply message. */ /* Grow MD buffer if needed finally */ if (info->mti_big_lmm_used) { void *lmm; LASSERT(md_size > md_packed); CDEBUG(D_INFO, "Enlarge reply buffer, need extra %d bytes\n", md_size - md_packed); rc = req_capsule_server_grow(pill, &RMF_MDT_MD, md_size); if (rc) { /* 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); /* don't return transno along with error */ lustre_msg_set_transno(pill->rc_req->rq_repmsg, 0); } else { /* now we need to pack right LOV/LMV EA */ lmm = req_capsule_server_get(pill, &RMF_MDT_MD); if (info->mti_attr.ma_valid & MA_LOV) { LASSERT(req_capsule_get_size(pill, &RMF_MDT_MD, RCL_SERVER) == info->mti_attr.ma_lmm_size); memcpy(lmm, info->mti_attr.ma_lmm, info->mti_attr.ma_lmm_size); } else if (info->mti_attr.ma_valid & MA_LMV) { LASSERT(req_capsule_get_size(pill, &RMF_MDT_MD, RCL_SERVER) == info->mti_attr.ma_lmv_size); memcpy(lmm, info->mti_attr.ma_lmv, info->mti_attr.ma_lmv_size); } } /* update mdt_max_mdsize so clients will be aware about that */ if (info->mti_mdt->mdt_max_mdsize < info->mti_attr.ma_lmm_size) info->mti_mdt->mdt_max_mdsize = info->mti_attr.ma_lmm_size; info->mti_big_lmm_used = 0; } RETURN(rc); }