X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fmdt%2Fmdt_handler.c;h=d9cc1157c307a5a7fc74f8785351dfd14dbf17a3;hb=a079ade7913b923b795ea5c01df4e69bf1a87691;hp=82cb9209e620edc682870552b9db97fd2d786292;hpb=74d92933108dc64b110a843352cf3336dca249d0;p=fs%2Flustre-release.git diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 82cb920..d9cc115 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -65,12 +65,14 @@ #include #include +#include + #include "mdt_internal.h" static unsigned int max_mod_rpcs_per_client = 8; -CFS_MODULE_PARM(max_mod_rpcs_per_client, "i", uint, 0644, - "maximum number of modify RPCs in flight allowed per client"); +module_param(max_mod_rpcs_per_client, uint, 0644); +MODULE_PARM_DESC(max_mod_rpcs_per_client, "maximum number of modify RPCs in flight allowed per client"); mdl_mode_t mdt_mdl_lock_modes[] = { [LCK_MINMODE] = MDL_MINMODE, @@ -266,12 +268,98 @@ static void mdt_lock_pdo_mode(struct mdt_thread_info *info, struct mdt_object *o EXIT; } -static int mdt_getstatus(struct tgt_session_info *tsi) +static int mdt_lookup_fileset(struct mdt_thread_info *info, const char *fileset, + struct lu_fid *fid) +{ + struct mdt_device *mdt = info->mti_mdt; + struct lu_name *lname = &info->mti_name; + char *name = NULL; + struct mdt_object *parent; + u32 mode; + int rc = 0; + + LASSERT(!info->mti_cross_ref); + + OBD_ALLOC(name, NAME_MAX + 1); + if (name == NULL) + return -ENOMEM; + lname->ln_name = name; + + /* + * We may want to allow this to mount a completely separate + * fileset from the MDT in the future, but keeping it to + * ROOT/ only for now avoid potential security issues. + */ + *fid = mdt->mdt_md_root_fid; + + while (rc == 0 && fileset != NULL && *fileset != '\0') { + const char *s1 = fileset; + const char *s2; + + while (*++s1 == '/') + ; + s2 = s1; + while (*s2 != '/' && *s2 != '\0') + s2++; + + if (s2 == s1) + break; + + fileset = s2; + + lname->ln_namelen = s2 - s1; + if (lname->ln_namelen > NAME_MAX) { + rc = -EINVAL; + break; + } + + /* reject .. as a path component */ + if (lname->ln_namelen == 2 && + strncmp(s1, "..", 2) == 0) { + rc = -EINVAL; + break; + } + + strncpy(name, s1, lname->ln_namelen); + name[lname->ln_namelen] = '\0'; + + parent = mdt_object_find(info->mti_env, mdt, fid); + if (IS_ERR(parent)) { + rc = PTR_ERR(parent); + break; + } + /* Only got the fid of this obj by name */ + fid_zero(fid); + rc = mdo_lookup(info->mti_env, mdt_object_child(parent), lname, + fid, &info->mti_spec); + mdt_object_put(info->mti_env, parent); + } + if (!rc) { + parent = mdt_object_find(info->mti_env, mdt, fid); + if (IS_ERR(parent)) + rc = PTR_ERR(parent); + else { + mode = lu_object_attr(&parent->mot_obj); + mdt_object_put(info->mti_env, parent); + if (!S_ISDIR(mode)) + rc = -ENOTDIR; + } + } + + OBD_FREE(name, NAME_MAX + 1); + + return rc; +} + +static int mdt_get_root(struct tgt_session_info *tsi) { struct mdt_thread_info *info = tsi2mdt_info(tsi); struct mdt_device *mdt = info->mti_mdt; struct mdt_body *repbody; + char *fileset = NULL, *buffer = NULL; int rc; + struct obd_export *exp = info->mti_exp; + char *nodemap_fileset; ENTRY; @@ -279,16 +367,48 @@ static int mdt_getstatus(struct tgt_session_info *tsi) if (rc) GOTO(out, rc = err_serious(rc)); - if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETSTATUS_PACK)) + if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GET_ROOT_PACK)) GOTO(out, rc = err_serious(-ENOMEM)); repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY); - repbody->mbo_fid1 = mdt->mdt_md_root_fid; + if (req_capsule_get_size(info->mti_pill, &RMF_NAME, RCL_CLIENT) > 0) { + fileset = req_capsule_client_get(info->mti_pill, &RMF_NAME); + if (fileset == NULL) + GOTO(out, rc = err_serious(-EFAULT)); + } + + nodemap_fileset = nodemap_get_fileset(exp->exp_target_data.ted_nodemap); + if (nodemap_fileset && nodemap_fileset[0]) { + if (fileset) { + /* consider fileset from client as a sub-fileset + * of the nodemap one */ + OBD_ALLOC(buffer, PATH_MAX + 1); + if (buffer == NULL) + GOTO(out, rc = err_serious(-ENOMEM)); + if (snprintf(buffer, PATH_MAX + 1, "%s/%s", + nodemap_fileset, fileset) >= PATH_MAX + 1) + GOTO(out, rc = err_serious(-EINVAL)); + fileset = buffer; + } else { + /* enforce fileset as specified in the nodemap */ + fileset = nodemap_fileset; + } + } + + if (fileset) { + rc = mdt_lookup_fileset(info, fileset, &repbody->mbo_fid1); + if (rc < 0) + GOTO(out, rc = err_serious(rc)); + } else { + repbody->mbo_fid1 = mdt->mdt_md_root_fid; + } repbody->mbo_valid |= OBD_MD_FLID; EXIT; out: mdt_thread_info_fini(info); + if (buffer) + OBD_FREE(buffer, PATH_MAX+1); return rc; } @@ -405,9 +525,9 @@ int mdt_pack_acl2body(struct mdt_thread_info *info, struct mdt_body *repbody, void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b, const struct lu_attr *attr, const struct lu_fid *fid) { - struct md_attr *ma = &info->mti_attr; - struct obd_export *exp = info->mti_exp; - struct lu_nodemap *nodemap = exp->exp_target_data.ted_nodemap; + struct md_attr *ma = &info->mti_attr; + struct obd_export *exp = info->mti_exp; + struct lu_nodemap *nodemap = NULL; LASSERT(ma->ma_valid & MA_INODE); @@ -431,6 +551,11 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b, b->mbo_nlink = attr->la_nlink; b->mbo_valid |= OBD_MD_FLNLINK; } + if (attr->la_valid & (LA_UID|LA_GID)) { + nodemap = nodemap_get_from_exp(exp); + if (IS_ERR(nodemap)) + goto out; + } if (attr->la_valid & LA_UID) { b->mbo_uid = nodemap_map_id(nodemap, NODEMAP_UID, NODEMAP_FS_TO_CLIENT, @@ -443,6 +568,7 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b, attr->la_gid); b->mbo_valid |= OBD_MD_FLGID; } + b->mbo_mode = attr->la_mode; if (attr->la_valid & LA_MODE) b->mbo_valid |= OBD_MD_FLMODE; @@ -492,6 +618,10 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b, if (fid != NULL && (b->mbo_valid & OBD_MD_FLSIZE)) CDEBUG(D_VFSTRACE, DFID": returning size %llu\n", PFID(fid), (unsigned long long)b->mbo_size); + +out: + if (!IS_ERR_OR_NULL(nodemap)) + nodemap_putref(nodemap); } static inline int mdt_body_has_lov(const struct lu_attr *la, @@ -819,7 +949,6 @@ static int mdt_getattr_internal(struct mdt_thread_info *info, struct mdt_body *repbody; struct lu_buf *buffer = &info->mti_buf; struct obd_export *exp = info->mti_exp; - struct lu_nodemap *nodemap = exp->exp_target_data.ted_nodemap; int rc; int is_root; ENTRY; @@ -1026,8 +1155,14 @@ static int mdt_getattr_internal(struct mdt_thread_info *info, } #ifdef CONFIG_FS_POSIX_ACL else if ((exp_connect_flags(req->rq_export) & OBD_CONNECT_ACL) && - (reqbody->mbo_valid & OBD_MD_FLACL)) + (reqbody->mbo_valid & OBD_MD_FLACL)) { + struct lu_nodemap *nodemap = nodemap_get_from_exp(exp); + if (IS_ERR(nodemap)) + RETURN(PTR_ERR(nodemap)); + rc = mdt_pack_acl2body(info, repbody, o, nodemap); + nodemap_putref(nodemap); + } #endif out: @@ -1326,7 +1461,7 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info, if (!mdt_object_exists(child)) { LU_OBJECT_DEBUG(D_INFO, info->mti_env, &child->mot_obj, - "remote object doesn't exist.\n"); + "remote object doesn't exist."); mdt_object_unlock(info, child, lhc, 1); RETURN(-ENOENT); } @@ -1366,7 +1501,7 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info, if (unlikely(!mdt_object_exists(parent)) && lu_name_is_valid(lname)) { LU_OBJECT_DEBUG(D_INODE, info->mti_env, &parent->mot_obj, - "Parent doesn't exist!\n"); + "Parent doesn't exist!"); RETURN(-ESTALE); } @@ -1437,7 +1572,7 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info, if (!mdt_object_exists(child)) { LU_OBJECT_DEBUG(D_INODE, info->mti_env, &child->mot_obj, - "Object doesn't exist!\n"); + "Object doesn't exist!"); GOTO(out_child, rc = -ENOENT); } @@ -1925,7 +2060,7 @@ static int mdt_quotactl(struct tgt_session_info *tsi) int id, rc; struct mdt_device *mdt = mdt_exp2dev(exp); struct lu_device *qmt = mdt->mdt_qmt_dev; - struct lu_nodemap *nodemap = exp->exp_target_data.ted_nodemap; + struct lu_nodemap *nodemap; ENTRY; oqctl = req_capsule_client_get(pill, &RMF_OBD_QUOTACTL); @@ -1936,23 +2071,27 @@ static int mdt_quotactl(struct tgt_session_info *tsi) if (rc) RETURN(err_serious(rc)); + nodemap = nodemap_get_from_exp(exp); + if (IS_ERR(nodemap)) + RETURN(PTR_ERR(nodemap)); + switch (oqctl->qc_cmd) { /* master quotactl */ case Q_SETINFO: case Q_SETQUOTA: if (!nodemap_can_setquota(nodemap)) - RETURN(-EPERM); + GOTO(out_nodemap, rc = -EPERM); case Q_GETINFO: case Q_GETQUOTA: if (qmt == NULL) - RETURN(-EOPNOTSUPP); + GOTO(out_nodemap, rc = -EOPNOTSUPP); /* slave quotactl */ case Q_GETOINFO: case Q_GETOQUOTA: break; default: CERROR("Unsupported quotactl command: %d\n", oqctl->qc_cmd); - RETURN(-EFAULT); + GOTO(out_nodemap, rc = -EFAULT); } /* map uid/gid for remote client */ @@ -1964,7 +2103,7 @@ static int mdt_quotactl(struct tgt_session_info *tsi) if (unlikely(oqctl->qc_cmd != Q_GETQUOTA && oqctl->qc_cmd != Q_GETINFO)) - RETURN(-EPERM); + GOTO(out_nodemap, rc = -EPERM); if (oqctl->qc_type == USRQUOTA) id = lustre_idmap_lookup_uid(NULL, idmap, 0, @@ -1973,11 +2112,11 @@ static int mdt_quotactl(struct tgt_session_info *tsi) id = lustre_idmap_lookup_gid(NULL, idmap, 0, oqctl->qc_id); else - RETURN(-EINVAL); + GOTO(out_nodemap, rc = -EINVAL); if (id == CFS_IDMAP_NOTFOUND) { CDEBUG(D_QUOTA, "no mapping for id %u\n", oqctl->qc_id); - RETURN(-EACCES); + GOTO(out_nodemap, rc = -EACCES); } } @@ -1990,7 +2129,7 @@ static int mdt_quotactl(struct tgt_session_info *tsi) repoqc = req_capsule_server_get(pill, &RMF_OBD_QUOTACTL); if (repoqc == NULL) - RETURN(err_serious(-EFAULT)); + GOTO(out_nodemap, rc = err_serious(-EFAULT)); if (oqctl->qc_id != id) swap(oqctl->qc_id, id); @@ -2014,14 +2153,20 @@ static int mdt_quotactl(struct tgt_session_info *tsi) default: CERROR("Unsupported quotactl command: %d\n", oqctl->qc_cmd); - RETURN(-EFAULT); + GOTO(out_nodemap, rc = -EFAULT); } if (oqctl->qc_id != id) swap(oqctl->qc_id, id); *repoqc = *oqctl; - RETURN(rc); + + EXIT; + +out_nodemap: + nodemap_putref(nodemap); + + return rc; } /** clone llog ctxt from child (mdd) @@ -2285,7 +2430,7 @@ int mdt_remote_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, } break; case LDLM_CB_CANCELING: - LDLM_DEBUG(lock, "Revoke remote lock\n"); + LDLM_DEBUG(lock, "Revoke remote lock"); /* discard slc lock here so that it can be cleaned anytime, * especially for cleanup_resource() */ tgt_discard_slc_lock(lock); @@ -2312,7 +2457,7 @@ int mdt_check_resent_lock(struct mdt_thread_info *info, /* Lock is pinned by ldlm_handle_enqueue0() as it is * a resend case, however, it could be already destroyed * due to client eviction or a raced cancel RPC. */ - LDLM_DEBUG_NOLOCK("Invalid lock handle "LPX64"\n", + LDLM_DEBUG_NOLOCK("Invalid lock handle "LPX64, lhc->mlh_reg_lh.cookie); RETURN(-ESTALE); } @@ -3025,7 +3170,7 @@ static int mdt_intent_lock_replace(struct mdt_thread_info *info, struct ldlm_lock **lockp, struct mdt_lock_handle *lh, - __u64 flags) + __u64 flags, int result) { struct ptlrpc_request *req = mdt_info_req(info); struct ldlm_lock *lock = *lockp; @@ -3039,8 +3184,19 @@ mdt_intent_lock_replace(struct mdt_thread_info *info, RETURN(0); } - LASSERTF(new_lock != NULL, - "lockh "LPX64"\n", lh->mlh_reg_lh.cookie); + if (new_lock == NULL && (flags & LDLM_FL_RESENT)) { + /* Lock is pinned by ldlm_handle_enqueue0() as it is + * a resend case, however, it could be already destroyed + * due to client eviction or a raced cancel RPC. */ + LDLM_DEBUG_NOLOCK("Invalid lock handle "LPX64"\n", + lh->mlh_reg_lh.cookie); + lh->mlh_reg_lh.cookie = 0; + RETURN(-ESTALE); + } + + LASSERTF(new_lock != NULL, + "lockh "LPX64" flags "LPX64" rc %d\n", + lh->mlh_reg_lh.cookie, flags, result); /* * If we've already given this lock to a client once, then we should @@ -3174,7 +3330,7 @@ static int mdt_intent_getxattr(enum mdt_it_code opcode, grc = mdt_getxattr(info); - rc = mdt_intent_lock_replace(info, lockp, lhc, flags); + rc = mdt_intent_lock_replace(info, lockp, lhc, flags, 0); if (mdt_info_req(info)->rq_repmsg != NULL) ldlm_rep = req_capsule_server_get(info->mti_pill, &RMF_DLM_REP); @@ -3243,7 +3399,7 @@ static int mdt_intent_getattr(enum mdt_it_code opcode, GOTO(out_ucred, rc = ELDLM_LOCK_ABORTED); } - rc = mdt_intent_lock_replace(info, lockp, lhc, flags); + rc = mdt_intent_lock_replace(info, lockp, lhc, flags, rc); EXIT; out_ucred: mdt_exit_ucred(info); @@ -3313,7 +3469,7 @@ out_obj: mdt_object_put(info->mti_env, obj); if (rc == 0 && lustre_handle_is_used(&lhc->mlh_reg_lh)) - rc = mdt_intent_lock_replace(info, lockp, lhc, flags); + rc = mdt_intent_lock_replace(info, lockp, lhc, flags, rc); out: lhc->mlh_reg_lh.cookie = 0; @@ -3368,7 +3524,7 @@ static int mdt_intent_reint(enum mdt_it_code opcode, if (lustre_handle_is_used(&lhc->mlh_reg_lh) && (rc == 0 || rc == -MDT_EREMOTE_OPEN)) { rep->lock_policy_res2 = 0; - rc = mdt_intent_lock_replace(info, lockp, lhc, flags); + rc = mdt_intent_lock_replace(info, lockp, lhc, flags, rc); RETURN(rc); } @@ -4241,7 +4397,7 @@ TGT_RPC_HANDLER(MDS_FIRST_OPC, HABEO_REFERO, MDS_SET_INFO, mdt_set_info, &RQF_OBD_SET_INFO, LUSTRE_MDS_VERSION), TGT_MDT_HDL(0, MDS_GET_INFO, mdt_get_info), -TGT_MDT_HDL(0 | HABEO_REFERO, MDS_GETSTATUS, mdt_getstatus), +TGT_MDT_HDL(0 | HABEO_REFERO, MDS_GET_ROOT, mdt_get_root), TGT_MDT_HDL(HABEO_CORPUS, MDS_GETATTR, mdt_getattr), TGT_MDT_HDL(HABEO_CORPUS| HABEO_REFERO, MDS_GETATTR_NAME, mdt_getattr_name), @@ -4648,6 +4804,7 @@ static struct cfg_interop_param mdt_interop_param[] = { { "mdt.group_upcall", NULL }, { "mdt.quota_type", NULL }, { "mdd.quota_type", NULL }, + { "mdt.som", NULL }, { "mdt.rootsquash", "mdt.root_squash" }, { "mdt.nosquash_nid", "mdt.nosquash_nids" }, { NULL } @@ -5060,7 +5217,6 @@ static int mdt_export_cleanup(struct obd_export *exp) if (!list_empty(&closing_list)) { struct md_attr *ma = &info->mti_attr; - struct mdt_object *o; /* Close any open files (which may also cause orphan * unlinking). */ @@ -5090,13 +5246,7 @@ static int mdt_export_cleanup(struct obd_export *exp) ma->ma_valid = MA_FLAGS; ma->ma_attr_flags |= MDS_KEEP_ORPHAN; } - - /* Do not lose object before last unlink. */ - o = mfd->mfd_object; - mdt_object_get(info->mti_env, o); mdt_mfd_close(info, mfd); - mdt_handle_last_unlink(info, o, ma); - mdt_object_put(info->mti_env, o); } } info->mti_mdt = NULL; @@ -5354,6 +5504,7 @@ int mdt_links_read(struct mdt_thread_info *info, struct mdt_object *mdt_obj, * \param[in] info Per-thread common data shared by MDT level handlers. * \param[in] obj Object to do path lookup of * \param[in,out] fp User-provided struct to store path information + * \param[in] root_fid Root FID of current path should reach * * \retval 0 Lookup successful, path information stored in fp * \retval -EAGAIN Lookup failed, usually because object is being moved @@ -5361,7 +5512,8 @@ int mdt_links_read(struct mdt_thread_info *info, struct mdt_object *mdt_obj, */ static int mdt_path_current(struct mdt_thread_info *info, struct mdt_object *obj, - struct getinfo_fid2path *fp) + struct getinfo_fid2path *fp, + struct lu_fid *root_fid) { struct mdt_device *mdt = info->mti_mdt; struct mdt_object *mdt_obj; @@ -5384,16 +5536,18 @@ static int mdt_path_current(struct mdt_thread_info *info, RETURN(-ENOMEM); ldata.ld_buf = buf; - ptr = fp->gf_path + fp->gf_pathlen - 1; + ptr = fp->gf_u.gf_path + fp->gf_pathlen - 1; *ptr = 0; --ptr; *tmpfid = fp->gf_fid = *mdt_object_fid(obj); - /* root FID only exists on MDT0, and fid2path should also ends at MDT0, - * so checking root_fid can only happen on MDT0. */ - while (!lu_fid_eq(&mdt->mdt_md_root_fid, &fp->gf_fid)) { + while (!lu_fid_eq(root_fid, &fp->gf_fid)) { struct lu_buf lmv_buf; + if (!lu_fid_eq(root_fid, &mdt->mdt_md_root_fid) && + lu_fid_eq(&mdt->mdt_md_root_fid, &fp->gf_fid)) + GOTO(out, rc = -ENOENT); + mdt_obj = mdt_object_find(info->mti_env, mdt, tmpfid); if (IS_ERR(mdt_obj)) GOTO(out, rc = PTR_ERR(mdt_obj)); @@ -5454,7 +5608,7 @@ static int mdt_path_current(struct mdt_thread_info *info, /* Pack the name in the end of the buffer */ ptr -= tmpname->ln_namelen; - if (ptr - 1 <= fp->gf_path) + if (ptr - 1 <= fp->gf_u.gf_path) GOTO(out, rc = -EOVERFLOW); strncpy(ptr, tmpname->ln_name, tmpname->ln_namelen); *(--ptr) = '/'; @@ -5469,7 +5623,8 @@ static int mdt_path_current(struct mdt_thread_info *info, remote_out: ptr++; /* skip leading / */ - memmove(fp->gf_path, ptr, fp->gf_path + fp->gf_pathlen - ptr); + memmove(fp->gf_u.gf_path, ptr, + fp->gf_u.gf_path + fp->gf_pathlen - ptr); out: RETURN(rc); @@ -5491,7 +5646,7 @@ out: * \retval negative errno if there was a problem */ static int mdt_path(struct mdt_thread_info *info, struct mdt_object *obj, - struct getinfo_fid2path *fp) + struct getinfo_fid2path *fp, struct lu_fid *root_fid) { struct mdt_device *mdt = info->mti_mdt; int tries = 3; @@ -5501,14 +5656,17 @@ static int mdt_path(struct mdt_thread_info *info, struct mdt_object *obj, if (fp->gf_pathlen < 3) RETURN(-EOVERFLOW); - if (lu_fid_eq(&mdt->mdt_md_root_fid, mdt_object_fid(obj))) { - fp->gf_path[0] = '\0'; + if (root_fid == NULL) + root_fid = &mdt->mdt_md_root_fid; + + if (lu_fid_eq(root_fid, mdt_object_fid(obj))) { + fp->gf_u.gf_path[0] = '\0'; RETURN(0); } /* Retry multiple times in case file is being moved */ while (tries-- && rc == -EAGAIN) - rc = mdt_path_current(info, obj, fp); + rc = mdt_path_current(info, obj, fp, root_fid); RETURN(rc); } @@ -5530,6 +5688,7 @@ static int mdt_path(struct mdt_thread_info *info, struct mdt_object *obj, * \retval negative errno if there was a problem */ static int mdt_fid2path(struct mdt_thread_info *info, + struct lu_fid *root_fid, struct getinfo_fid2path *fp) { struct mdt_device *mdt = info->mti_mdt; @@ -5572,20 +5731,22 @@ static int mdt_fid2path(struct mdt_thread_info *info, RETURN(rc); } - rc = mdt_path(info, obj, fp); + rc = mdt_path(info, obj, fp, root_fid); CDEBUG(D_INFO, "fid "DFID", path %s recno "LPX64" linkno %u\n", - PFID(&fp->gf_fid), fp->gf_path, fp->gf_recno, fp->gf_linkno); + PFID(&fp->gf_fid), fp->gf_u.gf_path, + fp->gf_recno, fp->gf_linkno); mdt_object_put(info->mti_env, obj); RETURN(rc); } -static int mdt_rpc_fid2path(struct mdt_thread_info *info, void *key, +static int mdt_rpc_fid2path(struct mdt_thread_info *info, void *key, int keylen, void *val, int vallen) { struct getinfo_fid2path *fpout, *fpin; + struct lu_fid *root_fid = NULL; int rc = 0; fpin = key + cfs_size_round(sizeof(KEY_FID2PATH)); @@ -5598,7 +5759,18 @@ static int mdt_rpc_fid2path(struct mdt_thread_info *info, void *key, if (fpout->gf_pathlen != vallen - sizeof(*fpin)) RETURN(-EINVAL); - rc = mdt_fid2path(info, fpout); + if (keylen >= cfs_size_round(sizeof(KEY_FID2PATH)) + sizeof(*fpin) + + sizeof(struct lu_fid)) { + /* client sent its root FID, which is normally fileset FID */ + root_fid = fpin->gf_u.gf_root_fid; + if (ptlrpc_req_need_swab(info->mti_pill->rc_req)) + lustre_swab_lu_fid(root_fid); + + if (root_fid != NULL && !fid_is_sane(root_fid)) + RETURN(-EINVAL); + } + + rc = mdt_fid2path(info, root_fid, fpout); RETURN(rc); } @@ -5643,7 +5815,7 @@ int mdt_get_info(struct tgt_session_info *tsi) if (KEY_IS(KEY_FID2PATH)) { struct mdt_thread_info *info = tsi2mdt_info(tsi); - rc = mdt_rpc_fid2path(info, key, valout, *vallen); + rc = mdt_rpc_fid2path(info, key, keylen, valout, *vallen); mdt_thread_info_fini(info); } else { rc = -EINVAL; @@ -5738,13 +5910,15 @@ static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len, if (rc) RETURN(rc); - switch (cmd) { - case OBD_IOC_SYNC: - rc = mdt_device_sync(&env, mdt); - break; - case OBD_IOC_SET_READONLY: - rc = dt->dd_ops->dt_ro(&env, dt); - break; + switch (cmd) { + case OBD_IOC_SYNC: + rc = mdt_device_sync(&env, mdt); + break; + case OBD_IOC_SET_READONLY: + rc = dt_sync(&env, dt); + if (rc == 0) + rc = dt_ro(&env, dt); + break; case OBD_IOC_ABORT_RECOVERY: CERROR("%s: Aborting recovery for device\n", mdt_obd_name(mdt)); obd->obd_abort_recovery = 1;