+ * Repair invalid name entry.
+ *
+ * If the name entry contains invalid information, such as bad file type
+ * or (and) corrupted object FID, then either remove the name entry or
+ * udpate the name entry with the given (right) information.
+ *
+ * \param[in] env pointer to the thread context
+ * \param[in] com pointer to the lfsck component
+ * \param[in] parent pointer to the parent directory
+ * \param[in] child pointer to the object referenced by the name entry
+ * \param[in] name the old name of the child under the parent directory
+ * \param[in] name2 the new name of the child under the parent directory
+ * \param[in] type the type claimed by the name entry
+ * \param[in] update update the name entry if true; otherwise, remove it
+ * \param[in] dec decrease the parent nlink count if true
+ *
+ * \retval positive number for repaired successfully
+ * \retval 0 if nothing to be repaired
+ * \retval negative error number on failure
+ */
+int lfsck_namespace_repair_dirent(const struct lu_env *env,
+ struct lfsck_component *com,
+ struct dt_object *parent,
+ struct dt_object *child,
+ const char *name, const char *name2,
+ __u16 type, bool update, bool dec)
+{
+ struct lfsck_thread_info *info = lfsck_env_info(env);
+ struct dt_insert_rec *rec = &info->lti_dt_rec;
+ const struct lu_fid *cfid = lfsck_dto2fid(child);
+ struct lu_fid *tfid = &info->lti_fid5;
+ struct lfsck_instance *lfsck = com->lc_lfsck;
+ struct dt_device *dev = lfsck->li_next;
+ struct thandle *th = NULL;
+ struct lustre_handle lh = { 0 };
+ int rc = 0;
+ ENTRY;
+
+ if (unlikely(!dt_try_as_dir(env, parent)))
+ GOTO(log, rc = -ENOTDIR);
+
+ rc = lfsck_ibits_lock(env, lfsck, parent, &lh,
+ MDS_INODELOCK_UPDATE, LCK_EX);
+ if (rc != 0)
+ GOTO(log, rc);
+
+ th = dt_trans_create(env, dev);
+ if (IS_ERR(th))
+ GOTO(unlock1, rc = PTR_ERR(th));
+
+ rc = dt_declare_delete(env, parent, (const struct dt_key *)name, th);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ if (update) {
+ rec->rec_type = lfsck_object_type(child) & S_IFMT;
+ rec->rec_fid = cfid;
+ rc = dt_declare_insert(env, parent,
+ (const struct dt_rec *)rec,
+ (const struct dt_key *)name2, th);
+ if (rc != 0)
+ GOTO(stop, rc);
+ }
+
+ if (dec) {
+ rc = dt_declare_ref_del(env, parent, th);
+ if (rc != 0)
+ GOTO(stop, rc);
+ }
+
+ rc = dt_trans_start(env, dev, th);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ dt_write_lock(env, parent, 0);
+ rc = dt_lookup(env, parent, (struct dt_rec *)tfid,
+ (const struct dt_key *)name, BYPASS_CAPA);
+ /* Someone has removed the bad name entry by race. */
+ if (rc == -ENOENT)
+ GOTO(unlock2, rc = 0);
+
+ if (rc != 0)
+ GOTO(unlock2, rc);
+
+ /* Someone has removed the bad name entry and reuse it for other
+ * object by race. */
+ if (!lu_fid_eq(tfid, cfid))
+ GOTO(unlock2, rc = 0);
+
+ if (lfsck->li_bookmark_ram.lb_param & LPF_DRYRUN)
+ GOTO(unlock2, rc = 1);
+
+ rc = dt_delete(env, parent, (const struct dt_key *)name, th,
+ BYPASS_CAPA);
+ if (rc != 0)
+ GOTO(unlock2, rc);
+
+ if (update) {
+ rc = dt_insert(env, parent,
+ (const struct dt_rec *)rec,
+ (const struct dt_key *)name2, th,
+ BYPASS_CAPA, 1);
+ if (rc != 0)
+ GOTO(unlock2, rc);
+ }
+
+ if (dec) {
+ rc = dt_ref_del(env, parent, th);
+ if (rc != 0)
+ GOTO(unlock2, rc);
+ }
+
+ GOTO(unlock2, rc = (rc == 0 ? 1 : rc));
+
+unlock2:
+ dt_write_unlock(env, parent);
+
+stop:
+ dt_trans_stop(env, dev, th);
+
+ /* We are not sure whether the child will become orphan or not.
+ * Record it in the LFSCK tracing file for further checking in
+ * the second-stage scanning. */
+ if (!update && !dec && rc == 0)
+ lfsck_namespace_trace_update(env, com, cfid,
+ LNTF_CHECK_LINKEA, true);
+
+unlock1:
+ lfsck_ibits_unlock(&lh, LCK_EX);
+
+log:
+ CDEBUG(D_LFSCK, "%s: namespace LFSCK assistant found bad name "
+ "entry for: parent "DFID", child "DFID", name %s, type "
+ "in name entry %o, type claimed by child %o. repair it "
+ "by %s with new name2 %s: rc = %d\n", lfsck_lfsck2name(lfsck),
+ PFID(lfsck_dto2fid(parent)), PFID(lfsck_dto2fid(child)),
+ name, type, update ? lfsck_object_type(child) : 0,
+ update ? "updating" : "removing", name2, rc);
+
+ if (rc != 0) {
+ struct lfsck_namespace *ns = com->lc_file_ram;
+
+ ns->ln_flags |= LF_INCONSISTENT;
+ }
+
+ return rc;
+}
+
+/**