static int lfsck_exec_dir(const struct lu_env *env,
struct lfsck_instance *lfsck,
+ struct lfsck_assistant_object *lso,
struct lu_dirent *ent, __u16 type)
{
struct lfsck_component *com;
int rc;
list_for_each_entry(com, &lfsck->li_list_scan, lc_link) {
- rc = com->lc_ops->lfsck_exec_dir(env, com, ent, type);
+ rc = com->lc_ops->lfsck_exec_dir(env, com, lso, ent, type);
if (rc != 0)
return rc;
}
(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;
int rc;
__u16 type;
ENTRY;
lfsck_lfsck2name(lfsck),
PFID(lfsck_dto2fid(dir)), lfsck->li_cookie_dir);
- RETURN(0);
+ GOTO(out, rc = 0);
}
lfsck->li_new_scanned++;
lfsck->li_cookie_dir, rc);
lfsck_fail(env, lfsck, true);
if (bk->lb_param & LPF_FAILOUT)
- RETURN(rc);
+ GOTO(out, rc);
else
goto checkpoint;
}
if (ent->lde_namelen == 1 && ent->lde_name[0] == '.')
goto checkpoint;
+ 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)
+ RETURN(PTR_ERR(lso));
+
+ lso = NULL;
+ goto checkpoint;
+ }
+ }
+
/* The type in the @ent structure may has been overwritten,
* so we need to pass the @type parameter independently. */
- rc = lfsck_exec_dir(env, lfsck, ent, type);
+ rc = lfsck_exec_dir(env, lfsck, lso, ent, type);
if (rc != 0 && bk->lb_param & LPF_FAILOUT)
- RETURN(rc);
+ GOTO(out, rc);
checkpoint:
rc = lfsck_checkpoint(env, lfsck);
if (rc != 0 && bk->lb_param & LPF_FAILOUT)
- RETURN(rc);
+ GOTO(out, rc);
/* Rate control. */
lfsck_control_speed(lfsck);
lfsck_lfsck2name(lfsck),
PFID(lfsck_dto2fid(dir)),
lfsck->li_cookie_dir);
- RETURN(0);
+ GOTO(out, rc = 0);
}
if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_FATAL2)) {
spin_lock(&lfsck->li_lock);
thread_set_flags(thread, SVC_STOPPING);
spin_unlock(&lfsck->li_lock);
- RETURN(-EINVAL);
+ GOTO(out, rc = -EINVAL);
}
rc = iops->next(env, di);
if (rc > 0 && !lfsck->li_oit_over)
lfsck_close_dir(env, lfsck, rc);
- RETURN(rc);
+ GOTO(out, rc);
+
+out:
+ if (lso != NULL)
+ lfsck_assistant_object_put(env, lso);
+
+ return rc;
}
/**
__u8 ll_ost_bitmap[0];
};
+struct lfsck_assistant_object {
+ struct lu_fid lso_fid;
+ __u64 lso_oit_cookie;
+ struct lu_attr lso_attr;
+ atomic_t lso_ref;
+ unsigned int lso_dead:1,
+ lso_is_dir:1;
+};
+
struct lfsck_component;
struct lfsck_tgt_descs;
struct lfsck_tgt_desc;
int (*lfsck_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_req {
- struct list_head lar_list;
- struct lu_fid lar_fid;
+ struct list_head lar_list;
+ struct lfsck_assistant_object *lar_parent;
};
struct lfsck_namespace_req {
struct lfsck_assistant_req lnr_lar;
struct lfsck_lmv *lnr_lmv;
struct lu_fid lnr_fid;
- __u64 lnr_oit_cookie;
__u64 lnr_dir_cookie;
__u32 lnr_attr;
__u32 lnr_size;
char lnr_name[0];
};
+struct lfsck_layout_req {
+ struct lfsck_assistant_req llr_lar;
+ struct dt_object *llr_child;
+ __u32 llr_ost_idx;
+ __u32 llr_lov_idx; /* offset in LOV EA */
+};
+
struct lfsck_assistant_operations {
int (*la_handler_p1)(const struct lu_env *env,
struct lfsck_component *com,
struct lu_fid lti_fid3;
struct lu_attr lti_la;
struct lu_attr lti_la2;
- struct lu_attr lti_la3;
struct ost_id lti_oi;
union {
struct lustre_mdt_attrs lti_lma;
struct lfsck_assistant_data *
lfsck_assistant_data_init(struct lfsck_assistant_operations *lao,
const char *name);
+struct lfsck_assistant_object *
+lfsck_assistant_object_init(const struct lu_env *env, const struct lu_fid *fid,
+ const struct lu_attr *attr, __u64 cookie,
+ bool is_dir);
+struct dt_object *
+lfsck_assistant_object_load(const struct lu_env *env,
+ struct lfsck_instance *lfsck,
+ struct lfsck_assistant_object *lso);
int lfsck_async_interpret_common(const struct lu_env *env,
struct ptlrpc_request *req,
void *args, int rc);
const char *name);
int lfsck_namespace_striped_dir_rescan(const struct lu_env *env,
struct lfsck_component *com,
- struct dt_object *dir,
struct lfsck_namespace_req *lnr);
int lfsck_namespace_handle_striped_master(const struct lu_env *env,
struct lfsck_component *com,
- struct dt_object *dir,
struct lfsck_namespace_req *lnr);
/* lfsck_layout.c */
dst->lmv_hash_type = cpu_to_le32(src->lmv_hash_type);
dst->lmv_layout_version = cpu_to_le32(src->lmv_layout_version);
}
+
+static inline struct lfsck_assistant_object *
+lfsck_assistant_object_get(struct lfsck_assistant_object *lso)
+{
+ atomic_inc(&lso->lso_ref);
+
+ return lso;
+}
+
+static inline void
+lfsck_assistant_object_put(const struct lu_env *env,
+ struct lfsck_assistant_object *lso)
+{
+ if (atomic_dec_and_test(&lso->lso_ref))
+ OBD_FREE_PTR(lso);
+}
#endif /* _LFSCK_INTERNAL_H */
unsigned int llsd_rbtree_valid:1;
};
-struct lfsck_layout_object {
- struct lu_attr llo_attr;
- atomic_t llo_ref;
- __u64 llo_cookie;
-};
-
-struct lfsck_layout_req {
- struct lfsck_assistant_req llr_lar;
- struct lfsck_layout_object *llr_parent;
- struct dt_object *llr_child;
- __u32 llr_ost_idx;
- __u32 llr_lov_idx; /* offset in LOV EA */
-};
-
struct lfsck_layout_slave_async_args {
struct obd_export *llsaa_exp;
struct lfsck_component *llsaa_com;
struct lfsck_layout_slave_target *llsaa_llst;
};
-static struct lfsck_layout_object *
-lfsck_layout_object_init(const struct lu_env *env, struct dt_object *obj,
- __u64 cookie)
-{
- struct lfsck_layout_object *llo;
- int rc;
-
- OBD_ALLOC_PTR(llo);
- if (llo == NULL)
- return ERR_PTR(-ENOMEM);
-
- rc = dt_attr_get(env, obj, &llo->llo_attr);
- if (rc != 0) {
- OBD_FREE_PTR(llo);
-
- return ERR_PTR(rc);
- }
-
- llo->llo_cookie = cookie;
- atomic_set(&llo->llo_ref, 1);
-
- return llo;
-}
-
static inline void
lfsck_layout_llst_put(struct lfsck_layout_slave_target *llst)
{
return NULL;
}
-static inline void lfsck_layout_object_put(const struct lu_env *env,
- struct lfsck_layout_object *llo)
-{
- if (atomic_dec_and_test(&llo->llo_ref))
- OBD_FREE_PTR(llo);
-}
-
static struct lfsck_layout_req *
-lfsck_layout_assistant_req_init(struct lfsck_layout_object *parent,
- const struct lu_fid *pfid,
+lfsck_layout_assistant_req_init(struct lfsck_assistant_object *lso,
struct dt_object *child, __u32 ost_idx,
__u32 lov_idx)
{
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&llr->llr_lar.lar_list);
- llr->llr_lar.lar_fid = *pfid;
-
- atomic_inc(&parent->llo_ref);
- llr->llr_parent = parent;
+ llr->llr_lar.lar_parent = lfsck_assistant_object_get(lso);
llr->llr_child = child;
llr->llr_ost_idx = ost_idx;
llr->llr_lov_idx = lov_idx;
container_of0(lar, struct lfsck_layout_req, llr_lar);
lfsck_object_put(env, llr->llr_child);
- lfsck_layout_object_put(env, llr->llr_parent);
+ lfsck_assistant_object_put(env, lar->lar_parent);
OBD_FREE_PTR(llr);
}
struct lfsck_component *com,
struct dt_object *parent,
struct lfsck_layout_req *llr,
- const struct lu_attr *pla)
+ struct lu_attr *la)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
struct filter_fid *pfid = &info->lti_new_pfid;
struct dt_object_format *dof = &info->lti_dof;
- struct lu_attr *cla = &info->lti_la2;
struct dt_object *child = llr->llr_child;
struct dt_device *dev = lfsck_obj2dev(child);
const struct lu_fid *tfid = lu_object_fid(&parent->do_lu);
if (!create)
GOTO(log, rc = 1);
- memset(cla, 0, sizeof(*cla));
- cla->la_uid = pla->la_uid;
- cla->la_gid = pla->la_gid;
- cla->la_mode = S_IFREG | 0666;
- cla->la_valid = LA_TYPE | LA_MODE | LA_UID | LA_GID |
- LA_ATIME | LA_MTIME | LA_CTIME;
- memset(dof, 0, sizeof(*dof));
-
rc = lfsck_ibits_lock(env, com->lc_lfsck, parent, &lh,
MDS_INODELOCK_LAYOUT | MDS_INODELOCK_XATTR,
LCK_EX);
if (rc != 0)
GOTO(log, rc);
+ rc = dt_attr_get(env, parent, la);
+ if (rc != 0)
+ GOTO(unlock1, rc);
+
+ la->la_mode = S_IFREG | 0666;
+ la->la_atime = la->la_mtime = la->la_ctime = 0;
+ la->la_valid = LA_TYPE | LA_MODE | LA_UID | LA_GID |
+ LA_ATIME | LA_MTIME | LA_CTIME;
+ memset(dof, 0, sizeof(*dof));
pfid->ff_parent.f_seq = cpu_to_le64(tfid->f_seq);
pfid->ff_parent.f_oid = cpu_to_le32(tfid->f_oid);
/* Currently, the filter_fid::ff_parent::f_ver is not the real parent
if (IS_ERR(handle))
GOTO(unlock1, rc = PTR_ERR(handle));
- rc = dt_declare_create(env, child, cla, NULL, dof, handle);
+ rc = dt_declare_create(env, child, la, NULL, dof, handle);
if (rc != 0)
GOTO(stop, rc);
if (unlikely(lfsck_is_dead_obj(parent)))
GOTO(unlock2, rc = 1);
- rc = dt_create(env, child, cla, NULL, dof, handle);
+ rc = dt_create(env, child, la, NULL, dof, handle);
if (rc != 0)
GOTO(unlock2, rc);
"stripe-index %u, owner %u/%u. %s: rc = %d\n",
lfsck_lfsck2name(com->lc_lfsck), PFID(lfsck_dto2fid(parent)),
PFID(lfsck_dto2fid(child)), llr->llr_ost_idx,
- llr->llr_lov_idx, pla->la_uid, pla->la_gid,
+ llr->llr_lov_idx, la->la_uid, la->la_gid,
create ? "Create the lost OST-object as required" :
"Keep the MDT-object there by default", rc);
struct lfsck_component *com,
struct dt_object *parent,
struct lfsck_layout_req *llr,
- const struct lu_attr *pla)
+ struct lu_attr *la)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
struct filter_fid *pfid = &info->lti_new_pfid;
- struct lu_attr *tla = &info->lti_la3;
struct dt_object *child = llr->llr_child;
struct dt_device *dev = lfsck_obj2dev(child);
const struct lu_fid *tfid = lu_object_fid(&parent->do_lu);
if (rc != 0)
GOTO(stop, rc);
- tla->la_valid = LA_UID | LA_GID;
- tla->la_uid = pla->la_uid;
- tla->la_gid = pla->la_gid;
- rc = dt_declare_attr_set(env, child, tla, handle);
+ rc = dt_attr_get(env, parent, la);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ la->la_valid = LA_UID | LA_GID;
+ rc = dt_declare_attr_set(env, child, la, handle);
if (rc != 0)
GOTO(stop, rc);
GOTO(unlock2, rc);
/* Get the latest parent's owner. */
- rc = dt_attr_get(env, parent, tla);
+ rc = dt_attr_get(env, parent, la);
if (rc != 0)
GOTO(unlock2, rc);
- tla->la_valid = LA_UID | LA_GID;
- rc = dt_attr_set(env, child, tla, handle);
+ la->la_valid = LA_UID | LA_GID;
+ rc = dt_attr_set(env, child, la, handle);
GOTO(unlock2, rc);
"stripe-index %u, owner %u/%u: rc = %d\n",
lfsck_lfsck2name(com->lc_lfsck), PFID(lfsck_dto2fid(parent)),
PFID(lfsck_dto2fid(child)), llr->llr_ost_idx, llr->llr_lov_idx,
- pla->la_uid, pla->la_gid, rc);
+ la->la_uid, la->la_gid, rc);
return rc;
}
child = container_of(n, struct dt_object, do_lu);
memset(hint, 0, sizeof(*hint));
+ rc = dt_attr_get(env, parent, la);
+ if (rc != 0)
+ GOTO(log, rc);
+
la->la_valid = LA_UID | LA_GID;
memset(dof, 0, sizeof(*dof));
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);
struct lfsck_component *com,
struct dt_object *parent,
struct lfsck_layout_req *llr,
- struct lu_attr *pla)
+ struct lu_attr *la)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
- struct lu_attr *tla = &info->lti_la3;
+ struct lu_attr *tla = &info->lti_la;
struct dt_object *child = llr->llr_child;
struct dt_device *dev = lfsck_obj2dev(child);
struct thandle *handle;
if (IS_ERR(handle))
GOTO(log, rc = PTR_ERR(handle));
- tla->la_uid = pla->la_uid;
- tla->la_gid = pla->la_gid;
+ tla->la_uid = la->la_uid;
+ tla->la_gid = la->la_gid;
tla->la_valid = LA_UID | LA_GID;
rc = dt_declare_attr_set(env, child, tla, handle);
if (rc != 0)
GOTO(unlock, rc = 1);
/* Get the latest parent's owner. */
- rc = dt_attr_get(env, parent, tla);
+ rc = dt_attr_get(env, parent, la);
if (rc != 0)
GOTO(unlock, rc);
/* Some others chown/chgrp during the LFSCK, needs to do nothing. */
- if (unlikely(tla->la_uid != pla->la_uid ||
- tla->la_gid != pla->la_gid))
+ if (unlikely(tla->la_uid != la->la_uid ||
+ tla->la_gid != la->la_gid))
GOTO(unlock, rc = 1);
- tla->la_valid = LA_UID | LA_GID;
rc = dt_attr_set(env, child, tla, handle);
GOTO(unlock, rc);
"stripe-index %u, owner %u/%u: rc = %d\n",
lfsck_lfsck2name(com->lc_lfsck), PFID(lfsck_dto2fid(parent)),
PFID(lfsck_dto2fid(child)), llr->llr_ost_idx, llr->llr_lov_idx,
- pla->la_uid, pla->la_gid, rc);
+ la->la_uid, la->la_gid, rc);
return rc;
}
* MDT-object (@parent) via the XATTR_NAME_FID xattr (@pfid). */
static int lfsck_layout_check_parent(const struct lu_env *env,
struct lfsck_component *com,
- struct dt_object *parent,
+ struct lfsck_assistant_object *lso,
const struct lu_fid *pfid,
const struct lu_fid *cfid,
- const struct lu_attr *pla,
const struct lu_attr *cla,
struct lfsck_layout_req *llr,
struct lu_buf *lov_ea, __u32 idx)
if (fid_is_zero(pfid)) {
/* client never wrote. */
if (cla->la_size == 0 && cla->la_blocks == 0) {
+ struct lu_attr *pla = &lso->lso_attr;
+
+ /* Someone may has changed the owner after the @pla
+ * pre-loaded. It can be handled when repairs owner
+ * inside lfsck_layout_repair_owner(). */
if (unlikely(cla->la_uid != pla->la_uid ||
cla->la_gid != pla->la_gid))
- RETURN (LLIT_INCONSISTENT_OWNER);
+ RETURN(LLIT_INCONSISTENT_OWNER);
RETURN(0);
}
if (unlikely(!fid_is_sane(pfid)))
RETURN(LLIT_UNMATCHED_PAIR);
- if (lu_fid_eq(pfid, lu_object_fid(&parent->do_lu))) {
+ if (lu_fid_eq(pfid, &lso->lso_fid)) {
if (llr->llr_lov_idx == idx)
RETURN(0);
{
struct lfsck_layout_req *llr =
container_of0(lar, struct lfsck_layout_req, llr_lar);
+ struct lfsck_assistant_object *lso = lar->lar_parent;
struct lfsck_layout *lo = com->lc_file_ram;
struct lfsck_thread_info *info = lfsck_env_info(env);
struct filter_fid_old *pea = &info->lti_old_pfid;
struct lu_fid *pfid = &info->lti_fid;
struct lu_buf buf = { NULL };
- struct dt_object *parent;
+ struct dt_object *parent = NULL;
struct dt_object *child = llr->llr_child;
- struct lu_attr *pla = &info->lti_la;
- struct lu_attr *cla = &info->lti_la2;
+ struct lu_attr *pla = &lso->lso_attr;
+ struct lu_attr *cla = &info->lti_la;
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
enum lfsck_layout_inconsistency_type type = LLIT_NONE;
int rc;
ENTRY;
- parent = lfsck_object_find_bottom(env, lfsck, &lar->lar_fid);
- if (IS_ERR(parent))
- RETURN(PTR_ERR(parent));
-
- if (unlikely(lfsck_is_dead_obj(parent)))
- GOTO(put_parent, rc = 0);
-
- rc = dt_attr_get(env, parent, pla);
- if (rc != 0)
- GOTO(out, rc);
+ if (lso->lso_dead)
+ RETURN(0);
rc = dt_attr_get(env, child, cla);
if (rc == -ENOENT) {
- if (unlikely(lfsck_is_dead_obj(parent)))
- GOTO(put_parent, rc = 0);
+ parent = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(parent)) {
+ rc = PTR_ERR(parent);
+
+ RETURN(rc == -ENOENT ? 0 : rc);
+ }
type = LLIT_DANGLING;
goto repair;
pfid->f_ver = 0;
}
- rc = lfsck_layout_check_parent(env, com, parent, pfid,
+ rc = lfsck_layout_check_parent(env, com, lso, pfid,
lu_object_fid(&child->do_lu),
- pla, cla, llr, &buf, idx);
+ cla, llr, &buf, idx);
if (rc > 0) {
type = rc;
goto repair;
if (rc < 0)
GOTO(out, rc);
+ /* Someone may has changed the owner after the parent attr pre-loaded.
+ * It can be handled later inside the lfsck_layout_repair_owner(). */
if (unlikely(cla->la_uid != pla->la_uid ||
cla->la_gid != pla->la_gid)) {
type = LLIT_INCONSISTENT_OWNER;
}
repair:
- if (bk->lb_param & LPF_DRYRUN) {
- if (type != LLIT_NONE)
- GOTO(out, rc = 1);
- else
- GOTO(out, rc = 0);
+ if (type == LLIT_NONE)
+ GOTO(out, rc = 0);
+
+ if (bk->lb_param & LPF_DRYRUN)
+ GOTO(out, rc = 1);
+
+ if (parent == NULL) {
+ parent = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(parent)) {
+ rc = PTR_ERR(parent);
+
+ if (rc == -ENOENT)
+ RETURN(0);
+
+ GOTO(out, rc);
+ }
}
switch (type) {
}
up_write(&com->lc_sem);
-put_parent:
- lfsck_object_put(env, parent);
+ if (parent != NULL && !IS_ERR(parent))
+ lfsck_object_put(env, parent);
return rc;
}
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct lfsck_layout *lo = com->lc_file_ram;
struct lfsck_assistant_data *lad = com->lc_data;
- struct lfsck_layout_object *llo = NULL;
+ struct lfsck_assistant_object *lso = NULL;
struct lov_ost_data_v1 *objs;
struct lfsck_tgt_descs *ltds = &lfsck->li_ost_descs;
struct ptlrpc_thread *mthread = &lfsck->li_thread;
if (rc != 0)
goto next;
- if (llo == NULL) {
- llo = lfsck_layout_object_init(env, parent,
- lfsck->li_pos_current.lp_oit_cookie);
- if (IS_ERR(llo)) {
- rc = PTR_ERR(llo);
+ if (lso == NULL) {
+ struct lu_attr *attr = &info->lti_la;
+
+ rc = dt_attr_get(env, parent, attr);
+ if (rc != 0) {
+ rc = PTR_ERR(lso);
+ goto next;
+ }
+
+ lso = lfsck_assistant_object_init(env,
+ lfsck_dto2fid(parent), attr,
+ lfsck->li_pos_current.lp_oit_cookie, false);
+ if (IS_ERR(lso)) {
+ rc = PTR_ERR(lso);
+ lso = NULL;
+
goto next;
}
}
- llr = lfsck_layout_assistant_req_init(llo,
- lfsck_dto2fid(parent),
- cobj, index, i);
+ llr = lfsck_layout_assistant_req_init(lso, cobj, index, i);
if (IS_ERR(llr)) {
rc = PTR_ERR(llr);
goto next;
GOTO(out, rc = 0);
out:
- if (llo != NULL && !IS_ERR(llo))
- lfsck_layout_object_put(env, llo);
+ if (lso != NULL)
+ lfsck_assistant_object_put(env, lso);
return rc;
}
static int lfsck_layout_exec_dir(const struct lu_env *env,
struct lfsck_component *com,
+ struct lfsck_assistant_object *lso,
struct lu_dirent *ent, __u16 type)
{
return 0;
llr = list_entry(lad->lad_req_list.next,
struct lfsck_layout_req,
llr_lar.lar_list);
- pos->lp_oit_cookie = llr->llr_parent->llo_cookie - 1;
+ pos->lp_oit_cookie = llr->llr_lar.lar_parent->lso_oit_cookie - 1;
}
struct lfsck_assistant_operations lfsck_layout_assistant_ops = {
return lad;
}
+struct lfsck_assistant_object *
+lfsck_assistant_object_init(const struct lu_env *env, const struct lu_fid *fid,
+ const struct lu_attr *attr, __u64 cookie,
+ bool is_dir)
+{
+ struct lfsck_assistant_object *lso;
+
+ OBD_ALLOC_PTR(lso);
+ if (lso == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ lso->lso_fid = *fid;
+ if (attr != NULL)
+ lso->lso_attr = *attr;
+
+ atomic_set(&lso->lso_ref, 1);
+ lso->lso_oit_cookie = cookie;
+ if (is_dir)
+ lso->lso_is_dir = 1;
+
+ return lso;
+}
+
+struct dt_object *
+lfsck_assistant_object_load(const struct lu_env *env,
+ struct lfsck_instance *lfsck,
+ struct lfsck_assistant_object *lso)
+{
+ struct dt_object *obj;
+
+ obj = lfsck_object_find_bottom(env, lfsck, &lso->lso_fid);
+ if (IS_ERR(obj))
+ return obj;
+
+ if (unlikely(!dt_object_exists(obj) || lfsck_is_dead_obj(obj))) {
+ lso->lso_dead = 1;
+ lfsck_object_put(env, obj);
+
+ return ERR_PTR(-ENOENT);
+ }
+
+ if (lso->lso_is_dir && unlikely(!dt_try_as_dir(env, obj))) {
+ lfsck_object_put(env, obj);
+
+ return ERR_PTR(-ENOTDIR);
+ }
+
+ return obj;
+}
+
/**
* Generic LFSCK asynchronous communication interpretor function.
* The LFSCK RPC reply for both the event notification and status
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);
}
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_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;
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;
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;
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(&lnr->lnr_lar.lar_fid), PFID(lfsck_dto2fid(child)),
+ PFID(lfsck_dto2fid(parent)), PFID(lfsck_dto2fid(child)),
type, cname->ln_name,
create ? "Create the lost OST-object as required" :
"Keep the MDT-object there by default", rc);
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;
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 (unlikely(!dt_try_as_dir(env, dir)))
- GOTO(put_dir, rc = -ENOTDIR);
+ 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 (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 (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,
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);
+
+ 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);
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) {
+ 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;
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);
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:
- lfsck_object_put(env, dir);
+ if (dir != NULL && !IS_ERR(dir))
+ lfsck_object_put(env, dir);
return rc;
}
(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);
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,
*
* \param[in] env pointer to the thread context
* \param[in] com pointer to the lfsck component
- * \paran[in] dir pointer to the striped directory or its shard to be
- * rescanned
* \param[in] lnr pointer to the namespace request that contains the
* striped directory or the shard
*
*/
int lfsck_namespace_striped_dir_rescan(const struct lu_env *env,
struct lfsck_component *com,
- struct dt_object *dir,
struct lfsck_namespace_req *lnr)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
struct lfsck_lmv *llmv = lnr->lnr_lmv;
struct lmv_mds_md_v1 *lmv = &llmv->ll_lmv;
struct lmv_mds_md_v1 *lmv2 = &info->lti_lmv2;
- const struct lu_fid *pfid = lfsck_dto2fid(dir);
+ struct lfsck_assistant_object *lso = lnr->lnr_lar.lar_parent;
+ const struct lu_fid *pfid = &lso->lso_fid;
+ struct dt_object *dir = NULL;
+ struct dt_object *obj = NULL;
struct lu_seq_range *range = &info->lti_range;
struct seq_server_site *ss = lfsck_dev_site(lfsck);
__u32 stripe_count;
if (llmv->ll_lmv_slave) {
if (llmv->ll_lmv_verified) {
ns->ln_striped_shards_scanned++;
- lfsck_namespace_trace_update(env, com,
- lfsck_dto2fid(dir),
+ lfsck_namespace_trace_update(env, com, pfid,
LNTF_UNCERTAIN_LMV |
LNTF_RECHECK_NAME_HASH, false);
}
}
if (llmv->ll_lmv_updated) {
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(dir)) {
+ rc = PTR_ERR(dir);
+
+ RETURN(rc == -ENOENT ? 0 : rc);
+ }
+ }
+
lmv->lmv_layout_version++;
rc = lfsck_namespace_update_lmv(env, com, dir, lmv, false);
if (rc != 0)
fld_range_set_mdt(range);
for (i = 0; i <= llmv->ll_max_filled_off; i++) {
- struct dt_object *obj = NULL;
struct lfsck_slave_lmv_rec *lslr = llmv->ll_lslr + i;
const struct lu_fid *cfid = &lslr->lslr_fid;
const struct lu_name *cname;
obj = lfsck_object_find_bottom_nowait(env, lfsck, cfid);
if (IS_ERR(obj)) {
- if (lfsck_is_dead_obj(dir))
- RETURN(0);
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck,
+ lso);
+ if (IS_ERR(dir)) {
+ if (PTR_ERR(dir) == -ENOENT)
+ RETURN(0);
+
+ dir = NULL;
+ }
+ } else if (lfsck_is_dead_obj(dir)) {
+ GOTO(out, rc = 0);
+ }
rc1 = PTR_ERR(obj);
goto next;
repair:
if (create) {
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck,
+ lso);
+ if (IS_ERR(dir)) {
+ rc1 = PTR_ERR(dir);
+
+ if (rc1 == -ENOENT)
+ GOTO(out, rc = 0);
+
+ dir = NULL;
+ goto next;
+ }
+ }
+
rc1 = lfsck_namespace_repair_dangling(env, com, dir,
obj, lnr);
if (rc1 >= 0) {
}
if (rename) {
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck,
+ lso);
+ if (IS_ERR(dir)) {
+ rc1 = PTR_ERR(dir);
+
+ if (rc1 == -ENOENT)
+ GOTO(out, rc = 0);
+
+ dir = NULL;
+ goto next;
+ }
+ }
+
rc1 = lfsck_namespace_repair_dirent(env, com, dir, obj,
info->lti_tmpbuf2, lnr->lnr_name,
lnr->lnr_type, true, false);
if (rc1 != 0)
goto next;
+ if (dir == NULL) {
+ dir = lfsck_assistant_object_load(env, lfsck,
+ lso);
+ if (IS_ERR(dir)) {
+ rc1 = PTR_ERR(dir);
+
+ if (rc1 == -ENOENT)
+ GOTO(out, rc = 0);
+
+ dir = NULL;
+ goto next;
+ }
+ }
+
rc1 = linkea_add_buf(&ldata, cname, lfsck_dto2fid(dir));
if (rc1 != 0)
goto next;
repair_lmvea ? "yes" : "no",
lmvea_repaired ? "yes" : "no", rc1);
- if (obj != NULL && !IS_ERR(obj))
+ if (obj != NULL && !IS_ERR(obj)) {
lfsck_object_put(env, obj);
+ obj = NULL;
+ }
if (rc1 < 0) {
rc = rc1;
}
}
- RETURN(rc);
+ GOTO(out, rc);
+
+out:
+ if (obj != NULL && !IS_ERR(obj))
+ lfsck_object_put(env, obj);
+
+ if (dir != NULL && !IS_ERR(dir))
+ lfsck_object_put(env, dir);
+
+ return rc;
}
/**
*
* \param[in] env pointer to the thread context
* \param[in] com pointer to the lfsck component
- * \param[in] dir pointer to the master MDT-object of the
- * striped directory
* \param[in] lnr pointer to the namespace request that contains the
* shard's name, parent object, parent's LMV, and ect.
*
*/
int lfsck_namespace_handle_striped_master(const struct lu_env *env,
struct lfsck_component *com,
- struct dt_object *dir,
struct lfsck_namespace_req *lnr)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_namespace *ns = com->lc_file_ram;
struct lfsck_lmv *llmv = lnr->lnr_lmv;
- const struct lu_fid *pfid = lfsck_dto2fid(dir);
+ struct lfsck_assistant_object *lso = lnr->lnr_lar.lar_parent;
+ const struct lu_fid *pfid = &lso->lso_fid;
+ struct dt_object *dir;
struct dt_object *obj = NULL;
struct dt_device *dev = NULL;
int shard_idx = 0;
if (unlikely(llmv->ll_ignore))
RETURN(0);
+ dir = lfsck_assistant_object_load(env, lfsck, lso);
+ if (IS_ERR(dir)) {
+ rc = PTR_ERR(dir);
+
+ RETURN(rc == -ENOENT ? 0 : rc);
+ }
+
shard_idx = lfsck_find_mdt_idx_by_fid(env, lfsck, &lnr->lnr_fid);
if (shard_idx < 0)
GOTO(fail_lmv, rc = shard_idx);
CDEBUG(D_LFSCK, "%s: namespace LFSCK assistant fail to handle "
"the shard: "DFID", parent "DFID", name %.*s: rc = %d\n",
lfsck_lfsck2name(lfsck), PFID(&lnr->lnr_fid),
- PFID(lfsck_dto2fid(dir)),
- lnr->lnr_namelen, lnr->lnr_name, rc);
+ PFID(pfid), lnr->lnr_namelen, lnr->lnr_name, rc);
if ((rc == -ENOTCONN || rc == -ESHUTDOWN || rc == -EREMCHG ||
rc == -ETIMEDOUT || rc == -EHOSTDOWN ||
if (obj != NULL && !IS_ERR(obj))
lfsck_object_put(env, obj);
+ lfsck_object_put(env, dir);
+
return rc;
}