#include <lu_object.h>
#include <dt_object.h>
#include <md_object.h>
-#include <lustre_linkea.h>
#include <lustre_fid.h>
#include <lustre_lib.h>
#include <lustre_net.h>
if (!lfsck->li_drop_dryrun ||
lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) {
ns->ln_status = LS_SCANNING_PHASE2;
- cfs_list_del_init(&com->lc_link);
- cfs_list_add_tail(&com->lc_link,
- &lfsck->li_list_double_scan);
- if (!cfs_list_empty(&com->lc_link_dir))
- cfs_list_del_init(&com->lc_link_dir);
+ list_move_tail(&com->lc_link,
+ &lfsck->li_list_double_scan);
+ if (!list_empty(&com->lc_link_dir))
+ list_del_init(&com->lc_link_dir);
lfsck_pos_set_zero(pos);
} else {
ns->ln_status = LS_SCANNING_PHASE1;
ns->ln_objs_nlink_repaired = 0;
ns->ln_objs_lost_found = 0;
fid_zero(&ns->ln_fid_latest_scanned_phase2);
- if (cfs_list_empty(&com->lc_link_dir))
- cfs_list_add_tail(&com->lc_link_dir,
- &lfsck->li_list_dir);
+ if (list_empty(&com->lc_link_dir))
+ list_add_tail(&com->lc_link_dir,
+ &lfsck->li_list_dir);
*pos = ns->ln_pos_first_inconsistent;
}
} else {
ns->ln_status = LS_SCANNING_PHASE1;
- if (cfs_list_empty(&com->lc_link_dir))
- cfs_list_add_tail(&com->lc_link_dir,
- &lfsck->li_list_dir);
+ if (list_empty(&com->lc_link_dir))
+ list_add_tail(&com->lc_link_dir,
+ &lfsck->li_list_dir);
if (!lfsck->li_drop_dryrun ||
lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) {
*pos = ns->ln_pos_last_checkpoint;
ns->ln_status = LS_SCANNING_PHASE2;
ns->ln_flags |= LF_SCANNED_ONCE;
ns->ln_flags &= ~LF_UPGRADE;
- cfs_list_del_init(&com->lc_link);
- cfs_list_del_init(&com->lc_link_dir);
- cfs_list_add_tail(&com->lc_link, &lfsck->li_list_double_scan);
+ list_del_init(&com->lc_link_dir);
+ list_move_tail(&com->lc_link, &lfsck->li_list_double_scan);
} else if (result == 0) {
ns->ln_status = lfsck->li_status;
if (ns->ln_status == 0)
ns->ln_status = LS_STOPPED;
if (ns->ln_status != LS_PAUSED) {
- cfs_list_del_init(&com->lc_link);
- cfs_list_del_init(&com->lc_link_dir);
- cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+ list_del_init(&com->lc_link_dir);
+ list_move_tail(&com->lc_link, &lfsck->li_list_idle);
}
} else {
ns->ln_status = LS_FAILED;
- cfs_list_del_init(&com->lc_link);
- cfs_list_del_init(&com->lc_link_dir);
- cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+ list_del_init(&com->lc_link_dir);
+ list_move_tail(&com->lc_link, &lfsck->li_list_idle);
}
spin_unlock(&lfsck->li_lock);
.lfsck_query = lfsck_namespace_query,
};
+/**
+ * Verify the specified linkEA entry for the given directory object.
+ * If the object has no such linkEA entry or it has more other linkEA
+ * entries, then re-generate the linkEA with the given information.
+ *
+ * \param[in] env pointer to the thread context
+ * \param[in] dev pointer to the dt_device
+ * \param[in] obj pointer to the dt_object to be handled
+ * \param[in] cname the name for the child in the parent directory
+ * \param[in] pfid the parent directory's FID for the linkEA
+ *
+ * \retval 0 for success
+ * \retval negative error number on failure
+ */
+int lfsck_verify_linkea(const struct lu_env *env, struct dt_device *dev,
+ struct dt_object *obj, const struct lu_name *cname,
+ const struct lu_fid *pfid)
+{
+ struct linkea_data ldata = { 0 };
+ struct lu_buf linkea_buf;
+ struct thandle *th;
+ int rc;
+ int fl = LU_XATTR_CREATE;
+ bool dirty = false;
+ ENTRY;
+
+ LASSERT(S_ISDIR(lfsck_object_type(obj)));
+
+ rc = lfsck_links_read(env, obj, &ldata);
+ if (rc == -ENODATA) {
+ dirty = true;
+ } else if (rc == 0) {
+ fl = LU_XATTR_REPLACE;
+ if (ldata.ld_leh->leh_reccount != 1) {
+ dirty = true;
+ } else {
+ rc = linkea_links_find(&ldata, cname, pfid);
+ if (rc != 0)
+ dirty = true;
+ }
+ }
+
+ if (!dirty)
+ RETURN(rc);
+
+ rc = linkea_data_new(&ldata, &lfsck_env_info(env)->lti_linkea_buf);
+ if (rc != 0)
+ RETURN(rc);
+
+ rc = linkea_add_buf(&ldata, cname, pfid);
+ if (rc != 0)
+ RETURN(rc);
+
+ linkea_buf.lb_buf = ldata.ld_buf->lb_buf;
+ linkea_buf.lb_len = ldata.ld_leh->leh_len;
+ th = dt_trans_create(env, dev);
+ if (IS_ERR(th))
+ RETURN(PTR_ERR(th));
+
+ rc = dt_declare_xattr_set(env, obj, &linkea_buf,
+ XATTR_NAME_LINK, fl, th);
+ if (rc != 0)
+ GOTO(stop, rc = PTR_ERR(th));
+
+ rc = dt_trans_start_local(env, dev, th);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ dt_write_lock(env, obj, 0);
+ rc = dt_xattr_set(env, obj, &linkea_buf,
+ XATTR_NAME_LINK, fl, th, BYPASS_CAPA);
+ dt_write_unlock(env, obj);
+
+ GOTO(stop, rc);
+
+stop:
+ dt_trans_stop(env, dev, th);
+ return rc;
+}
+
int lfsck_namespace_setup(const struct lu_env *env,
struct lfsck_instance *lfsck)
{
if (com == NULL)
RETURN(-ENOMEM);
- CFS_INIT_LIST_HEAD(&com->lc_link);
- CFS_INIT_LIST_HEAD(&com->lc_link_dir);
+ INIT_LIST_HEAD(&com->lc_link);
+ INIT_LIST_HEAD(&com->lc_link_dir);
init_rwsem(&com->lc_sem);
atomic_set(&com->lc_ref, 1);
com->lc_lfsck = lfsck;
case LS_FAILED:
case LS_STOPPED:
spin_lock(&lfsck->li_lock);
- cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+ list_add_tail(&com->lc_link, &lfsck->li_list_idle);
spin_unlock(&lfsck->li_lock);
break;
default:
case LS_PAUSED:
case LS_CRASHED:
spin_lock(&lfsck->li_lock);
- cfs_list_add_tail(&com->lc_link, &lfsck->li_list_scan);
- cfs_list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir);
+ list_add_tail(&com->lc_link, &lfsck->li_list_scan);
+ list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir);
spin_unlock(&lfsck->li_lock);
break;
}