+static int mdt_unlock_slaves(struct mdt_thread_info *mti,
+ struct mdt_object *obj,
+ struct ldlm_enqueue_info *einfo,
+ int decref)
+{
+ union ldlm_policy_data *policy = &mti->mti_policy;
+ struct mdt_lock_handle *lh = &mti->mti_lh[MDT_LH_LOCAL];
+ struct lustre_handle_array *slave_locks = einfo->ei_cbdata;
+ int i;
+
+ LASSERT(S_ISDIR(obj->mot_header.loh_attr));
+ LASSERT(slave_locks);
+
+ memset(policy, 0, sizeof(*policy));
+ policy->l_inodebits.bits = einfo->ei_inodebits;
+ mdt_lock_handle_init(lh);
+ mdt_lock_reg_init(lh, einfo->ei_mode);
+ for (i = 0; i < slave_locks->ha_count; i++) {
+ if (test_bit(i, (void *)slave_locks->ha_map))
+ lh->mlh_rreg_lh = slave_locks->ha_handles[i];
+ else
+ lh->mlh_reg_lh = slave_locks->ha_handles[i];
+ mdt_object_unlock(mti, NULL, lh, decref);
+ slave_locks->ha_handles[i].cookie = 0ull;
+ }
+
+ return mo_object_unlock(mti->mti_env, mdt_object_child(obj), einfo,
+ policy);
+}
+
+static inline int mdt_object_striped(struct mdt_thread_info *mti,
+ struct mdt_object *obj)
+{
+ int rc;
+
+ if (!S_ISDIR(obj->mot_header.loh_attr))
+ return 0;
+
+ rc = mo_xattr_get(mti->mti_env, mdt_object_child(obj), &LU_BUF_NULL,
+ XATTR_NAME_LMV);
+ if (rc <= 0)
+ return rc == -ENODATA ? 0 : rc;
+
+ return 1;
+}
+
+/**
+ * Lock slave stripes if necessary, the lock handles of slave stripes
+ * will be stored in einfo->ei_cbdata.
+ **/
+static int mdt_lock_slaves(struct mdt_thread_info *mti, struct mdt_object *obj,
+ enum ldlm_mode mode, __u64 ibits,
+ struct ldlm_enqueue_info *einfo)
+{
+ union ldlm_policy_data *policy = &mti->mti_policy;
+
+ LASSERT(S_ISDIR(obj->mot_header.loh_attr));
+
+ einfo->ei_type = LDLM_IBITS;
+ einfo->ei_mode = mode;
+ einfo->ei_cb_bl = mdt_remote_blocking_ast;
+ einfo->ei_cb_local_bl = mdt_blocking_ast;
+ einfo->ei_cb_cp = ldlm_completion_ast;
+ einfo->ei_enq_slave = 1;
+ einfo->ei_namespace = mti->mti_mdt->mdt_namespace;
+ einfo->ei_inodebits = ibits;
+ memset(policy, 0, sizeof(*policy));
+ policy->l_inodebits.bits = ibits;
+
+ return mo_object_lock(mti->mti_env, mdt_object_child(obj), NULL, einfo,
+ policy);
+}
+
+static inline int mdt_reint_striped_lock(struct mdt_thread_info *info,
+ struct mdt_object *o,
+ struct mdt_lock_handle *lh,
+ __u64 ibits,
+ struct ldlm_enqueue_info *einfo,
+ bool cos_incompat)
+{
+ int rc;
+
+ LASSERT(!mdt_object_remote(o));
+
+ memset(einfo, 0, sizeof(*einfo));
+
+ rc = mdt_reint_object_lock(info, o, lh, ibits, cos_incompat);
+ if (rc)
+ return rc;
+
+ rc = mdt_object_striped(info, o);
+ if (rc != 1) {
+ if (rc < 0)
+ mdt_object_unlock(info, o, lh, rc);
+ return rc;
+ }
+
+ rc = mdt_lock_slaves(info, o, lh->mlh_reg_mode, ibits, einfo);
+ if (rc) {
+ mdt_object_unlock(info, o, lh, rc);
+ if (rc == -EIO && OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_SLAVE_NAME))
+ rc = 0;
+ }
+
+ return rc;
+}
+
+static inline void
+mdt_reint_striped_unlock(struct mdt_thread_info *info, struct mdt_object *o,
+ struct mdt_lock_handle *lh,
+ struct ldlm_enqueue_info *einfo, int decref)
+{
+ if (einfo->ei_cbdata)
+ mdt_unlock_slaves(info, o, einfo, decref);
+ mdt_object_unlock(info, o, lh, decref);
+}
+