static struct lfsck_namespace_req *
lfsck_namespace_assistant_req_init(struct lfsck_instance *lfsck,
+ struct lfsck_assistant_object *lso,
struct lu_dirent *ent, __u16 type)
{
struct lfsck_namespace_req *lnr;
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&lnr->lnr_lar.lar_list);
- lnr->lnr_lar.lar_fid = *lfsck_dto2fid(lfsck->li_obj_dir);
+ lnr->lnr_lar.lar_parent = lfsck_assistant_object_get(lso);
lnr->lnr_lmv = lfsck_lmv_get(lfsck->li_lmv);
lnr->lnr_fid = ent->lde_fid;
- lnr->lnr_oit_cookie = lfsck->li_pos_current.lp_oit_cookie;
lnr->lnr_dir_cookie = ent->lde_hash;
lnr->lnr_attr = ent->lde_attrs;
lnr->lnr_size = size;
if (lnr->lnr_lmv != NULL)
lfsck_lmv_put(env, lnr->lnr_lmv);
+ lfsck_assistant_object_put(env, lar->lar_parent);
OBD_FREE(lnr, lnr->lnr_size);
}
size = (ns->ln_bitmap_size + 7) >> 3;
rc = dt_xattr_get(env, obj,
lfsck_buf_get(env, bitmap->data, size),
- XATTR_NAME_LFSCK_BITMAP, BYPASS_CAPA);
+ XATTR_NAME_LFSCK_BITMAP);
if (rc != size)
RETURN(rc >= 0 ? -EINVAL : rc);
rc = dt_xattr_get(env, com->lc_obj,
lfsck_buf_get(env, com->lc_file_disk, len),
- XATTR_NAME_LFSCK_NAMESPACE, BYPASS_CAPA);
+ XATTR_NAME_LFSCK_NAMESPACE);
if (rc == len) {
struct lfsck_namespace *ns = com->lc_file_ram;
* If yes, it should be reset via returning -ESTALE. */
rc = dt_xattr_get(env, com->lc_obj,
lfsck_buf_get(env, com->lc_file_disk, len),
- XATTR_NAME_LFSCK_NAMESPACE_OLD, BYPASS_CAPA);
+ XATTR_NAME_LFSCK_NAMESPACE_OLD);
if (rc >= 0)
rc = -ESTALE;
}
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_namespace *ns = com->lc_file_ram;
struct lfsck_assistant_data *lad = com->lc_data;
+ struct dt_device *dev = lfsck_obj2dev(obj);
cfs_bitmap_t *bitmap = NULL;
struct thandle *handle;
__u32 nbits = 0;
ns->ln_bitmap_size = nbits;
lfsck_namespace_cpu_to_le((struct lfsck_namespace *)com->lc_file_disk,
ns);
- handle = dt_trans_create(env, lfsck->li_bottom);
+ handle = dt_trans_create(env, dev);
if (IS_ERR(handle))
GOTO(log, rc = PTR_ERR(handle));
}
#endif
- rc = dt_trans_start_local(env, lfsck->li_bottom, handle);
+ rc = dt_trans_start_local(env, dev, handle);
if (rc != 0)
GOTO(out, rc);
rc = dt_xattr_set(env, obj,
lfsck_buf_get(env, com->lc_file_disk, len),
- XATTR_NAME_LFSCK_NAMESPACE, 0, handle, BYPASS_CAPA);
+ XATTR_NAME_LFSCK_NAMESPACE, 0, handle);
if (rc == 0 && bitmap != NULL)
rc = dt_xattr_set(env, obj,
lfsck_buf_get(env, bitmap->data, nbits >> 3),
- XATTR_NAME_LFSCK_BITMAP, 0, handle,
- BYPASS_CAPA);
+ XATTR_NAME_LFSCK_BITMAP, 0, handle);
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 8, 53, 0)
if (rc == 0 && init)
rc = dt_xattr_set(env, obj, &tbuf,
XATTR_NAME_LFSCK_NAMESPACE_OLD,
- LU_XATTR_CREATE, handle, BYPASS_CAPA);
+ LU_XATTR_CREATE, handle);
#endif
GOTO(out, rc);
out:
- dt_trans_stop(env, lfsck->li_bottom, handle);
+ dt_trans_stop(env, dev, handle);
log:
if (rc != 0)
lfsck_namespace_load_one_trace_file(const struct lu_env *env,
struct lfsck_component *com,
struct dt_object *parent,
- const char *name,
- const struct dt_index_features *ft,
- bool reset)
+ const char *name, bool reset)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
struct dt_object *obj;
return ERR_PTR(rc);
}
- if (ft != NULL)
- obj = local_index_find_or_create(env, lfsck->li_los, parent,
- name, S_IFREG | S_IRUGO | S_IWUSR, ft);
- else
- obj = local_file_find_or_create(env, lfsck->li_los, parent,
- name, S_IFREG | S_IRUGO | S_IWUSR);
+ obj = local_index_find_or_create(env, lfsck->li_los, parent, name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ &dt_lfsck_features);
return obj;
}
if (!reset)
continue;
- lu_object_put(env, &lsto->lsto_obj->do_lu);
+ lfsck_object_put(env, lsto->lsto_obj);
lsto->lsto_obj = NULL;
}
obj = lfsck_namespace_load_one_trace_file(env, com,
- com->lc_lfsck->li_lfsck_dir,
- name, &dt_lfsck_features, reset);
+ com->lc_lfsck->li_lfsck_dir, name, reset);
if (IS_ERR(obj))
return PTR_ERR(obj);
* trace file
* \param[in] add true if add new flags, otherwise remove flags
*
- * \retval 0 for succeed or nothing to be done
+ * \retval 0 for success or nothing to be done
* \retval negative error number on failure
*/
int lfsck_namespace_trace_update(const struct lu_env *env,
struct lfsck_instance *lfsck = com->lc_lfsck;
struct dt_object *obj;
struct lu_fid *key = &lfsck_env_info(env)->lti_fid3;
- struct dt_device *dev = lfsck->li_bottom;
+ struct dt_device *dev;
struct thandle *th = NULL;
int idx;
int rc = 0;
idx = lfsck_sub_trace_file_fid2idx(fid);
obj = com->lc_sub_trace_objs[idx].lsto_obj;
+ dev = lfsck_obj2dev(obj);
mutex_lock(&com->lc_sub_trace_objs[idx].lsto_mutex);
fid_cpu_to_be(key, fid);
rc = dt_lookup(env, obj, (struct dt_rec *)&old,
- (const struct dt_key *)key, BYPASS_CAPA);
+ (const struct dt_key *)key);
if (rc == -ENOENT) {
if (!add)
GOTO(unlock, rc = 0);
GOTO(log, rc);
if (old != 0) {
- rc = dt_delete(env, obj, (const struct dt_key *)key,
- th, BYPASS_CAPA);
+ rc = dt_delete(env, obj, (const struct dt_key *)key, th);
if (rc != 0)
GOTO(log, rc);
}
if (new != 0) {
rc = dt_insert(env, obj, (const struct dt_rec *)&new,
- (const struct dt_key *)key, th, BYPASS_CAPA, 1);
+ (const struct dt_key *)key, th, 1);
if (rc != 0)
GOTO(log, rc);
}
RETURN(LFSCK_NAMEENTRY_DEAD);
rc = dt_lookup(env, dir, (struct dt_rec *)fid,
- (const struct dt_key *)name, BYPASS_CAPA);
+ (const struct dt_key *)name);
if (rc == -ENOENT)
RETURN(LFSCK_NAMEENTRY_REMOVED);
if (!dt_object_exists(obj))
return -ENOENT;
- rc = dt_xattr_get(env, obj, ldata->ld_buf, XATTR_NAME_LINK, BYPASS_CAPA);
+ rc = dt_xattr_get(env, obj, ldata->ld_buf, XATTR_NAME_LINK);
if (rc == -ERANGE) {
/* Buf was too small, figure out what we need. */
- rc = dt_xattr_get(env, obj, &LU_BUF_NULL, XATTR_NAME_LINK,
- BYPASS_CAPA);
+ rc = dt_xattr_get(env, obj, &LU_BUF_NULL, XATTR_NAME_LINK);
if (rc <= 0)
return rc;
if (ldata->ld_buf->lb_buf == NULL)
return -ENOMEM;
- rc = dt_xattr_get(env, obj, ldata->ld_buf, XATTR_NAME_LINK,
- BYPASS_CAPA);
+ rc = dt_xattr_get(env, obj, ldata->ld_buf, XATTR_NAME_LINK);
}
if (rc > 0)
struct dt_object *obj)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
- struct dt_device *dev = lfsck->li_bottom;
+ struct dt_device *dev = lfsck_obj2dev(obj);
struct thandle *th = NULL;
int rc = 0;
ENTRY;
if (lfsck->li_bookmark_ram.lb_param & LPF_DRYRUN)
GOTO(unlock, rc = 0);
- rc = dt_xattr_del(env, obj, XATTR_NAME_LINK, th, BYPASS_CAPA);
+ rc = dt_xattr_del(env, obj, XATTR_NAME_LINK, th);
GOTO(unlock, rc);
ldata->ld_buf->lb_buf,
ldata->ld_leh->leh_len);
- return dt_xattr_set(env, obj, buf, XATTR_NAME_LINK, 0, handle,
- BYPASS_CAPA);
+ return dt_xattr_set(env, obj, buf, XATTR_NAME_LINK, 0, handle);
}
static void lfsck_namespace_unpack_linkea_entry(struct linkea_data *ldata,
struct lfsck_thread_info *info = lfsck_env_info(env);
struct lu_name *cname = &info->lti_name;
struct dt_insert_rec *rec = &info->lti_dt_rec;
- struct lu_attr *la = &info->lti_la3;
+ struct lu_attr *la = &info->lti_la2;
const struct lu_fid *cfid = lfsck_dto2fid(orphan);
const struct lu_fid *pfid;
struct lu_fid tfid;
struct lfsck_instance *lfsck = com->lc_lfsck;
- struct dt_device *dev = lfsck->li_bottom;
+ struct dt_device *dev = lfsck_obj2dev(orphan);
struct dt_object *parent;
struct thandle *th = NULL;
- struct lustre_handle plh = { 0 };
+ struct lfsck_lock_handle *pllh = &info->lti_llh;
struct lustre_handle clh = { 0 };
struct linkea_data ldata = { NULL };
struct lu_buf linkea_buf;
parent = lfsck->li_lpf_obj;
pfid = lfsck_dto2fid(parent);
- /* Hold update lock on the parent to prevent others to access. */
- rc = lfsck_ibits_lock(env, lfsck, parent, &plh,
- MDS_INODELOCK_UPDATE, LCK_EX);
- if (rc != 0)
- GOTO(log, rc);
-
+again:
do {
namelen = snprintf(info->lti_key, NAME_MAX, DFID"%s-%s-%d",
PFID(cfid), infix, type, idx++);
rc = dt_lookup(env, parent, (struct dt_rec *)&tfid,
- (const struct dt_key *)info->lti_key,
- BYPASS_CAPA);
+ (const struct dt_key *)info->lti_key);
if (rc != 0 && rc != -ENOENT)
GOTO(log, rc);
exist = true;
} while (rc == 0 && !exist);
+ rc = lfsck_lock(env, lfsck, parent, info->lti_key, pllh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
+ if (rc != 0)
+ GOTO(log, rc);
+
+ /* Re-check whether the name conflict with othrs after taken
+ * the ldlm lock. */
+ rc = dt_lookup(env, parent, (struct dt_rec *)&tfid,
+ (const struct dt_key *)info->lti_key);
+ if (rc == 0) {
+ if (!lu_fid_eq(cfid, &tfid)) {
+ exist = false;
+ lfsck_unlock(pllh);
+ goto again;
+ }
+
+ exist = true;
+ } else if (rc != -ENOENT) {
+ GOTO(log, rc);
+ } else {
+ exist = false;
+ }
+
cname->ln_name = info->lti_key;
cname->ln_namelen = namelen;
rc = linkea_data_new(&ldata, &info->lti_linkea_buf2);
GOTO(log, rc);
rc = lfsck_ibits_lock(env, lfsck, orphan, &clh,
- MDS_INODELOCK_UPDATE | MDS_INODELOCK_LOOKUP,
- LCK_EX);
+ MDS_INODELOCK_UPDATE | MDS_INODELOCK_LOOKUP |
+ MDS_INODELOCK_XATTR, LCK_EX);
if (rc != 0)
GOTO(log, rc);
if (S_ISDIR(lfsck_object_type(orphan))) {
rc = dt_delete(env, orphan,
- (const struct dt_key *)dotdot, th,
- BYPASS_CAPA);
+ (const struct dt_key *)dotdot, th);
if (rc != 0)
GOTO(unlock, rc);
rec->rec_type = S_IFDIR;
rec->rec_fid = pfid;
rc = dt_insert(env, orphan, (const struct dt_rec *)rec,
- (const struct dt_key *)dotdot, th,
- BYPASS_CAPA, 1);
+ (const struct dt_key *)dotdot, th, 1);
if (rc != 0)
GOTO(unlock, rc);
}
rc = dt_xattr_set(env, orphan, &linkea_buf, XATTR_NAME_LINK, 0,
- th, BYPASS_CAPA);
+ th);
} else {
if (rc == 0 && count != NULL)
*count = ldata.ld_leh->leh_reccount;
rec->rec_type = lfsck_object_type(orphan) & S_IFMT;
rec->rec_fid = cfid;
rc = dt_insert(env, parent, (const struct dt_rec *)rec,
- (const struct dt_key *)cname->ln_name,
- th, BYPASS_CAPA, 1);
+ (const struct dt_key *)cname->ln_name, th, 1);
if (rc == 0 && S_ISDIR(rec->rec_type)) {
dt_write_lock(env, parent, 0);
rc = dt_ref_add(env, parent, th);
}
if (rc == 0)
- rc = dt_attr_set(env, orphan, la, th, BYPASS_CAPA);
+ rc = dt_attr_set(env, orphan, la, th);
GOTO(stop, rc = (rc == 0 ? 1 : rc));
log:
lfsck_ibits_unlock(&clh, LCK_EX);
- lfsck_ibits_unlock(&plh, LCK_EX);
+ lfsck_unlock(pllh);
CDEBUG(D_LFSCK, "%s: namespace LFSCK insert orphan for the "
"object "DFID", name = %s: rc = %d\n",
lfsck_lfsck2name(lfsck), PFID(cfid),
struct lu_attr *la = &info->lti_la;
struct dt_insert_rec *rec = &info->lti_dt_rec;
struct lfsck_instance *lfsck = com->lc_lfsck;
+ /* The child and its name may be on different MDTs. */
struct dt_device *dev = lfsck->li_next;
+ struct dt_object *pobj = NULL;
+ struct dt_object *cobj = NULL;
struct thandle *th = NULL;
- struct lustre_handle lh = { 0 };
+ struct lfsck_lock_handle *llh = &info->lti_llh;
int rc = 0;
ENTRY;
- if (unlikely(!dt_try_as_dir(env, parent)))
+ /* @parent/@child may be based on lfsck->li_bottom,
+ * but here we need the object based on the lfsck->li_next. */
+
+ pobj = lfsck_object_locate(dev, parent);
+ if (IS_ERR(pobj))
+ GOTO(log, rc = PTR_ERR(pobj));
+
+ if (unlikely(!dt_try_as_dir(env, pobj)))
GOTO(log, rc = -ENOTDIR);
+ cobj = lfsck_object_locate(dev, child);
+ if (IS_ERR(cobj))
+ GOTO(log, rc = PTR_ERR(cobj));
+
if (lfsck->li_bookmark_ram.lb_param & LPF_DRYRUN)
GOTO(log, rc = 1);
- /* Hold update lock on the parent to prevent others to access. */
- 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)
GOTO(log, rc);
if (IS_ERR(th))
GOTO(unlock, rc = PTR_ERR(th));
- rec->rec_type = lfsck_object_type(child) & S_IFMT;
- rec->rec_fid = lfsck_dto2fid(child);
- rc = dt_declare_insert(env, parent, (const struct dt_rec *)rec,
+ rec->rec_type = lfsck_object_type(cobj) & S_IFMT;
+ rec->rec_fid = lfsck_dto2fid(cobj);
+ rc = dt_declare_insert(env, pobj, (const struct dt_rec *)rec,
(const struct dt_key *)name, th);
if (rc != 0)
GOTO(stop, rc);
if (S_ISDIR(rec->rec_type)) {
- rc = dt_declare_ref_add(env, parent, th);
+ rc = dt_declare_ref_add(env, pobj, th);
if (rc != 0)
GOTO(stop, rc);
}
memset(la, 0, sizeof(*la));
la->la_ctime = cfs_time_current_sec();
la->la_valid = LA_CTIME;
- rc = dt_declare_attr_set(env, parent, la, th);
+ rc = dt_declare_attr_set(env, pobj, la, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_declare_attr_set(env, child, la, th);
+ rc = dt_declare_attr_set(env, cobj, la, th);
if (rc != 0)
GOTO(stop, rc);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_insert(env, parent, (const struct dt_rec *)rec,
- (const struct dt_key *)name, th, BYPASS_CAPA, 1);
+ rc = dt_insert(env, pobj, (const struct dt_rec *)rec,
+ (const struct dt_key *)name, th, 1);
if (rc != 0)
GOTO(stop, rc);
if (S_ISDIR(rec->rec_type)) {
- dt_write_lock(env, parent, 0);
- rc = dt_ref_add(env, parent, th);
- dt_write_unlock(env, parent);
+ dt_write_lock(env, pobj, 0);
+ rc = dt_ref_add(env, pobj, th);
+ dt_write_unlock(env, pobj);
if (rc != 0)
GOTO(stop, rc);
}
la->la_ctime = cfs_time_current_sec();
- rc = dt_attr_set(env, parent, la, th, BYPASS_CAPA);
+ rc = dt_attr_set(env, pobj, la, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_attr_set(env, child, la, th, BYPASS_CAPA);
+ rc = dt_attr_set(env, cobj, la, th);
GOTO(stop, rc = (rc == 0 ? 1 : rc));
dt_trans_stop(env, dev, th);
unlock:
- lfsck_ibits_unlock(&lh, LCK_EX);
+ lfsck_unlock(llh);
log:
CDEBUG(D_LFSCK, "%s: namespace LFSCK insert object "DFID" with "
struct lu_fid tfid;
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_namespace *ns = com->lc_file_ram;
- struct dt_device *dev;
+ struct dt_device *dev = lfsck_obj2dev(orphan);
struct dt_object *parent = NULL;
- struct dt_object *child = NULL;
struct thandle *th = NULL;
- struct lustre_handle lh = { 0 };
+ struct lfsck_lock_handle *llh = &info->lti_llh;
struct linkea_data ldata = { NULL };
struct lu_buf linkea_buf;
struct lu_buf lmv_buf;
snprintf(name, 8, "MDT%04x", idx);
rc = dt_lookup(env, lfsck->li_lpf_root_obj,
(struct dt_rec *)&tfid,
- (const struct dt_key *)name, BYPASS_CAPA);
+ (const struct dt_key *)name);
if (rc != 0)
GOTO(log, rc = (rc == -ENOENT ? -ENXIO : rc));
if (IS_ERR(dev))
GOTO(log, rc = PTR_ERR(dev));
- child = lfsck_object_find_by_dev(env, dev, cfid);
- if (IS_ERR(child))
- GOTO(log, rc = PTR_ERR(child));
-
- /* Hold update lock on the parent to prevent others to access. */
- rc = lfsck_ibits_lock(env, lfsck, parent, &lh,
- MDS_INODELOCK_UPDATE, LCK_EX);
- if (rc != 0)
- GOTO(log, rc);
-
idx = 0;
+
+again:
do {
namelen = snprintf(name, 31, DFID"-P-%d",
PFID(cfid), idx++);
rc = dt_lookup(env, parent, (struct dt_rec *)&tfid,
- (const struct dt_key *)name, BYPASS_CAPA);
+ (const struct dt_key *)name);
if (rc != 0 && rc != -ENOENT)
- GOTO(unlock1, rc);
+ GOTO(log, rc);
} while (rc == 0);
+ rc = lfsck_lock(env, lfsck, parent, name, llh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
+ if (rc != 0)
+ GOTO(log, rc);
+
+ /* Re-check whether the name conflict with othrs after taken
+ * the ldlm lock. */
+ rc = dt_lookup(env, parent, (struct dt_rec *)&tfid,
+ (const struct dt_key *)name);
+ if (unlikely(rc == 0)) {
+ lfsck_unlock(llh);
+ goto again;
+ }
+
+ if (rc != -ENOENT)
+ GOTO(unlock1, rc);
+
cname->ln_name = name;
cname->ln_namelen = namelen;
la->la_valid = LA_TYPE | LA_MODE | LA_UID | LA_GID |
LA_ATIME | LA_MTIME | LA_CTIME;
- child->do_ops->do_ah_init(env, hint, parent, child,
- la->la_mode & S_IFMT);
+ orphan->do_ops->do_ah_init(env, hint, parent, orphan,
+ la->la_mode & S_IFMT);
memset(dof, 0, sizeof(*dof));
dof->dof_type = dt_mode_to_dft(S_IFDIR);
if (dt_object_remote(orphan))
th->th_sync = 1;
- rc = dt_declare_create(env, child, la, hint, dof, th);
+ rc = dt_declare_create(env, orphan, la, hint, dof, th);
if (rc != 0)
GOTO(stop, rc);
- if (unlikely(!dt_try_as_dir(env, child)))
+ if (unlikely(!dt_try_as_dir(env, orphan)))
GOTO(stop, rc = -ENOTDIR);
rec->rec_type = S_IFDIR;
rec->rec_fid = cfid;
- rc = dt_declare_insert(env, child, (const struct dt_rec *)rec,
+ rc = dt_declare_insert(env, orphan, (const struct dt_rec *)rec,
(const struct dt_key *)dot, th);
if (rc != 0)
GOTO(stop, rc);
rec->rec_fid = lfsck_dto2fid(parent);
- rc = dt_declare_insert(env, child, (const struct dt_rec *)rec,
+ rc = dt_declare_insert(env, orphan, (const struct dt_rec *)rec,
(const struct dt_key *)dotdot, th);
if (rc == 0)
- rc = dt_declare_ref_add(env, child, th);
+ rc = dt_declare_ref_add(env, orphan, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_declare_ref_add(env, child, th);
+ rc = dt_declare_ref_add(env, orphan, th);
if (rc != 0)
GOTO(stop, rc);
if (lmv != NULL) {
lmv->lmv_magic = LMV_MAGIC;
- lmv->lmv_master_mdt_index = lfsck_dev_idx(dev);
+ lmv->lmv_master_mdt_index = lfsck_dev_idx(lfsck);
lfsck_lmv_header_cpu_to_le(lmv2, lmv);
lfsck_buf_init(&lmv_buf, lmv2, sizeof(*lmv2));
- rc = dt_declare_xattr_set(env, child, &lmv_buf,
+ rc = dt_declare_xattr_set(env, orphan, &lmv_buf,
XATTR_NAME_LMV, 0, th);
if (rc != 0)
GOTO(stop, rc);
lfsck_buf_init(&linkea_buf, ldata.ld_buf->lb_buf,
ldata.ld_leh->leh_len);
- rc = dt_declare_xattr_set(env, child, &linkea_buf,
+ rc = dt_declare_xattr_set(env, orphan, &linkea_buf,
XATTR_NAME_LINK, 0, th);
if (rc != 0)
GOTO(stop, rc);
if (rc != 0)
GOTO(stop, rc);
- dt_write_lock(env, child, 0);
- rc = dt_create(env, child, la, hint, dof, th);
+ dt_write_lock(env, orphan, 0);
+ rc = dt_create(env, orphan, la, hint, dof, th);
if (rc != 0)
GOTO(unlock2, rc);
rec->rec_fid = cfid;
- rc = dt_insert(env, child, (const struct dt_rec *)rec,
- (const struct dt_key *)dot, th, BYPASS_CAPA, 1);
+ rc = dt_insert(env, orphan, (const struct dt_rec *)rec,
+ (const struct dt_key *)dot, th, 1);
if (rc != 0)
GOTO(unlock2, rc);
rec->rec_fid = lfsck_dto2fid(parent);
- rc = dt_insert(env, child, (const struct dt_rec *)rec,
- (const struct dt_key *)dotdot, th,
- BYPASS_CAPA, 1);
+ rc = dt_insert(env, orphan, (const struct dt_rec *)rec,
+ (const struct dt_key *)dotdot, th, 1);
if (rc != 0)
GOTO(unlock2, rc);
- rc = dt_ref_add(env, child, th);
+ rc = dt_ref_add(env, orphan, th);
if (rc != 0)
GOTO(unlock2, rc);
if (lmv != NULL) {
- rc = dt_xattr_set(env, child, &lmv_buf, XATTR_NAME_LMV, 0,
- th, BYPASS_CAPA);
+ rc = dt_xattr_set(env, orphan, &lmv_buf, XATTR_NAME_LMV, 0, th);
if (rc != 0)
GOTO(unlock2, rc);
}
- rc = dt_xattr_set(env, child, &linkea_buf,
- XATTR_NAME_LINK, 0, th, BYPASS_CAPA);
- dt_write_unlock(env, child);
+ rc = dt_xattr_set(env, orphan, &linkea_buf,
+ XATTR_NAME_LINK, 0, th);
+ dt_write_unlock(env, orphan);
if (rc != 0)
GOTO(stop, rc);
rec->rec_fid = cfid;
rc = dt_insert(env, parent, (const struct dt_rec *)rec,
- (const struct dt_key *)name, th, BYPASS_CAPA, 1);
+ (const struct dt_key *)name, th, 1);
if (rc == 0) {
dt_write_lock(env, parent, 0);
rc = dt_ref_add(env, parent, th);
GOTO(stop, rc = (rc == 0 ? 1 : rc));
unlock2:
- dt_write_unlock(env, child);
+ dt_write_unlock(env, orphan);
stop:
dt_trans_stop(env, dev, th);
unlock1:
- lfsck_ibits_unlock(&lh, LCK_EX);
+ lfsck_unlock(llh);
log:
CDEBUG(D_LFSCK, "%s: namespace LFSCK create orphan dir for "
lfsck_lfsck2name(lfsck), PFID(cfid),
cname->ln_name != NULL ? cname->ln_name : "<NULL>", rc);
- if (child != NULL && !IS_ERR(child))
- lfsck_object_put(env, child);
-
if (parent != NULL && !IS_ERR(parent) && parent != lfsck->li_lpf_obj)
lfsck_object_put(env, parent);
bool next)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
- struct dt_device *dev = lfsck->li_bottom;
+ struct dt_device *dev = lfsck_obj2dev(obj);
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct thandle *th = NULL;
struct lustre_handle lh = { 0 };
ENTRY;
rc = lfsck_ibits_lock(env, lfsck, obj, &lh,
- MDS_INODELOCK_UPDATE |
- MDS_INODELOCK_XATTR, LCK_EX);
+ MDS_INODELOCK_UPDATE | MDS_INODELOCK_XATTR,
+ LCK_EX);
if (rc != 0)
GOTO(log, rc);
lfsck_buf_init(&linkea_buf, ldata_new.ld_buf->lb_buf,
ldata_new.ld_leh->leh_len);
- rc = dt_xattr_set(env, obj, &linkea_buf,
- XATTR_NAME_LINK, 0, th, BYPASS_CAPA);
+ rc = dt_xattr_set(env, obj, &linkea_buf, XATTR_NAME_LINK, 0, th);
GOTO(unlock2, rc = (rc == 0 ? 1 : rc));
struct lu_name *cname,
struct lu_fid *pfid)
{
- struct lu_fid *cfid = &lfsck_env_info(env)->lti_fid3;
- struct lustre_handle lh = { 0 };
- int rc;
+ struct lfsck_thread_info *info = lfsck_env_info(env);
+ struct lu_fid *cfid = &info->lti_fid3;
+ struct lfsck_lock_handle *llh = &info->lti_llh;
+ int rc;
ENTRY;
- rc = lfsck_ibits_lock(env, com->lc_lfsck, parent, &lh,
- MDS_INODELOCK_UPDATE, LCK_EX);
+ rc = lfsck_lock(env, com->lc_lfsck, parent, cname->ln_name, llh,
+ MDS_INODELOCK_UPDATE, LCK_PR);
if (rc != 0)
RETURN(rc);
dt_read_lock(env, parent, 0);
if (unlikely(lfsck_is_dead_obj(parent))) {
dt_read_unlock(env, parent);
- lfsck_ibits_unlock(&lh, LCK_EX);
+ lfsck_unlock(llh);
rc = lfsck_namespace_shrink_linkea(env, com, child, ldata,
cname, pfid, true);
}
rc = dt_lookup(env, parent, (struct dt_rec *)cfid,
- (const struct dt_key *)cname->ln_name,
- BYPASS_CAPA);
+ (const struct dt_key *)cname->ln_name);
dt_read_unlock(env, parent);
/* It is safe to release the ldlm lock, because when the logic come
* has removed the specified linkEA entry by race, then it is OK,
* because the subsequent lfsck_namespace_shrink_linkea() can handle
* such case. */
- lfsck_ibits_unlock(&lh, LCK_EX);
+ lfsck_unlock(llh);
if (rc == -ENOENT) {
rc = lfsck_namespace_shrink_linkea(env, com, child, ldata,
cname, pfid, true);
struct dt_insert_rec *rec = &info->lti_dt_rec;
struct lu_fid tfid;
struct lfsck_instance *lfsck = com->lc_lfsck;
+ /* The child and its name may be on different MDTs. */
struct dt_device *dev = lfsck->li_next;
const char *name = cname->ln_name;
- struct dt_object *obj = NULL;
- struct lustre_handle plh = { 0 };
+ struct dt_object *pobj = NULL;
+ struct dt_object *cobj = NULL;
+ struct lfsck_lock_handle *pllh = &info->lti_llh;
struct lustre_handle clh = { 0 };
struct linkea_data ldata = { NULL };
struct thandle *th = NULL;
int rc = 0;
ENTRY;
- rc = lfsck_ibits_lock(env, lfsck, parent, &plh,
- MDS_INODELOCK_UPDATE, LCK_EX);
+ /* @parent/@child may be based on lfsck->li_bottom,
+ * but here we need the object based on the lfsck->li_next. */
+
+ pobj = lfsck_object_locate(dev, parent);
+ if (IS_ERR(pobj))
+ GOTO(log, rc = PTR_ERR(pobj));
+
+ if (unlikely(!dt_try_as_dir(env, pobj)))
+ GOTO(log, rc = -ENOTDIR);
+
+ rc = lfsck_lock(env, lfsck, parent, name, pllh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
if (rc != 0)
GOTO(log, rc);
goto replace;
}
- obj = lfsck_object_find(env, lfsck, cfid);
- if (IS_ERR(obj)) {
- rc = PTR_ERR(obj);
+ cobj = lfsck_object_find_by_dev(env, dev, cfid);
+ if (IS_ERR(cobj)) {
+ rc = PTR_ERR(cobj);
if (rc == -ENOENT) {
exist = false;
goto replace;
GOTO(log, rc);
}
- if (!dt_object_exists(obj)) {
+ if (!dt_object_exists(cobj)) {
exist = false;
goto replace;
}
- rc = dt_lookup(env, parent, (struct dt_rec *)&tfid,
- (const struct dt_key *)name, BYPASS_CAPA);
+ rc = dt_lookup(env, pobj, (struct dt_rec *)&tfid,
+ (const struct dt_key *)name);
if (rc == -ENOENT) {
exist = false;
goto replace;
GOTO(log, rc = 0);
/* lock the object to be destroyed. */
- rc = lfsck_ibits_lock(env, lfsck, obj, &clh,
+ rc = lfsck_ibits_lock(env, lfsck, cobj, &clh,
MDS_INODELOCK_UPDATE |
- MDS_INODELOCK_XATTR, LCK_EX);
+ MDS_INODELOCK_UPDATE | MDS_INODELOCK_XATTR,
+ LCK_EX);
if (rc != 0)
GOTO(log, rc);
- if (unlikely(lfsck_is_dead_obj(obj))) {
+ if (unlikely(lfsck_is_dead_obj(cobj))) {
exist = false;
goto replace;
}
- rc = dt_attr_get(env, obj, la, BYPASS_CAPA);
+ rc = dt_attr_get(env, cobj, la);
if (rc != 0)
GOTO(log, rc);
GOTO(log, rc);
if (S_ISREG(la->la_mode)) {
- rc = dt_xattr_get(env, obj, &LU_BUF_NULL, XATTR_NAME_LOV,
- BYPASS_CAPA);
+ rc = dt_xattr_get(env, cobj, &LU_BUF_NULL, XATTR_NAME_LOV);
/* If someone has created related OST-object(s),
* then keep it. */
if ((rc > 0) || (rc < 0 && rc != -ENODATA))
if (rc != 0)
GOTO(log, rc);
- rc = linkea_links_find(&ldata, cname, lfsck_dto2fid(parent));
+ rc = linkea_links_find(&ldata, cname, lfsck_dto2fid(pobj));
/* Someone moved the child, no need to replace. */
if (rc != 0)
GOTO(log, rc = 0);
GOTO(log, rc = PTR_ERR(th));
if (exist) {
- rc = dt_declare_destroy(env, obj, th);
+ rc = dt_declare_destroy(env, cobj, th);
if (rc != 0)
GOTO(stop, rc);
}
- rc = dt_declare_delete(env, parent, (const struct dt_key *)name, th);
+ rc = dt_declare_delete(env, pobj, (const struct dt_key *)name, th);
if (rc != 0)
GOTO(stop, rc);
rec->rec_type = S_IFDIR;
rec->rec_fid = lfsck_dto2fid(child);
- rc = dt_declare_insert(env, parent, (const struct dt_rec *)rec,
+ rc = dt_declare_insert(env, pobj, (const struct dt_rec *)rec,
(const struct dt_key *)name, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_trans_start(env, dev, th);
+ rc = dt_trans_start_local(env, dev, th);
if (rc != 0)
GOTO(stop, rc);
if (exist) {
- rc = dt_destroy(env, obj, th);
+ rc = dt_destroy(env, cobj, th);
if (rc != 0)
GOTO(stop, rc);
}
/* The old name entry maybe not exist. */
- dt_delete(env, parent, (const struct dt_key *)name, th,
- BYPASS_CAPA);
+ rc = dt_delete(env, pobj, (const struct dt_key *)name, th);
+ if (rc != 0 && rc != -ENOENT)
+ GOTO(stop, rc);
- rc = dt_insert(env, parent, (const struct dt_rec *)rec,
- (const struct dt_key *)name, th, BYPASS_CAPA, 1);
+ rc = dt_insert(env, pobj, (const struct dt_rec *)rec,
+ (const struct dt_key *)name, th, 1);
GOTO(stop, rc = (rc == 0 ? 1 : rc));
log:
lfsck_ibits_unlock(&clh, LCK_EX);
- lfsck_ibits_unlock(&plh, LCK_EX);
- if (obj != NULL && !IS_ERR(obj))
- lfsck_object_put(env, obj);
+ lfsck_unlock(pllh);
+
+ if (cobj != NULL && !IS_ERR(cobj))
+ lfsck_object_put(env, cobj);
CDEBUG(D_LFSCK, "%s: namespace LFSCK conditionally destroy the "
"object "DFID" because of conflict with the object "DFID
struct linkea_data *ldata)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
- struct dt_device *dev = lfsck->li_bottom;
+ struct dt_device *dev = lfsck_obj2dev(obj);
struct thandle *th = NULL;
struct lu_buf linkea_buf;
int rc = 0;
GOTO(unlock, rc = 1);
rc = dt_xattr_set(env, obj, &linkea_buf,
- XATTR_NAME_LINK, 0, th, BYPASS_CAPA);
+ XATTR_NAME_LINK, 0, th);
GOTO(unlock, rc = (rc == 0 ? 1 : rc));
const char *name, const char *name2,
__u16 type, bool update, bool dec)
{
- struct dt_insert_rec *rec = &lfsck_env_info(env)->lti_dt_rec;
- const struct lu_fid *cfid = lfsck_dto2fid(child);
- struct lu_fid tfid;
- 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;
+ 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;
+ struct lfsck_instance *lfsck = com->lc_lfsck;
+ struct dt_object *dto;
+ struct dt_device *dev = lfsck->li_next;
+ struct thandle *th = NULL;
+ struct lfsck_lock_handle *llh = &info->lti_llh;
+ 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 (!update || strcmp(name, name2) == 0)
+ rc = lfsck_lock(env, lfsck, parent, name, llh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
+ else
+ rc = lfsck_ibits_lock(env, lfsck, parent, &lh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
if (rc != 0)
GOTO(log, rc);
if (IS_ERR(th))
GOTO(unlock1, rc = PTR_ERR(th));
- rc = dt_declare_delete(env, parent, (const struct dt_key *)name, th);
+ dto = dt_object_locate(parent, th->th_dev);
+ rc = dt_declare_delete(env, dto, (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,
+ rc = dt_declare_insert(env, dto,
(const struct dt_rec *)rec,
(const struct dt_key *)name2, th);
if (rc != 0)
}
if (dec) {
- rc = dt_declare_ref_del(env, parent, th);
+ rc = dt_declare_ref_del(env, dto, th);
if (rc != 0)
GOTO(stop, rc);
}
- rc = dt_trans_start(env, dev, th);
+ rc = dt_trans_start_local(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);
+
+ dt_write_lock(env, dto, 0);
+ rc = dt_lookup(env, dto, (struct dt_rec *)&tfid,
+ (const struct dt_key *)name);
/* Someone has removed the bad name entry by race. */
if (rc == -ENOENT)
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);
+ rc = dt_delete(env, dto, (const struct dt_key *)name, th);
if (rc != 0)
GOTO(unlock2, rc);
if (update) {
- rc = dt_insert(env, parent,
+ rc = dt_insert(env, dto,
(const struct dt_rec *)rec,
- (const struct dt_key *)name2, th,
- BYPASS_CAPA, 1);
+ (const struct dt_key *)name2, th, 1);
if (rc != 0)
GOTO(unlock2, rc);
}
if (dec) {
- rc = dt_ref_del(env, parent, th);
+ rc = dt_ref_del(env, dto, th);
if (rc != 0)
GOTO(unlock2, rc);
}
LNTF_CHECK_LINKEA, true);
unlock1:
- lfsck_ibits_unlock(&lh, LCK_EX);
+ /* It is harmless even if unlock the unused lock_handle */
+ lfsck_ibits_unlock(&lh, LCK_PW);
+ lfsck_unlock(llh);
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)),
+ PFID(lfsck_dto2fid(parent)), PFID(cfid),
name, type, update ? lfsck_object_type(child) : 0,
update ? "updating" : "removing", name2, rc);
struct lfsck_thread_info *info = lfsck_env_info(env);
struct dt_insert_rec *rec = &info->lti_dt_rec;
struct lfsck_instance *lfsck = com->lc_lfsck;
- struct dt_device *dev = lfsck->li_bottom;
+ struct dt_device *dev = lfsck_obj2dev(obj);
struct thandle *th = NULL;
struct linkea_data ldata = { NULL };
struct lu_buf linkea_buf;
GOTO(unlock, rc = 1);
/* The old ".." name entry maybe not exist. */
- dt_delete(env, obj, (const struct dt_key *)dotdot, th,
- BYPASS_CAPA);
+ dt_delete(env, obj, (const struct dt_key *)dotdot, th);
rc = dt_insert(env, obj, (const struct dt_rec *)rec,
- (const struct dt_key *)dotdot, th, BYPASS_CAPA, 1);
+ (const struct dt_key *)dotdot, th, 1);
if (rc != 0)
GOTO(unlock, rc);
rc = dt_xattr_set(env, obj, &linkea_buf,
- XATTR_NAME_LINK, 0, th, BYPASS_CAPA);
+ XATTR_NAME_LINK, 0, th);
GOTO(unlock, rc = (rc == 0 ? 1 : rc));
}
rc = dt_lookup(env, parent, (struct dt_rec *)&tfid,
- (const struct dt_key *)cname->ln_name, BYPASS_CAPA);
+ (const struct dt_key *)cname->ln_name);
if (rc == -ENOENT) {
/* If the LFSCK is marked as LF_INCOMPLETE, then means some MDT
* has ever tried to verify some remote MDT-object that resides
}
rc = dt_lookup(env, parent, (struct dt_rec *)&tfid,
- (const struct dt_key *)cname->ln_name,
- BYPASS_CAPA);
+ (const struct dt_key *)cname->ln_name);
*pfid2 = *lfsck_dto2fid(parent);
if (rc == -ENOENT) {
lfsck_object_put(env, parent);
struct lu_fid *tfid = &info->lti_fid3;
struct lfsck_namespace *ns = com->lc_file_ram;
struct lfsck_instance *lfsck = com->lc_lfsck;
- struct dt_device *dev = lfsck->li_bottom;
+ struct dt_device *dev = lfsck_obj2dev(obj);
const struct lu_fid *cfid = lfsck_dto2fid(obj);
- struct dt_object *child = NULL;
struct thandle *th = NULL;
struct linkea_data ldata = { NULL };
struct lustre_handle lh = { 0 };
LASSERT(!dt_object_remote(obj));
LASSERT(S_ISREG(lfsck_object_type(obj)));
- child = lfsck_object_find_by_dev(env, dev, cfid);
- if (IS_ERR(child))
- GOTO(log, rc = PTR_ERR(child));
-
- rc = lfsck_ibits_lock(env, lfsck, child, &lh,
- MDS_INODELOCK_UPDATE |
- MDS_INODELOCK_XATTR, LCK_EX);
+ rc = lfsck_ibits_lock(env, lfsck, obj, &lh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
if (rc != 0)
GOTO(log, rc);
GOTO(log, rc = PTR_ERR(th));
la->la_valid = LA_NLINK;
- rc = dt_declare_attr_set(env, child, la, th);
+ rc = dt_declare_attr_set(env, obj, la, th);
if (rc != 0)
GOTO(stop, rc);
if (rc != 0)
GOTO(stop, rc);
- dt_write_lock(env, child, 0);
+ dt_write_lock(env, obj, 0);
/* If the LFSCK is marked as LF_INCOMPLETE, then means some MDT has
* ever tried to verify some remote MDT-object that resides on this
* MDT, but this MDT failed to respond such request. So means there
fid_cpu_to_be(tfid, cfid);
idx = lfsck_sub_trace_file_fid2idx(cfid);
rc = dt_lookup(env, com->lc_sub_trace_objs[idx].lsto_obj,
- (struct dt_rec *)&flags, (const struct dt_key *)tfid,
- BYPASS_CAPA);
+ (struct dt_rec *)&flags, (const struct dt_key *)tfid);
if (rc != 0)
GOTO(unlock, rc);
if (flags & LNTF_SKIP_NLINK)
GOTO(unlock, rc = 0);
- rc = dt_attr_get(env, child, la, BYPASS_CAPA);
+ rc = dt_attr_get(env, obj, la);
if (rc != 0)
GOTO(unlock, rc = (rc == -ENOENT ? 0 : rc));
- rc = lfsck_links_read2(env, child, &ldata);
+ rc = lfsck_links_read2(env, obj, &ldata);
if (rc != 0)
GOTO(unlock, rc = (rc == -ENODATA ? 0 : rc));
if (lfsck->li_bookmark_ram.lb_param & LPF_DRYRUN)
GOTO(unlock, rc = 1);
- rc = dt_attr_set(env, child, la, th, BYPASS_CAPA);
+ rc = dt_attr_set(env, obj, la, th);
GOTO(unlock, rc = (rc == 0 ? 1 : rc));
unlock:
- dt_write_unlock(env, child);
+ dt_write_unlock(env, obj);
stop:
dt_trans_stop(env, dev, th);
log:
- lfsck_ibits_unlock(&lh, LCK_EX);
- if (child != NULL && !IS_ERR(child))
- lfsck_object_put(env, child);
-
+ lfsck_ibits_unlock(&lh, LCK_PW);
CDEBUG(D_LFSCK, "%s: namespace LFSCK repaired the object "DFID"'s "
"nlink count from %u to %u: rc = %d\n",
lfsck_lfsck2name(lfsck), PFID(cfid), old, la->la_nlink, rc);
}
rc = dt_lookup(env, child, (struct dt_rec *)pfid,
- (const struct dt_key *)dotdot, BYPASS_CAPA);
+ (const struct dt_key *)dotdot);
if (rc != 0) {
if (rc != -ENOENT && rc != -ENODATA && rc != -EINVAL) {
dt_read_unlock(env, child);
}
rc = dt_lookup(env, parent, (struct dt_rec *)cfid,
- (const struct dt_key *)cname->ln_name,
- BYPASS_CAPA);
+ (const struct dt_key *)cname->ln_name);
if (rc != 0 && rc != -ENOENT) {
lfsck_object_put(env, parent);
continue;
}
- rc = dt_attr_get(env, child, la, BYPASS_CAPA);
+ rc = dt_attr_get(env, child, la);
if (rc != 0)
GOTO(out, rc);
}
}
} else {
- rc = dt_attr_get(env, child, la, BYPASS_CAPA);
+ rc = dt_attr_get(env, child, la);
if (rc != 0)
return rc;
struct lu_attr *la = &lfsck_env_info(env)->lti_la;
int rc;
- rc = dt_attr_get(env, obj, la, BYPASS_CAPA);
+ rc = dt_attr_get(env, obj, la);
if (rc != 0)
return rc;
lfsck_object_put(env, com->lc_obj);
com->lc_obj = NULL;
dto = lfsck_namespace_load_one_trace_file(env, com, root,
- LFSCK_NAMESPACE, NULL, true);
+ LFSCK_NAMESPACE, true);
if (IS_ERR(dto))
GOTO(out, rc = PTR_ERR(dto));
up_write(&com->lc_sem);
put:
- lu_object_put(env, &root->do_lu);
+ lfsck_object_put(env, root);
log:
CDEBUG(D_LFSCK, "%s: namespace LFSCK reset: rc = %d\n",
lfsck_lfsck2name(lfsck), rc);
{
struct lfsck_namespace *ns = com->lc_file_ram;
struct lfsck_assistant_data *lad = com->lc_data;
+ struct lfsck_assistant_object *lso = NULL;
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_lmv *llmv = lfsck->li_lmv;
struct lfsck_namespace_req *lnr;
RETURN_EXIT;
}
+ lso = lfsck_assistant_object_init(env, lfsck_dto2fid(lfsck->li_obj_dir),
+ NULL, lfsck->li_pos_current.lp_oit_cookie, true);
+ if (IS_ERR(lso)) {
+ OBD_FREE(lnr, size);
+ ns->ln_striped_dirs_skipped++;
+
+ RETURN_EXIT;
+ }
+
/* Generate a dummy request to indicate that all shards' name entry
* in this striped directory has been scanned for the first time. */
INIT_LIST_HEAD(&lnr->lnr_lar.lar_list);
- lnr->lnr_lar.lar_fid = *lfsck_dto2fid(lfsck->li_obj_dir);
+ lnr->lnr_lar.lar_parent = lso;
lnr->lnr_lmv = lfsck_lmv_get(llmv);
lnr->lnr_fid = *lfsck_dto2fid(lfsck->li_obj_dir);
- lnr->lnr_oit_cookie = lfsck->li_pos_current.lp_oit_cookie;
lnr->lnr_dir_cookie = MDS_DIR_END_OFF;
lnr->lnr_size = size;
if (llmv->ll_lmv_master) {
struct lmv_mds_md_v1 *lmv = &llmv->ll_lmv;
- if (lmv->lmv_master_mdt_index !=
- lfsck_dev_idx(lfsck->li_bottom)) {
+ if (lmv->lmv_master_mdt_index != lfsck_dev_idx(lfsck)) {
lmv->lmv_master_mdt_index =
- lfsck_dev_idx(lfsck->li_bottom);
+ lfsck_dev_idx(lfsck);
ns->ln_flags |= LF_INCONSISTENT;
llmv->ll_lmv_updated = 1;
}
struct lu_fid *pfid = &info->lti_fid2;
struct lu_name *cname = &info->lti_name;
struct lu_seq_range *range = &info->lti_range;
- struct dt_device *dev = lfsck->li_bottom;
- struct seq_server_site *ss =
- lu_site2seq(dev->dd_lu_dev.ld_site);
+ struct seq_server_site *ss = lfsck_dev_site(lfsck);
struct linkea_data ldata = { NULL };
- __u32 idx = lfsck_dev_idx(dev);
+ __u32 idx = lfsck_dev_idx(lfsck);
int rc;
ENTRY;
out:
down_write(&com->lc_sem);
- com->lc_new_checked++;
if (S_ISDIR(lfsck_object_type(obj)))
ns->ln_dirs_checked++;
if (rc != 0)
static int lfsck_namespace_exec_dir(const struct lu_env *env,
struct lfsck_component *com,
+ struct lfsck_assistant_object *lso,
struct lu_dirent *ent, __u16 type)
{
struct lfsck_assistant_data *lad = com->lc_data;
bool wakeup = false;
l_wait_event(mthread->t_ctl_waitq,
- bk->lb_async_windows == 0 ||
lad->lad_prefetched < bk->lb_async_windows ||
!thread_is_running(mthread) ||
thread_is_stopped(athread),
if (unlikely(lfsck_is_dead_obj(lfsck->li_obj_dir)))
return 0;
- lnr = lfsck_namespace_assistant_req_init(com->lc_lfsck, ent, type);
+ lnr = lfsck_namespace_assistant_req_init(com->lc_lfsck, lso, ent, type);
if (IS_ERR(lnr)) {
struct lfsck_namespace *ns = com->lc_file_ram;
goto out;
rc = lfsck_time_dump(m, ns->ln_time_last_complete,
- "time_since_last_completed");
+ "last_completed");
if (rc < 0)
goto out;
rc = lfsck_time_dump(m, ns->ln_time_latest_start,
- "time_since_latest_start");
+ "latest_start");
if (rc < 0)
goto out;
rc = lfsck_time_dump(m, ns->ln_time_last_checkpoint,
- "time_since_last_checkpoint");
+ "last_checkpoint");
if (rc < 0)
goto out;
if (duration != 0)
do_div(new_checked, duration);
+
if (rtime != 0)
do_div(speed, rtime);
- lfsck_namespace_dump_statistics(m, ns, checked,
- ns->ln_objs_checked_phase2,
- rtime, ns->ln_run_time_phase2);
+ lfsck_namespace_dump_statistics(m, ns, checked, 0, rtime, 0);
seq_printf(m, "average_speed_phase1: "LPU64" items/sec\n"
"average_speed_phase2: N/A\n"
+ "average_speed_total: "LPU64" items/sec\n"
"real_time_speed_phase1: "LPU64" items/sec\n"
"real_time_speed_phase2: N/A\n",
speed,
+ speed,
new_checked);
LASSERT(lfsck->li_di_oit != NULL);
lfsck_pos_dump(m, &pos, "current_position");
} else if (ns->ln_status == LS_SCANNING_PHASE2) {
cfs_duration_t duration = cfs_time_current() -
- lfsck->li_time_last_checkpoint;
+ com->lc_time_last_checkpoint;
__u64 checked = ns->ln_objs_checked_phase2 +
com->lc_new_checked;
__u64 speed1 = ns->ln_items_checked;
__u64 speed2 = checked;
+ __u64 speed0 = speed1 + speed2;
__u64 new_checked = com->lc_new_checked *
msecs_to_jiffies(MSEC_PER_SEC);
__u32 rtime = ns->ln_run_time_phase2 +
cfs_duration_sec(duration + HALF_SEC);
+ __u32 time0 = ns->ln_run_time_phase1 + rtime;
if (duration != 0)
do_div(new_checked, duration);
+
if (ns->ln_run_time_phase1 != 0)
do_div(speed1, ns->ln_run_time_phase1);
+ else if (ns->ln_items_checked != 0)
+ time0++;
+
if (rtime != 0)
do_div(speed2, rtime);
+ else if (checked != 0)
+ time0++;
+
+ if (time0 != 0)
+ do_div(speed0, time0);
+
lfsck_namespace_dump_statistics(m, ns, ns->ln_items_checked,
checked,
ns->ln_run_time_phase1, rtime);
-
seq_printf(m, "average_speed_phase1: "LPU64" items/sec\n"
"average_speed_phase2: "LPU64" objs/sec\n"
+ "average_speed_total: "LPU64" items/sec\n"
"real_time_speed_phase1: N/A\n"
"real_time_speed_phase2: "LPU64" objs/sec\n"
"current_position: "DFID"\n",
speed1,
speed2,
+ speed0,
new_checked,
PFID(&ns->ln_fid_latest_scanned_phase2));
} else {
__u64 speed1 = ns->ln_items_checked;
__u64 speed2 = ns->ln_objs_checked_phase2;
+ __u64 speed0 = speed1 + speed2;
+ __u32 time0 = ns->ln_run_time_phase1 + ns->ln_run_time_phase2;
if (ns->ln_run_time_phase1 != 0)
do_div(speed1, ns->ln_run_time_phase1);
+ else if (ns->ln_items_checked != 0)
+ time0++;
+
if (ns->ln_run_time_phase2 != 0)
do_div(speed2, ns->ln_run_time_phase2);
+ else if (ns->ln_objs_checked_phase2 != 0)
+ time0++;
+
+ if (time0 != 0)
+ do_div(speed0, time0);
+
lfsck_namespace_dump_statistics(m, ns, ns->ln_items_checked,
ns->ln_objs_checked_phase2,
ns->ln_run_time_phase1,
ns->ln_run_time_phase2);
-
seq_printf(m, "average_speed_phase1: "LPU64" items/sec\n"
"average_speed_phase2: "LPU64" objs/sec\n"
+ "average_speed_total: "LPU64" items/sec\n"
"real_time_speed_phase1: N/A\n"
"real_time_speed_phase2: N/A\n"
"current_position: N/A\n",
speed1,
- speed2);
+ speed2,
+ speed0);
}
out:
up_read(&com->lc_sem);
struct lfsck_assistant_data *lad = com->lc_data;
struct lfsck_tgt_descs *ltds = &lfsck->li_mdt_descs;
struct lfsck_tgt_desc *ltd;
- int rc;
+ int rc = 0;
bool fail = false;
ENTRY;
fid_cpu_to_be(key, &lr->lr_fid);
mutex_lock(&com->lc_sub_trace_objs[idx].lsto_mutex);
rc = dt_lookup(env, obj, (struct dt_rec *)&flags,
- (const struct dt_key *)key, BYPASS_CAPA);
+ (const struct dt_key *)key);
if (rc == 0) {
if (flags & LNTF_SKIP_NLINK) {
mutex_unlock(
flags |= LNTF_SKIP_NLINK;
if (exist) {
rc = dt_delete(env, obj, (const struct dt_key *)key,
- th, BYPASS_CAPA);
+ th);
if (rc != 0)
GOTO(log, rc);
}
rc = dt_insert(env, obj, (const struct dt_rec *)&flags,
- (const struct dt_key *)key, th, BYPASS_CAPA, 1);
+ (const struct dt_key *)key, th, 1);
GOTO(log, rc);
case LE_SET_LMV_MASTER: {
struct dt_object *obj;
- obj = lfsck_object_find_by_dev(env, lfsck->li_bottom,
- &lr->lr_fid);
+ obj = lfsck_object_find_bottom(env, lfsck, &lr->lr_fid);
if (IS_ERR(obj))
RETURN(PTR_ERR(obj));
- rc = lfsck_namespace_notify_lmv_master_local(env, com, obj);
+ if (likely(dt_object_exists(obj)))
+ rc = lfsck_namespace_notify_lmv_master_local(env, com,
+ obj);
+
lfsck_object_put(env, obj);
RETURN(rc > 0 ? 0 : rc);
lr->lr_index, lr->lr_status, lr->lr_flags2);
spin_lock(<ds->ltd_lock);
- ltd = LTD_TGT(ltds, lr->lr_index);
+ ltd = lfsck_ltd2tgt(ltds, lr->lr_index);
if (ltd == NULL) {
spin_unlock(<ds->ltd_lock);
struct dt_object_format *dof = &info->lti_dof;
struct dt_insert_rec *rec = &info->lti_dt_rec;
struct lmv_mds_md_v1 *lmv2 = &info->lti_lmv2;
+ struct dt_object *pobj = NULL;
+ struct dt_object *cobj = NULL;
const struct lu_name *cname;
struct linkea_data ldata = { NULL };
- struct lustre_handle lh = { 0 };
+ struct lfsck_lock_handle *llh = &info->lti_llh;
struct lu_buf linkea_buf;
struct lu_buf lmv_buf;
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
- struct dt_device *dev = lfsck_obj2dt_dev(child);
+ struct dt_device *dev = lfsck->li_next;
struct thandle *th = NULL;
int rc = 0;
__u16 type = lnr->lnr_type;
if (!create || bk->lb_param & LPF_DRYRUN)
GOTO(log, rc = 0);
+ /* We may need to create the sub-objects of the @child via LOD,
+ * so make the modification based on lfsck->li_next. */
+
+ pobj = lfsck_object_locate(dev, parent);
+ if (IS_ERR(pobj))
+ GOTO(log, rc = PTR_ERR(pobj));
+
+ if (unlikely(!dt_try_as_dir(env, pobj)))
+ GOTO(log, rc = -ENOTDIR);
+
+ cobj = lfsck_object_locate(dev, child);
+ if (IS_ERR(cobj))
+ GOTO(log, rc = PTR_ERR(cobj));
+
rc = linkea_data_new(&ldata, &info->lti_linkea_buf2);
if (rc != 0)
GOTO(log, rc);
- rc = linkea_add_buf(&ldata, cname, lfsck_dto2fid(parent));
+ rc = linkea_add_buf(&ldata, cname, lfsck_dto2fid(pobj));
if (rc != 0)
GOTO(log, rc);
- rc = lfsck_ibits_lock(env, lfsck, parent, &lh,
- MDS_INODELOCK_UPDATE, LCK_EX);
+ rc = lfsck_lock(env, lfsck, parent, lnr->lnr_name, llh,
+ MDS_INODELOCK_UPDATE, LCK_PR);
if (rc != 0)
GOTO(log, rc);
- rc = lfsck_namespace_check_exist(env, parent, child, lnr->lnr_name);
+ rc = lfsck_namespace_check_exist(env, pobj, cobj, lnr->lnr_name);
if (rc != 0)
GOTO(log, rc);
- th = dt_trans_create(env, dev);
- if (IS_ERR(th))
- GOTO(log, rc = PTR_ERR(th));
-
/* Set the ctime as zero, then others can know it is created for
* repairing dangling name entry by LFSCK. And if the LFSCK made
* wrong decision and the real MDT-object has been found later,
la->la_valid = LA_TYPE | LA_MODE | LA_UID | LA_GID |
LA_ATIME | LA_MTIME | LA_CTIME;
- child->do_ops->do_ah_init(env, hint, parent, child,
- la->la_mode & S_IFMT);
+ cobj->do_ops->do_ah_init(env, hint, pobj, cobj,
+ la->la_mode & S_IFMT);
memset(dof, 0, sizeof(*dof));
dof->dof_type = dt_mode_to_dft(type);
* the MDT-object without stripes (dof->dof_reg.striped = 0). related
* OST-objects will be created when write open. */
+ th = dt_trans_create(env, dev);
+ if (IS_ERR(th))
+ GOTO(log, rc = PTR_ERR(th));
+
/* 1a. create child. */
- rc = dt_declare_create(env, child, la, hint, dof, th);
+ rc = dt_declare_create(env, cobj, la, hint, dof, th);
if (rc != 0)
GOTO(stop, rc);
if (S_ISDIR(type)) {
- if (unlikely(!dt_try_as_dir(env, child)))
+ if (unlikely(!dt_try_as_dir(env, cobj)))
GOTO(stop, rc = -ENOTDIR);
/* 2a. insert dot into child dir */
rec->rec_type = S_IFDIR;
- rec->rec_fid = lfsck_dto2fid(child);
- rc = dt_declare_insert(env, child,
+ rec->rec_fid = lfsck_dto2fid(cobj);
+ rc = dt_declare_insert(env, cobj,
(const struct dt_rec *)rec,
(const struct dt_key *)dot, th);
if (rc != 0)
GOTO(stop, rc);
/* 3a. insert dotdot into child dir */
- rec->rec_fid = lfsck_dto2fid(parent);
- rc = dt_declare_insert(env, child,
+ rec->rec_fid = lfsck_dto2fid(pobj);
+ rc = dt_declare_insert(env, cobj,
(const struct dt_rec *)rec,
(const struct dt_key *)dotdot, th);
if (rc != 0)
GOTO(stop, rc);
/* 4a. increase child nlink */
- rc = dt_declare_ref_add(env, child, th);
+ rc = dt_declare_ref_add(env, cobj, th);
if (rc != 0)
GOTO(stop, rc);
idx = lfsck_shard_name_to_index(env,
lnr->lnr_name, lnr->lnr_namelen,
- type, lfsck_dto2fid(child));
+ type, lfsck_dto2fid(cobj));
if (unlikely(idx < 0))
GOTO(stop, rc = idx);
lfsck_lmv_header_cpu_to_le(lmv2, lmv2);
lfsck_buf_init(&lmv_buf, lmv2, sizeof(*lmv2));
- rc = dt_declare_xattr_set(env, child, &lmv_buf,
+ rc = dt_declare_xattr_set(env, cobj, &lmv_buf,
XATTR_NAME_LMV, 0, th);
if (rc != 0)
GOTO(stop, rc);
/* 6a. insert linkEA for child */
lfsck_buf_init(&linkea_buf, ldata.ld_buf->lb_buf,
ldata.ld_leh->leh_len);
- rc = dt_declare_xattr_set(env, child, &linkea_buf,
+ rc = dt_declare_xattr_set(env, cobj, &linkea_buf,
XATTR_NAME_LINK, 0, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_trans_start(env, dev, th);
+ rc = dt_trans_start_local(env, dev, th);
if (rc != 0)
GOTO(stop, rc = (rc == -EEXIST ? 1 : rc));
- dt_write_lock(env, child, 0);
+ dt_write_lock(env, cobj, 0);
/* 1b. create child */
- rc = dt_create(env, child, la, hint, dof, th);
+ rc = dt_create(env, cobj, la, hint, dof, th);
if (rc != 0)
GOTO(unlock, rc = (rc == -EEXIST ? 1 : rc));
if (S_ISDIR(type)) {
- if (unlikely(!dt_try_as_dir(env, child)))
- GOTO(unlock, rc = -ENOTDIR);
-
/* 2b. insert dot into child dir */
rec->rec_type = S_IFDIR;
- rec->rec_fid = lfsck_dto2fid(child);
- rc = dt_insert(env, child, (const struct dt_rec *)rec,
- (const struct dt_key *)dot, th, BYPASS_CAPA, 1);
+ rec->rec_fid = lfsck_dto2fid(cobj);
+ rc = dt_insert(env, cobj, (const struct dt_rec *)rec,
+ (const struct dt_key *)dot, th, 1);
if (rc != 0)
GOTO(unlock, rc);
/* 3b. insert dotdot into child dir */
- rec->rec_fid = lfsck_dto2fid(parent);
- rc = dt_insert(env, child, (const struct dt_rec *)rec,
- (const struct dt_key *)dotdot, th,
- BYPASS_CAPA, 1);
+ rec->rec_fid = lfsck_dto2fid(pobj);
+ rc = dt_insert(env, cobj, (const struct dt_rec *)rec,
+ (const struct dt_key *)dotdot, th, 1);
if (rc != 0)
GOTO(unlock, rc);
/* 4b. increase child nlink */
- rc = dt_ref_add(env, child, th);
+ rc = dt_ref_add(env, cobj, th);
if (rc != 0)
GOTO(unlock, rc);
/* 5b. generate slave LMV EA. */
if (lnr->lnr_lmv != NULL && lnr->lnr_lmv->ll_lmv_master) {
- rc = dt_xattr_set(env, child, &lmv_buf, XATTR_NAME_LMV,
- 0, th, BYPASS_CAPA);
+ rc = dt_xattr_set(env, cobj, &lmv_buf, XATTR_NAME_LMV,
+ 0, th);
if (rc != 0)
GOTO(unlock, rc);
}
}
/* 6b. insert linkEA for child. */
- rc = dt_xattr_set(env, child, &linkea_buf,
- XATTR_NAME_LINK, 0, th, BYPASS_CAPA);
+ rc = dt_xattr_set(env, cobj, &linkea_buf,
+ XATTR_NAME_LINK, 0, th);
GOTO(unlock, rc);
unlock:
- dt_write_unlock(env, child);
+ dt_write_unlock(env, cobj);
stop:
dt_trans_stop(env, dev, th);
log:
- lfsck_ibits_unlock(&lh, LCK_EX);
+ lfsck_unlock(llh);
CDEBUG(D_LFSCK, "%s: namespace LFSCK assistant found dangling "
"reference for: parent "DFID", child "DFID", type %u, "
"name %s. %s: rc = %d\n", lfsck_lfsck2name(lfsck),
PFID(lfsck_dto2fid(parent)), PFID(lfsck_dto2fid(child)),
type, cname->ln_name,
- create ? "Create the lost OST-object as required" :
+ create ? "Create the lost MDT-object as required" :
"Keep the MDT-object there by default", rc);
if (rc <= 0) {
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct lfsck_namespace *ns = com->lc_file_ram;
+ struct lfsck_assistant_data *lad = com->lc_data;
struct linkea_data ldata = { NULL };
const struct lu_name *cname;
struct thandle *handle = NULL;
container_of0(lar, struct lfsck_namespace_req, lnr_lar);
struct dt_object *dir = NULL;
struct dt_object *obj = NULL;
- const struct lu_fid *pfid;
+ struct lfsck_assistant_object *lso = lar->lar_parent;
+ const struct lu_fid *pfid = &lso->lso_fid;
struct dt_device *dev = NULL;
struct lustre_handle lh = { 0 };
bool repaired = false;
bool newdata;
bool log = false;
bool bad_hash = false;
+ bool bad_linkea = false;
int idx = 0;
int count = 0;
int rc = 0;
enum lfsck_namespace_inconsistency_type type = LNIT_NONE;
ENTRY;
- dir = lfsck_object_find_bottom(env, lfsck, &lar->lar_fid);
- if (IS_ERR(dir))
- RETURN(PTR_ERR(dir));
-
- if (unlikely(lfsck_is_dead_obj(dir)))
- GOTO(put_dir, rc = 0);
+ if (lso->lso_dead)
+ RETURN(0);
- pfid = lfsck_dto2fid(dir);
la->la_nlink = 0;
if (lnr->lnr_attr & LUDA_UPGRADE) {
ns->ln_flags |= LF_UPGRADE;
}
if (unlikely(lnr->lnr_dir_cookie == MDS_DIR_END_OFF)) {
- rc = lfsck_namespace_striped_dir_rescan(env, com, dir, lnr);
+ rc = lfsck_namespace_striped_dir_rescan(env, com, lnr);
- GOTO(put_dir, rc);
+ RETURN(rc);
}
- if (lnr->lnr_name[0] == '.' &&
- (lnr->lnr_namelen == 1 || fid_seq_is_dot(fid_seq(&lnr->lnr_fid))))
+ if (fid_seq_is_dot(fid_seq(&lnr->lnr_fid)))
GOTO(out, rc = 0);
if (lnr->lnr_lmv != NULL && lnr->lnr_lmv->ll_lmv_master) {
- rc = lfsck_namespace_handle_striped_master(env, com, dir, lnr);
+ rc = lfsck_namespace_handle_striped_master(env, com, lnr);
- GOTO(put_dir, rc);
+ RETURN(rc);
}
idx = lfsck_find_mdt_idx_by_fid(env, lfsck, &lnr->lnr_fid);
if (idx < 0)
GOTO(out, rc = idx);
- if (idx == lfsck_dev_idx(lfsck->li_bottom)) {
+ if (idx == lfsck_dev_idx(lfsck)) {
if (unlikely(strcmp(lnr->lnr_name, dotdot) == 0))
GOTO(out, rc = 0);
GOTO(out, rc);
}
- ltd = LTD_TGT(&lfsck->li_mdt_descs, idx);
+ ltd = lfsck_ltd2tgt(&lfsck->li_mdt_descs, idx);
if (unlikely(ltd == NULL)) {
CDEBUG(D_LFSCK, "%s: cannot talk with MDT %x which "
"did not join the namespace LFSCK\n",
if (dt_object_exists(obj) == 0) {
dangling:
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(dir)) {
+ rc = PTR_ERR(dir);
+
+ GOTO(trace, rc == -ENOENT ? 0 : rc);
+ }
+ }
+
rc = lfsck_namespace_check_exist(env, dir, obj, lnr->lnr_name);
if (rc == 0) {
if (!lfsck_is_valid_slave_name_entry(env, lnr->lnr_lmv,
GOTO(out, rc);
}
- if (!(bk->lb_param & LPF_DRYRUN) && repaired) {
+ if (!(bk->lb_param & LPF_DRYRUN) && lad->lad_advance_lock) {
again:
rc = lfsck_ibits_lock(env, lfsck, obj, &lh,
if (rc != 0)
GOTO(stop, rc);
- rc = dt_trans_start(env, dev, handle);
+ rc = dt_trans_start_local(env, dev, handle);
if (rc != 0)
GOTO(stop, rc);
dtlocked = true;
}
- rc = lfsck_namespace_check_exist(env, dir, obj, lnr->lnr_name);
- if (rc != 0)
- GOTO(stop, rc);
-
rc = lfsck_links_read(env, obj, &ldata);
if (unlikely(rc == -ENOENT)) {
if (handle != NULL) {
goto stop;
}
- ns->ln_flags |= LF_INCONSISTENT;
-
/* If the name entry hash does not match the slave striped
* directory, and the name entry does not match also, then
* it is quite possible that name entry is corrupted. */
if (!lfsck_is_valid_slave_name_entry(env, lnr->lnr_lmv,
lnr->lnr_name, lnr->lnr_namelen)) {
+ ns->ln_flags |= LF_INCONSISTENT;
type = LNIT_BAD_DIRENT;
GOTO(stop, rc = 0);
* not recognize the name entry, then it is quite possible
* that the name entry is corrupted. */
if ((lfsck_object_type(obj) & S_IFMT) != lnr->lnr_type) {
+ ns->ln_flags |= LF_INCONSISTENT;
type = LNIT_BAD_DIRENT;
GOTO(stop, rc = 0);
type = LNIT_BAD_TYPE;
count = 1;
- ns->ln_flags |= LF_INCONSISTENT;
/* The magic crashed, we are not sure whether there are more
* corrupt data in the linkea, so remove all linkea entries. */
remove = true;
type = LNIT_BAD_TYPE;
count = 1;
- ns->ln_flags |= LF_UPGRADE;
remove = false;
newdata = true;
nodata:
if (bk->lb_param & LPF_DRYRUN) {
+ if (rc == -ENODATA)
+ ns->ln_flags |= LF_UPGRADE;
+ else
+ ns->ln_flags |= LF_INCONSISTENT;
ns->ln_linkea_repaired++;
repaired = true;
log = true;
goto stop;
}
- if (!lustre_handle_is_used(&lh))
+ if (!lustre_handle_is_used(&lh)) {
+ remove = false;
+ newdata = false;
+ type = LNIT_NONE;
+
goto again;
+ }
+
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(dir)) {
+ rc = PTR_ERR(dir);
+
+ GOTO(stop, rc == -ENOENT ? 0 : rc);
+ }
+ }
+
+ rc = lfsck_namespace_check_exist(env, dir, obj, lnr->lnr_name);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ bad_linkea = true;
+ if (!remove && newdata)
+ ns->ln_flags |= LF_UPGRADE;
+ else if (remove || !(ns->ln_flags & LF_UPGRADE))
+ ns->ln_flags |= LF_INCONSISTENT;
if (remove) {
LASSERT(newdata);
- rc = dt_xattr_del(env, obj, XATTR_NAME_LINK, handle,
- BYPASS_CAPA);
+ rc = dt_xattr_del(env, obj, XATTR_NAME_LINK, handle);
if (rc != 0)
GOTO(stop, rc);
}
ns->ln_flags |= LF_INCONSISTENT;
log = false;
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(dir)) {
+ rc = PTR_ERR(dir);
+
+ GOTO(trace, rc == -ENOENT ? 0 : rc);
+ }
+ }
+
rc = lfsck_namespace_repair_bad_name_hash(env, com, dir,
lnr->lnr_lmv, lnr->lnr_name);
- if (rc >= 0)
+ if (rc == 0)
bad_hash = true;
}
if (rc >= 0) {
+ if (type != LNIT_NONE && dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(dir)) {
+ rc = PTR_ERR(dir);
+
+ GOTO(trace, rc == -ENOENT ? 0 : rc);
+ }
+ }
+
switch (type) {
case LNIT_BAD_TYPE:
log = false;
}
if (count == 1 && S_ISREG(lfsck_object_type(obj)))
- dt_attr_get(env, obj, la, BYPASS_CAPA);
+ dt_attr_get(env, obj, la);
}
+trace:
down_write(&com->lc_sem);
if (rc < 0) {
CDEBUG(D_LFSCK, "%s: namespace LFSCK assistant fail to handle "
"the entry: "DFID", parent "DFID", name %.*s: rc = %d\n",
- lfsck_lfsck2name(lfsck), PFID(&lnr->lnr_fid),
- PFID(lfsck_dto2fid(dir)),
+ lfsck_lfsck2name(lfsck), PFID(&lnr->lnr_fid), PFID(pfid),
lnr->lnr_namelen, lnr->lnr_name, rc);
lfsck_namespace_record_failure(env, lfsck, ns);
if ((rc == -ENOTCONN || rc == -ESHUTDOWN || rc == -EREMCHG ||
rc == -ETIMEDOUT || rc == -EHOSTDOWN ||
rc == -EHOSTUNREACH || rc == -EINPROGRESS) &&
- dev != NULL && dev != lfsck->li_next)
+ dev != NULL && dev != lfsck->li_bottom)
lfsck_lad_set_bitmap(env, com, idx);
if (!(bk->lb_param & LPF_FAILOUT))
CDEBUG(D_LFSCK, "%s: namespace LFSCK assistant "
"repaired the entry: "DFID", parent "DFID
", name %.*s\n", lfsck_lfsck2name(lfsck),
- PFID(&lnr->lnr_fid),
- PFID(lfsck_dto2fid(dir)),
+ PFID(&lnr->lnr_fid), PFID(pfid),
lnr->lnr_namelen, lnr->lnr_name);
if (repaired) {
if (obj != NULL && !IS_ERR(obj))
lfsck_object_put(env, obj);
-put_dir:
- lu_object_put(env, &dir->do_lu);
+ if (dir != NULL && !IS_ERR(dir))
+ lfsck_object_put(env, dir);
+
+ lad->lad_advance_lock = bad_linkea;
return rc;
}
obj = com->lc_sub_trace_objs[idx].lsto_obj;
fid_cpu_to_be(key, &ent->lde_fid);
rc = dt_lookup(env, obj, (struct dt_rec *)&flags,
- (const struct dt_key *)key, BYPASS_CAPA);
+ (const struct dt_key *)key);
if (rc == 0) {
exist = true;
flags |= LNTF_CHECK_ORPHAN;
GOTO(stop, rc);
/* b1. remove name entry from backend /lost+found */
- rc = dt_delete(env, parent, (const struct dt_key *)ent->lde_name, th,
- BYPASS_CAPA);
+ rc = dt_delete(env, parent, (const struct dt_key *)ent->lde_name, th);
if (rc != 0)
GOTO(stop, rc);
if (exist) {
/* a3. remove child's FID from the LFSCK trace file. */
- rc = dt_delete(env, obj, (const struct dt_key *)key, th,
- BYPASS_CAPA);
+ rc = dt_delete(env, obj, (const struct dt_key *)key, th);
if (rc != 0)
GOTO(stop, rc);
} else {
/* b4. set child's ctime as 1 */
- rc = dt_attr_set(env, child, la, th, BYPASS_CAPA);
+ rc = dt_attr_set(env, child, la, th);
if (rc != 0)
GOTO(stop, rc);
}
/* b5. insert child's FID into the LFSCK trace file. */
rc = dt_insert(env, obj, (const struct dt_rec *)&flags,
- (const struct dt_key *)key, th, BYPASS_CAPA, 1);
+ (const struct dt_key *)key, th, 1);
GOTO(stop, rc = (rc == 0 ? 1 : rc));
dt_trans_stop(env, dev, th);
out:
- lu_object_put(env, &child->do_lu);
+ lfsck_object_put(env, child);
return rc;
}
struct lfsck_instance *lfsck = com->lc_lfsck;
struct ptlrpc_thread *thread = &lfsck->li_thread;
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
- struct dt_device *dev = lfsck->li_bottom;
struct lfsck_namespace *ns = com->lc_file_ram;
struct dt_object *parent;
const struct dt_it_ops *iops;
struct dt_it *di;
- struct seq_server_site *ss =
- lu_site2seq(dev->dd_lu_dev.ld_site);
+ struct seq_server_site *ss = lfsck_dev_site(lfsck);
__u64 cookie;
+ __u32 idx = lfsck_dev_idx(lfsck);
int rc = 0;
__u16 type;
ENTRY;
- parent = lfsck_object_find_by_dev(env, dev, &LU_BACKEND_LPF_FID);
+ parent = lfsck_object_find_by_dev(env, lfsck->li_bottom,
+ &LU_BACKEND_LPF_FID);
if (IS_ERR(parent)) {
CERROR("%s: fail to find backend /lost+found: rc = %ld\n",
lfsck_lfsck2name(lfsck), PTR_ERR(parent));
com->lc_new_scanned = 0;
iops = &parent->do_index_ops->dio_it;
- di = iops->init(env, parent, LUDA_64BITHASH | LUDA_TYPE, BYPASS_CAPA);
+ di = iops->init(env, parent, LUDA_64BITHASH | LUDA_TYPE);
if (IS_ERR(di))
GOTO(out, rc = PTR_ERR(di));
fid_seq(&ent->lde_fid), range);
if (rc != 0)
goto skip;
- } else if (lfsck_dev_idx(dev) != 0) {
+ } else if (idx != 0) {
/* If the returned FID is IGIF, then there are three
* possible cases:
*
"in the backend /lost+found on the MDT %04x, "
"to be safe, skip it.\n",
lfsck_lfsck2name(lfsck), ent->lde_namelen,
- ent->lde_name, PFID(&ent->lde_fid),
- lfsck_dev_idx(dev));
+ ent->lde_name, PFID(&ent->lde_fid), idx);
goto skip;
}
CDEBUG(D_LFSCK, "%s: stop to scan backend /lost+found: rc = %d\n",
lfsck_lfsck2name(lfsck), rc);
- lu_object_put(env, &parent->do_lu);
+ lfsck_object_put(env, parent);
}
/**
(struct lu_dirent *)info->lti_key;
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct ptlrpc_thread *thread = &lfsck->li_thread;
+ struct lfsck_assistant_object *lso = NULL;
struct lfsck_namespace_req *lnr;
struct lfsck_assistant_req *lar;
int rc;
if (name_is_dot_or_dotdot(ent->lde_name, ent->lde_namelen))
goto next;
- lnr = lfsck_namespace_assistant_req_init(lfsck, ent, type);
+ if (lso == NULL) {
+ lso = lfsck_assistant_object_init(env,
+ lfsck_dto2fid(dir), NULL,
+ lfsck->li_pos_current.lp_oit_cookie, true);
+ if (IS_ERR(lso)) {
+ if (bk->lb_param & LPF_FAILOUT)
+ GOTO(out, rc = PTR_ERR(lso));
+
+ lso = NULL;
+ goto next;
+ }
+ }
+
+ lnr = lfsck_namespace_assistant_req_init(lfsck, lso, ent, type);
if (IS_ERR(lnr)) {
if (bk->lb_param & LPF_FAILOUT)
GOTO(out, rc = PTR_ERR(lnr));
} while (rc == 0);
out:
+ if (lso != NULL && !IS_ERR(lso))
+ lfsck_assistant_object_put(env, lso);
+
lfsck_close_dir(env, lfsck, rc);
if (rc <= 0)
RETURN(rc);
__u8 flags = 0;
ENTRY;
- di = iops->init(env, obj, 0, BYPASS_CAPA);
+ di = iops->init(env, obj, 0);
if (IS_ERR(di))
RETURN(PTR_ERR(di));
goto checkpoint;
}
- target = lfsck_object_find_by_dev(env, lfsck->li_bottom, &fid);
+ target = lfsck_object_find_bottom(env, lfsck, &fid);
if (IS_ERR(target)) {
rc = PTR_ERR(target);
goto checkpoint;
lnr = list_entry(lad->lad_req_list.next,
struct lfsck_namespace_req,
lnr_lar.lar_list);
- pos->lp_oit_cookie = lnr->lnr_oit_cookie;
+ pos->lp_oit_cookie = lnr->lnr_lar.lar_parent->lso_oit_cookie;
pos->lp_dir_cookie = lnr->lnr_dir_cookie - 1;
- pos->lp_dir_parent = lnr->lnr_lar.lar_fid;
+ pos->lp_dir_parent = lnr->lnr_lar.lar_parent->lso_fid;
}
static int lfsck_namespace_double_scan_result(const struct lu_env *env,
down_write(&com->lc_sem);
ns->ln_run_time_phase2 += cfs_duration_sec(cfs_time_current() +
- HALF_SEC - lfsck->li_time_last_checkpoint);
+ HALF_SEC - com->lc_time_last_checkpoint);
ns->ln_time_last_checkpoint = cfs_time_current_sec();
ns->ln_objs_checked_phase2 += com->lc_new_checked;
com->lc_new_checked = 0;
down_read(<ds->ltd_rw_sem);
cfs_foreach_bit(lad->lad_bitmap, idx) {
- ltd = LTD_TGT(ltds, idx);
+ ltd = lfsck_ltd2tgt(ltds, idx);
LASSERT(ltd != NULL);
laia->laia_ltd = ltd;
* 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)
+int lfsck_verify_linkea(const struct lu_env *env, struct dt_object *obj,
+ const struct lu_name *cname, const struct lu_fid *pfid)
{
+ struct dt_device *dev = lfsck_obj2dev(obj);
struct linkea_data ldata = { NULL };
struct lu_buf linkea_buf;
struct thandle *th;
dt_write_lock(env, obj, 0);
rc = dt_xattr_set(env, obj, &linkea_buf,
- XATTR_NAME_LINK, fl, th, BYPASS_CAPA);
+ XATTR_NAME_LINK, fl, th);
dt_write_unlock(env, obj);
GOTO(stop, rc);
*
* \param[in] env pointer to the thread context
* \param[in] lfsck pointer to the lfsck instance
- * \param[in] parent pointer to the parent directory that holds
+ * \param[in] dir pointer to the directory that holds
* the name entry
* \param[in] name the name for the entry to be updated
- * \param[in] pfid the new PFID for the name entry
+ * \param[in] fid the new FID for the name entry referenced
* \param[in] type the type for the name entry to be updated
*
* \retval 0 for success
*/
int lfsck_update_name_entry(const struct lu_env *env,
struct lfsck_instance *lfsck,
- struct dt_object *parent, const char *name,
- const struct lu_fid *pfid, __u32 type)
+ struct dt_object *dir, const char *name,
+ const struct lu_fid *fid, __u32 type)
{
- struct dt_insert_rec *rec = &lfsck_env_info(env)->lti_dt_rec;
- struct dt_device *dev = lfsck->li_next;
- struct lustre_handle lh = { 0 };
- struct thandle *th;
- int rc;
- bool exists = true;
+ struct lfsck_thread_info *info = lfsck_env_info(env);
+ struct dt_insert_rec *rec = &info->lti_dt_rec;
+ struct lfsck_lock_handle *llh = &info->lti_llh;
+ struct dt_device *dev = lfsck_obj2dev(dir);
+ struct thandle *th;
+ int rc;
+ bool exists = true;
ENTRY;
- rc = lfsck_ibits_lock(env, lfsck, parent, &lh,
- MDS_INODELOCK_UPDATE, LCK_EX);
+ rc = lfsck_lock(env, lfsck, dir, name, llh,
+ MDS_INODELOCK_UPDATE, LCK_PW);
if (rc != 0)
RETURN(rc);
if (IS_ERR(th))
GOTO(unlock, rc = PTR_ERR(th));
- rc = dt_declare_delete(env, parent, (const struct dt_key *)name, th);
+ rc = dt_declare_delete(env, dir, (const struct dt_key *)name, th);
if (rc != 0)
GOTO(stop, rc);
rec->rec_type = type;
- rec->rec_fid = pfid;
- rc = dt_declare_insert(env, parent, (const struct dt_rec *)rec,
+ rec->rec_fid = fid;
+ rc = dt_declare_insert(env, dir, (const struct dt_rec *)rec,
(const struct dt_key *)name, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_declare_ref_add(env, parent, th);
+ rc = dt_declare_ref_add(env, dir, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_trans_start(env, dev, th);
+ rc = dt_trans_start_local(env, dev, th);
if (rc != 0)
GOTO(stop, rc);
- rc = dt_delete(env, parent, (const struct dt_key *)name, th,
- BYPASS_CAPA);
+ rc = dt_delete(env, dir, (const struct dt_key *)name, th);
if (rc == -ENOENT) {
exists = false;
rc = 0;
if (rc != 0)
GOTO(stop, rc);
- rc = dt_insert(env, parent, (const struct dt_rec *)rec,
- (const struct dt_key *)name, th, BYPASS_CAPA, 1);
+ rc = dt_insert(env, dir, (const struct dt_rec *)rec,
+ (const struct dt_key *)name, th, 1);
if (rc == 0 && S_ISDIR(type) && !exists) {
- dt_write_lock(env, parent, 0);
- rc = dt_ref_add(env, parent, th);
- dt_write_unlock(env, parent);
+ dt_write_lock(env, dir, 0);
+ rc = dt_ref_add(env, dir, th);
+ dt_write_unlock(env, dir);
}
GOTO(stop, rc);
dt_trans_stop(env, dev, th);
unlock:
- lfsck_ibits_unlock(&lh, LCK_EX);
-
+ lfsck_unlock(llh);
CDEBUG(D_LFSCK, "%s: update name entry "DFID"/%s with the FID "DFID
" and the type %o: rc = %d\n", lfsck_lfsck2name(lfsck),
- PFID(lfsck_dto2fid(parent)), name, PFID(pfid), type, rc);
+ PFID(lfsck_dto2fid(dir)), name, PFID(fid), type, rc);
return rc;
}
if (unlikely(!dt_try_as_dir(env, root)))
GOTO(out, rc = -ENOTDIR);
- obj = local_file_find_or_create(env, lfsck->li_los, root,
- LFSCK_NAMESPACE,
- S_IFREG | S_IRUGO | S_IWUSR);
+ obj = local_index_find_or_create(env, lfsck->li_los, root,
+ LFSCK_NAMESPACE,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ &dt_lfsck_features);
if (IS_ERR(obj))
GOTO(out, rc = PTR_ERR(obj));
out:
if (root != NULL && !IS_ERR(root))
- lu_object_put(env, &root->do_lu);
+ lfsck_object_put(env, root);
if (rc != 0) {
lfsck_component_cleanup(env, com);
CERROR("%s: fail to init namespace LFSCK component: rc = %d\n",