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 mdt_device *mdt = info->mti_mdt;
struct obd_export *exp = info->mti_exp;
+ struct md_attr *ma = &info->mti_attr;
struct lu_nodemap *nodemap = NULL;
LASSERT(ma->ma_valid & MA_INODE);
b->mbo_nlink = attr->la_nlink;
b->mbo_valid |= OBD_MD_FLNLINK;
}
- if (attr->la_valid & (LA_UID|LA_GID)) {
+ if (attr->la_valid & (LA_UID|LA_GID|LA_PROJID)) {
nodemap = nodemap_get_from_exp(exp);
if (IS_ERR(nodemap))
goto out;
}
if (attr->la_valid & LA_PROJID) {
- /* TODO, nodemap for project id */
- b->mbo_projid = attr->la_projid;
+ b->mbo_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_FS_TO_CLIENT,
+ attr->la_projid);
b->mbo_valid |= OBD_MD_FLPROJID;
}
else
b->mbo_blocks = 1;
b->mbo_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
- } else if (info->mti_som_valid) { /* som is valid */
+ } else if (info->mti_som_strict &&
+ mdt->mdt_opts.mo_enable_strict_som) {
+ /* use SOM for size*/
b->mbo_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
} else if (ma->ma_valid & MA_SOM) { /* lsom is valid */
b->mbo_valid |= OBD_MD_FLLAZYSIZE | OBD_MD_FLLAZYBLOCKS;
RETURN(rc);
}
+static void mdt_preset_encctx_size(struct mdt_thread_info *info)
+{
+ struct req_capsule *pill = info->mti_pill;
+
+ ENTRY;
+ if (req_capsule_has_field(pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER))
+ /* pre-set size in server part with max size */
+ req_capsule_set_size(pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER,
+ info->mti_mdt->mdt_max_mdsize);
+ EXIT;
+}
+
static int mdt_getattr_internal(struct mdt_thread_info *info,
struct mdt_object *o, int ma_need)
{
* enlarge the buffer when necessary. */
req_capsule_set_size(pill, &RMF_ACL, RCL_SERVER,
LUSTRE_POSIX_ACL_MAX_SIZE_OLD);
+ mdt_preset_encctx_size(info);
rc = req_capsule_server_pack(pill);
if (unlikely(rc != 0))
info->mti_cross_ref = !!(reqbody->mbo_valid & OBD_MD_FLCROSSREF);
rc = mdt_getattr_internal(info, obj, 0);
+ if (unlikely(rc))
+ GOTO(out_shrink, rc);
+
+ rc = mdt_pack_encctx_in_reply(info, obj);
EXIT;
out_shrink:
mdt_client_compatibility(info);
* \param lname encoded hash to find
* \param parent parent object
* \param child object to search with LinkEA
- * \param force_check true to check hash even if LinkEA has only one entry
*
* \retval 1 match found
* \retval 0 no match found
* \retval -ev negative errno upon error
*/
int find_name_matching_hash(struct mdt_thread_info *info, struct lu_name *lname,
- struct mdt_object *parent, struct mdt_object *child,
- bool force_check)
+ struct mdt_object *parent, struct mdt_object *child)
{
/* Here, lname is an encoded hash of on-disk name, and
* client is doing access without encryption key.
struct link_ea_header *leh;
struct link_ea_entry *lee;
struct lu_buf link = { 0 };
- char *hash = NULL;
+ char *hash;
int reclen, count, rc;
ENTRY;
-
- if (lname->ln_namelen < LLCRYPT_FNAME_DIGEST_SIZE)
+ if (lname->ln_namelen < LL_CRYPTO_BLOCK_SIZE)
RETURN(-EINVAL);
buf = lu_buf_check_and_alloc(buf, PATH_MAX);
if (rc < 0)
RETURN(rc);
+ hash = kmalloc(lname->ln_namelen, GFP_NOFS);
+ if (!hash)
+ RETURN(-ENOMEM);
+ rc = critical_decode(lname->ln_name, lname->ln_namelen, hash);
+
leh = buf->lb_buf;
- if (force_check || leh->leh_reccount > 1) {
- hash = kmalloc(lname->ln_namelen, GFP_NOFS);
- if (!hash)
- RETURN(-ENOMEM);
- rc = critical_decode(lname->ln_name, lname->ln_namelen, hash);
- }
lee = (struct link_ea_entry *)(leh + 1);
for (count = 0; count < leh->leh_reccount; count++) {
linkea_entry_unpack(lee, &reclen, &name, &pfid);
- if (!force_check && leh->leh_reccount == 1) {
- /* if there is only one rec, it has to be it */
- *lname = name;
- break;
- }
if (!parent || lu_fid_eq(&pfid, mdt_object_fid(parent))) {
lu_buf_check_and_alloc(&link, name.ln_namelen);
if (!link.lb_buf)
rc = critical_decode(name.ln_name, name.ln_namelen,
link.lb_buf);
- if (memcmp(LLCRYPT_FNAME_DIGEST(link.lb_buf, rc),
- hash, LLCRYPT_FNAME_DIGEST_SIZE) == 0) {
+ if (memcmp(LLCRYPT_EXTRACT_DIGEST(link.lb_buf, rc),
+ hash, LL_CRYPTO_BLOCK_SIZE) == 0) {
*lname = name;
break;
}
GOTO(out_child, rc = -ESTALE);
}
- if (!(info->mti_body->mbo_valid & OBD_MD_NAMEHASH) &&
+ if (!child && is_resent) {
+ lock = ldlm_handle2lock(&lhc->mlh_reg_lh);
+ if (lock == NULL) {
+ /* 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 %#llx",
+ lhc->mlh_reg_lh.cookie);
+ RETURN(-ESTALE);
+ }
+ fid_extract_from_res_name(child_fid,
+ &lock->l_resource->lr_name);
+ LDLM_LOCK_PUT(lock);
+ child = mdt_object_find(info->mti_env, info->mti_mdt,
+ child_fid);
+ if (IS_ERR(child))
+ RETURN(PTR_ERR(child));
+ } else if (!(info->mti_body->mbo_valid & OBD_MD_NAMEHASH) &&
lu_name_is_valid(lname)) {
if (info->mti_body->mbo_valid == OBD_MD_FLID) {
rc = mdt_raw_lookup(info, parent, lname);
* So we need to compare name hash with the one in the request.
*/
if (!find_name_matching_hash(info, lname, parent,
- child, true)) {
+ child)) {
mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
mdt_clear_disposition(info, ldlm_rep, DISP_LOOKUP_POS);
GOTO(out_child, rc = -ENOENT);
/* finally, we can get attr for child. */
rc = mdt_getattr_internal(info, child, ma_need);
if (unlikely(rc != 0)) {
- mdt_object_unlock(info, child, lhc, 1);
+ if (!is_resent)
+ mdt_object_unlock(info, child, lhc, 1);
GOTO(out_child, rc);
}
rc = mdt_pack_secctx_in_reply(info, child);
if (unlikely(rc)) {
- mdt_object_unlock(info, child, lhc, 1);
+ if (!is_resent)
+ mdt_object_unlock(info, child, lhc, 1);
GOTO(out_child, rc);
}
rc = mdt_pack_encctx_in_reply(info, child);
if (unlikely(rc)) {
- mdt_object_unlock(info, child, lhc, 1);
+ if (!is_resent)
+ mdt_object_unlock(info, child, lhc, 1);
GOTO(out_child, rc);
}
unlock_parent:
if (lhp)
mdt_object_unlock(info, parent, lhp, 1);
+ if (rc == -ENOENT) {
+ /* return -ENOKEY instead of -ENOENT to encryption-unaware
+ * client if trying to access an encrypted file
+ */
+ int rc2 = mdt_check_enc(info, parent);
+
+ if (rc2)
+ rc = rc2;
+ }
return rc;
}
static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
void *karg, void __user *uarg);
+int mdt_io_set_info(struct tgt_session_info *tsi)
+{
+ struct ptlrpc_request *req = tgt_ses_req(tsi);
+ struct ost_body *body = NULL, *repbody;
+ void *key, *val = NULL;
+ int keylen, vallen, rc = 0;
+ bool is_grant_shrink;
+
+ ENTRY;
+
+ key = req_capsule_client_get(tsi->tsi_pill, &RMF_SETINFO_KEY);
+ if (key == NULL) {
+ DEBUG_REQ(D_HA, req, "no set_info key");
+ RETURN(err_serious(-EFAULT));
+ }
+ keylen = req_capsule_get_size(tsi->tsi_pill, &RMF_SETINFO_KEY,
+ RCL_CLIENT);
+
+ val = req_capsule_client_get(tsi->tsi_pill, &RMF_SETINFO_VAL);
+ if (val == NULL) {
+ DEBUG_REQ(D_HA, req, "no set_info val");
+ RETURN(err_serious(-EFAULT));
+ }
+ vallen = req_capsule_get_size(tsi->tsi_pill, &RMF_SETINFO_VAL,
+ RCL_CLIENT);
+
+ is_grant_shrink = KEY_IS(KEY_GRANT_SHRINK);
+ if (is_grant_shrink)
+ /* In this case the value is actually an RMF_OST_BODY, so we
+ * transmutate the type of this PTLRPC */
+ req_capsule_extend(tsi->tsi_pill, &RQF_OST_SET_GRANT_INFO);
+
+ rc = req_capsule_server_pack(tsi->tsi_pill);
+ if (rc < 0)
+ RETURN(rc);
+
+ if (is_grant_shrink) {
+ body = req_capsule_client_get(tsi->tsi_pill, &RMF_OST_BODY);
+
+ repbody = req_capsule_server_get(tsi->tsi_pill, &RMF_OST_BODY);
+ *repbody = *body;
+
+ /** handle grant shrink, similar to a read request */
+ tgt_grant_prepare_read(tsi->tsi_env, tsi->tsi_exp,
+ &repbody->oa);
+ } else {
+ CERROR("%s: Unsupported key %s\n",
+ tgt_name(tsi->tsi_tgt), (char *)key);
+ rc = -EOPNOTSUPP;
+ }
+
+ RETURN(rc);
+}
+
+
static int mdt_set_info(struct tgt_session_info *tsi)
{
struct ptlrpc_request *req = tgt_ses_req(tsi);
}
}
-static void mdt_preset_encctx_size(struct mdt_thread_info *info)
-{
- struct req_capsule *pill = info->mti_pill;
-
- if (req_capsule_has_field(pill, &RMF_FILE_ENCCTX,
- RCL_SERVER))
- /* pre-set size in server part with max size */
- req_capsule_set_size(pill, &RMF_FILE_ENCCTX,
- RCL_SERVER,
- info->mti_mdt->mdt_max_mdsize);
-}
-
static int mdt_reint_internal(struct mdt_thread_info *info,
struct mdt_lock_handle *lhc,
__u32 op)
case LUSTRE_Q_SETQUOTAPOOL:
case LUSTRE_Q_SETINFOPOOL:
case LUSTRE_Q_SETDEFAULT_POOL:
- if (!nodemap_can_setquota(nodemap))
+ case LUSTRE_Q_DELETEQID:
+ if (!nodemap_can_setquota(nodemap, oqctl->qc_type,
+ oqctl->qc_id))
GOTO(out_nodemap, rc = -EPERM);
- /* fallthrough */
+ fallthrough;
case Q_GETINFO:
case Q_GETQUOTA:
case LUSTRE_Q_GETDEFAULT:
if (qmt == NULL)
GOTO(out_nodemap, rc = -EOPNOTSUPP);
/* slave quotactl */
- /* fallthrough */
+ fallthrough;
case Q_GETOINFO:
case Q_GETOQUOTA:
break;
NODEMAP_CLIENT_TO_FS, id);
break;
case PRJQUOTA:
- /* todo: check/map project id */
- id = oqctl->qc_id;
+ id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_CLIENT_TO_FS, id);
break;
default:
GOTO(out_nodemap, rc = -EOPNOTSUPP);
case LUSTRE_Q_GETINFOPOOL:
case LUSTRE_Q_SETDEFAULT_POOL:
case LUSTRE_Q_GETDEFAULT_POOL:
+ case LUSTRE_Q_DELETEQID:
/* forward quotactl request to QMT */
rc = qmt_hdls.qmth_quotactl(tsi->tsi_env, qmt, oqctl);
break;
einfo->ei_cb_cp = ldlm_completion_ast;
einfo->ei_enq_slave = 0;
einfo->ei_res_id = res_id;
+ einfo->ei_req_slot = 1;
if (cache) {
/*
info->mti_opdata = 0;
info->mti_big_lmm_used = 0;
info->mti_big_acl_used = 0;
- info->mti_som_valid = 0;
+ info->mti_som_strict = 0;
info->mti_spec.no_create = 0;
info->mti_spec.sp_rm_entry = 0;
rc = mdt_getattr_name_lock(info, lhc, child_bits, ldlm_rep);
ldlm_rep->lock_policy_res2 = clear_serious(rc);
- if (mdt_get_disposition(ldlm_rep, DISP_LOOKUP_NEG))
- ldlm_rep->lock_policy_res2 = 0;
- if (!mdt_get_disposition(ldlm_rep, DISP_LOOKUP_POS) ||
- ldlm_rep->lock_policy_res2) {
- lhc->mlh_reg_lh.cookie = 0ull;
- GOTO(out_ucred, rc = ELDLM_LOCK_ABORTED);
- }
+ if (mdt_get_disposition(ldlm_rep, DISP_LOOKUP_NEG) &&
+ ldlm_rep->lock_policy_res2 != -ENOKEY)
+ ldlm_rep->lock_policy_res2 = 0;
+ if (!mdt_get_disposition(ldlm_rep, DISP_LOOKUP_POS) ||
+ ldlm_rep->lock_policy_res2) {
+ lhc->mlh_reg_lh.cookie = 0ull;
+ GOTO(out_ucred, rc = ELDLM_LOCK_ABORTED);
+ }
rc = mdt_intent_lock_replace(info, lockp, lhc, flags, rc);
EXIT;
break;
case IT_GETATTR:
check_mdt_object = true;
- /* fallthrough */
+ fallthrough;
case IT_LOOKUP:
it_format = &RQF_LDLM_INTENT_GETATTR;
it_handler = &mdt_intent_getattr;
TGT_OST_HDL(HAS_BODY | HAS_REPLY | IS_MUTABLE, OST_FALLOCATE,
mdt_fallocate_hdl),
TGT_OST_HDL(HAS_BODY | HAS_REPLY, OST_SEEK, tgt_lseek),
+TGT_RPC_HANDLER(OST_FIRST_OPC,
+ 0, OST_SET_INFO, mdt_io_set_info,
+ &RQF_OBD_SET_INFO, LUSTRE_OST_VERSION),
};
static struct tgt_handler mdt_sec_ctx_ops[] = {
INIT_LIST_HEAD(&m->mdt_squash.rsi_nosquash_nids);
spin_lock_init(&m->mdt_squash.rsi_lock);
spin_lock_init(&m->mdt_lock);
- m->mdt_enable_remote_dir = 1;
- m->mdt_enable_striped_dir = 1;
+ m->mdt_enable_chprojid_gid = 0;
m->mdt_enable_dir_migration = 1;
m->mdt_enable_dir_restripe = 0;
m->mdt_enable_dir_auto_split = 0;
+ m->mdt_enable_parallel_rename_dir = 1;
+ m->mdt_enable_parallel_rename_file = 1;
+ m->mdt_enable_remote_dir = 1;
m->mdt_enable_remote_dir_gid = 0;
- m->mdt_enable_chprojid_gid = 0;
m->mdt_enable_remote_rename = 1;
- m->mdt_dir_restripe_nsonly = 1;
m->mdt_enable_remote_subdir_mount = 1;
+ m->mdt_enable_striped_dir = 1;
+ m->mdt_dir_restripe_nsonly = 1;
+ m->mdt_rename_stats.rs_init = ktime_get();
atomic_set(&m->mdt_mds_mds_conns, 0);
atomic_set(&m->mdt_async_commit_count, 0);
else
m->mdt_opts.mo_acl = 0;
+ m->mdt_opts.mo_enable_strict_som = 1;
+
/* XXX: to support suppgid for ACL, we enable identity_upcall
* by default, otherwise, maybe got unexpected -EACCESS. */
if (m->mdt_opts.mo_acl)
atomic_set(&mo->mot_open_count, 0);
mo->mot_restripe_offset = 0;
INIT_LIST_HEAD(&mo->mot_restripe_linkage);
+ mo->mot_lsom_size = 0;
+ mo->mot_lsom_blocks = 0;
+ mo->mot_lsom_inited = false;
RETURN(o);
}
RETURN(NULL);
case OBD_IOC_ABORT_RECOVERY: {
struct obd_ioctl_data *data = karg;
- CERROR("%s: Aborting recovery for device\n", mdt_obd_name(mdt));
if (data->ioc_type & OBD_FLG_ABORT_RECOV_MDT) {
+ CERROR("%s: Aborting MDT recovery\n",
+ mdt_obd_name(mdt));
obd->obd_abort_recov_mdt = 1;
wake_up(&obd->obd_next_transno_waitq);
} else { /* if (data->ioc_type & OBD_FLG_ABORT_RECOV_OST) */
/* lctl didn't set OBD_FLG_ABORT_RECOV_OST < 2.13.57 */
+ CERROR("%s: Aborting client recovery\n",
+ mdt_obd_name(mdt));
obd->obd_abort_recovery = 1;
target_stop_recovery_thread(obd);
}