RETURN(rc);
}
-/**
- * Request the specified ibits lock for the given object.
- *
- * Before the LFSCK modifying on the namespace visible object,
- * it needs to acquire related ibits ldlm lock.
- *
- * \param[in] env pointer to the thread context
- * \param[in] lfsck pointer to the lfsck instance
- * \param[in] obj pointer to the dt_object to be locked
- * \param[out] lh pointer to the lock handle
- * \param[in] ibits the bits for the ldlm lock to be acquired
- * \param[in] mode the mode for the ldlm lock to be acquired
- *
- * \retval 0 for success
- * \retval negative error number on failure
- */
-int lfsck_ibits_lock(const struct lu_env *env, struct lfsck_instance *lfsck,
- struct dt_object *obj, struct lustre_handle *lh,
- __u64 bits, ldlm_mode_t mode)
+static int __lfsck_ibits_lock(const struct lu_env *env,
+ struct lfsck_instance *lfsck,
+ struct dt_object *obj,
+ struct ldlm_res_id *resid,
+ struct lustre_handle *lh,
+ __u64 bits, ldlm_mode_t mode)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
ldlm_policy_data_t *policy = &info->lti_policy;
- struct ldlm_res_id *resid = &info->lti_resid;
__u64 flags = LDLM_FL_ATOMIC_CB;
int rc;
memset(policy, 0, sizeof(*policy));
policy->l_inodebits.bits = bits;
- fid_build_reg_res_name(lfsck_dto2fid(obj), resid);
if (dt_object_remote(obj)) {
struct ldlm_enqueue_info *einfo = &info->lti_einfo;
}
/**
+ * Request the specified ibits lock for the given object.
+ *
+ * Before the LFSCK modifying on the namespace visible object,
+ * it needs to acquire related ibits ldlm lock.
+ *
+ * \param[in] env pointer to the thread context
+ * \param[in] lfsck pointer to the lfsck instance
+ * \param[in] obj pointer to the dt_object to be locked
+ * \param[out] lh pointer to the lock handle
+ * \param[in] bits the bits for the ldlm lock to be acquired
+ * \param[in] mode the mode for the ldlm lock to be acquired
+ *
+ * \retval 0 for success
+ * \retval negative error number on failure
+ */
+int lfsck_ibits_lock(const struct lu_env *env, struct lfsck_instance *lfsck,
+ struct dt_object *obj, struct lustre_handle *lh,
+ __u64 bits, ldlm_mode_t mode)
+{
+ struct ldlm_res_id *resid = &lfsck_env_info(env)->lti_resid;
+
+ LASSERT(!lustre_handle_is_used(lh));
+
+ fid_build_reg_res_name(lfsck_dto2fid(obj), resid);
+ return __lfsck_ibits_lock(env, lfsck, obj, resid, lh, bits, mode);
+}
+
+/**
* Release the the specified ibits lock.
*
* If the lock has been acquired before, release it
}
}
+/**
+ * Request compound ibits locks for the given <obj, name> pairs.
+ *
+ * Before the LFSCK modifying on the namespace visible object, it needs to
+ * acquire related ibits ldlm lock. Usually, we can use lfsck_ibits_lock for
+ * the lock purpose. But the simple lfsck_ibits_lock for directory-based
+ * modificationis (such as insert name entry to the directory) may be too
+ * coarse-grained and not efficient.
+ *
+ * The lfsck_lock() will request compound ibits locks on the specified
+ * <obj, name> pairs: the PDO (Parallel Directory Operations) ibits (UPDATE)
+ * lock on the directory object, and the regular ibits lock on the name hash.
+ *
+ * \param[in] env pointer to the thread context
+ * \param[in] lfsck pointer to the lfsck instance
+ * \param[in] obj pointer to the dt_object to be locked
+ * \param[in] name used for building the PDO lock resource
+ * \param[out] llh pointer to the lfsck_lock_handle
+ * \param[in] bits the bits for the ldlm lock to be acquired
+ * \param[in] mode the mode for the ldlm lock to be acquired
+ *
+ * \retval 0 for success
+ * \retval negative error number on failure
+ */
+int lfsck_lock(const struct lu_env *env, struct lfsck_instance *lfsck,
+ struct dt_object *obj, const char *name,
+ struct lfsck_lock_handle *llh, __u64 bits, ldlm_mode_t mode)
+{
+ struct ldlm_res_id *resid = &lfsck_env_info(env)->lti_resid;
+ int rc;
+
+ LASSERT(S_ISDIR(lfsck_object_type(obj)));
+ LASSERT(name != NULL);
+ LASSERT(!lustre_handle_is_used(&llh->llh_pdo_lh));
+ LASSERT(!lustre_handle_is_used(&llh->llh_reg_lh));
+
+ switch (mode) {
+ case LCK_EX:
+ llh->llh_pdo_mode = LCK_EX;
+ break;
+ case LCK_PW:
+ llh->llh_pdo_mode = LCK_CW;
+ break;
+ case LCK_PR:
+ llh->llh_pdo_mode = LCK_CR;
+ break;
+ default:
+ CDEBUG(D_LFSCK, "%s: unexpected PDO lock mode %u on the obj "
+ DFID"\n", lfsck_lfsck2name(lfsck), mode,
+ PFID(lfsck_dto2fid(obj)));
+ LBUG();
+ }
+
+ fid_build_reg_res_name(lfsck_dto2fid(obj), resid);
+ rc = __lfsck_ibits_lock(env, lfsck, obj, resid, &llh->llh_pdo_lh,
+ MDS_INODELOCK_UPDATE, llh->llh_pdo_mode);
+ if (rc != 0)
+ return rc;
+
+ llh->llh_reg_mode = mode;
+ resid->name[LUSTRE_RES_ID_HSH_OFF] = full_name_hash(name, strlen(name));
+ rc = __lfsck_ibits_lock(env, lfsck, obj, resid, &llh->llh_reg_lh,
+ bits, llh->llh_reg_mode);
+ if (rc != 0)
+ lfsck_ibits_unlock(&llh->llh_pdo_lh, llh->llh_pdo_mode);
+
+ return rc;
+}
+
+/**
+ * Release the the compound ibits locks.
+ *
+ * \param[in] llh pointer to the lfsck_lock_handle to be released
+ */
+void lfsck_unlock(struct lfsck_lock_handle *llh)
+{
+ lfsck_ibits_unlock(&llh->llh_reg_lh, llh->llh_reg_mode);
+ lfsck_ibits_unlock(&llh->llh_pdo_lh, llh->llh_pdo_mode);
+}
+
int lfsck_find_mdt_idx_by_fid(const struct lu_env *env,
struct lfsck_instance *lfsck,
const struct lu_fid *fid)
struct dt_object *parent = lfsck->li_lpf_root_obj;
struct dt_device *dev = lfsck_obj2dev(parent);
struct thandle *th;
- struct lustre_handle lh = { 0 };
+ struct lfsck_lock_handle *llh = &lfsck_env_info(env)->lti_llh;
int rc;
ENTRY;
- rc = lfsck_ibits_lock(env, lfsck, parent, &lh,
- MDS_INODELOCK_UPDATE, LCK_EX);
+ rc = lfsck_lock(env, lfsck, parent, name, llh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
if (rc != 0)
RETURN(rc);
dt_trans_stop(env, dev, th);
unlock:
- lfsck_ibits_unlock(&lh, LCK_EX);
+ lfsck_unlock(llh);
CDEBUG(D_LFSCK, "%s: remove name entry "DFID"/%s: rc = %d\n",
lfsck_lfsck2name(lfsck), PFID(lfsck_dto2fid(parent)), name, rc);
struct dt_object_format *dof = &info->lti_dof;
struct dt_object *parent = lfsck->li_lpf_root_obj;
struct dt_object *child = NULL;
- struct lustre_handle lh = { 0 };
+ struct lfsck_lock_handle *llh = &info->lti_llh;
char name[8];
int node = lfsck_dev_idx(lfsck);
int rc = 0;
LASSERT(parent != NULL);
LASSERT(lfsck->li_lpf_obj == NULL);
- rc = lfsck_ibits_lock(env, lfsck, parent, &lh,
- MDS_INODELOCK_UPDATE, LCK_EX);
+ rc = lfsck_lock(env, lfsck, parent, name, llh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
if (rc != 0)
RETURN(rc);
GOTO(unlock, rc);
unlock:
- lfsck_ibits_unlock(&lh, LCK_EX);
+ lfsck_unlock(llh);
if (rc != 0 && child != NULL && !IS_ERR(child))
lfsck_object_put(env, child);