From: Fan Yong Date: Tue, 15 Jan 2013 09:47:16 +0000 (+0800) Subject: LU-1866 lfsck: LFSCK for namespace consistency (1) X-Git-Tag: 2.3.61~31 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=3d6a1b79c92933f8d822919229016fbb0122b769 LU-1866 lfsck: LFSCK for namespace consistency (1) It is the first part of LFSCK 1.5 for namespace consistency check and repair. It mainly implements the LFSCK namespace component internal framework and external APIs. The functionality parts for the LFSCK namespace component, such as lfsck_operations::lfsck_{exec_dir,dump,double_scan}, are not included. They will be implemented in other patches. Signed-off-by: Fan Yong Change-Id: I011e06c991577e632eadf364b87be74f1f5535c6 Reviewed-on: http://review.whamcloud.com/4910 Reviewed-by: Mike Pershin Tested-by: Hudson Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/dt_object.h b/lustre/include/dt_object.h index f8c7477..4207f1c 100644 --- a/lustre/include/dt_object.h +++ b/lustre/include/dt_object.h @@ -213,6 +213,7 @@ enum dt_index_flags { */ extern const struct dt_index_features dt_directory_features; extern const struct dt_index_features dt_otable_features; +extern const struct dt_index_features dt_lfsck_features; /* index features supported by the accounting objects */ extern const struct dt_index_features dt_acct_features; @@ -811,6 +812,10 @@ int dt_path_parser(const struct lu_env *env, char *local, dt_entry_func_t entry_func, void *data); +struct dt_object * +dt_store_resolve(const struct lu_env *env, struct dt_device *dt, + const char *path, struct lu_fid *fid); + struct dt_object *dt_store_open(const struct lu_env *env, struct dt_device *dt, const char *dirname, diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index 8226334..0750b87 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -1481,6 +1481,7 @@ struct lov_mds_md_v1 { /* LOV EA mds/wire data (little-endian) */ #define XATTR_NAME_VERSION "trusted.version" #define XATTR_NAME_SOM "trusted.som" #define XATTR_NAME_HSM "trusted.hsm" +#define XATTR_NAME_LFSCK_NAMESPACE "trusted.lfsck_namespace" struct lov_mds_md_v3 { /* LOV EA mds/wire data (little-endian) */ diff --git a/lustre/include/lustre/lustre_lfsck_user.h b/lustre/include/lustre/lustre_lfsck_user.h index 1e2b011..aaa9330 100644 --- a/lustre/include/lustre/lustre_lfsck_user.h +++ b/lustre/include/lustre/lustre_lfsck_user.h @@ -50,6 +50,9 @@ enum lfsck_type { /* For MDT-MDT consistency check/repair. */ LT_DNE = 0x0002, + + /* For FID-in-dirent and linkEA consistency check/repair. */ + LT_NAMESPACE = 0x0004, }; #define LFSCK_VERSION_V1 1 diff --git a/lustre/include/lustre_fid.h b/lustre/include/lustre_fid.h index 388c097..539e829 100644 --- a/lustre/include/lustre_fid.h +++ b/lustre/include/lustre_fid.h @@ -232,6 +232,7 @@ enum local_oid { MGS_CONFIGS_OID = 4119UL, OFD_HEALTH_CHECK_OID = 4120UL, MDD_LOV_OBJ_OSEQ = 4121UL, + LFSCK_NAMESPACE_OID = 4122UL, }; static inline void lu_local_obj_fid(struct lu_fid *fid, __u32 oid) diff --git a/lustre/mdd/mdd_device.c b/lustre/mdd/mdd_device.c index f87fa42..0388758 100644 --- a/lustre/mdd/mdd_device.c +++ b/lustre/mdd/mdd_device.c @@ -1746,6 +1746,13 @@ static struct lu_local_obj_desc llod_lfsck_bookmark = { .llod_is_index = 0, }; +static struct lu_local_obj_desc llod_lfsck_namespace = { + .llod_name = lfsck_namespace_name, + .llod_oid = LFSCK_NAMESPACE_OID, + .llod_is_index = 1, + .llod_feat = &dt_lfsck_features, +}; + static int __init mdd_mod_init(void) { struct lprocfs_static_vars lvars; @@ -1766,6 +1773,7 @@ static int __init mdd_mod_init(void) llo_local_obj_register(&llod_mdd_orphan); llo_local_obj_register(&llod_mdd_root); llo_local_obj_register(&llod_lfsck_bookmark); + llo_local_obj_register(&llod_lfsck_namespace); rc = class_register_type(&mdd_obd_device_ops, NULL, lvars.module_vars, LUSTRE_MDD_NAME, &mdd_device_type); @@ -1780,6 +1788,7 @@ static void __exit mdd_mod_exit(void) llo_local_obj_unregister(&llod_mdd_orphan); llo_local_obj_unregister(&llod_mdd_root); llo_local_obj_unregister(&llod_lfsck_bookmark); + llo_local_obj_unregister(&llod_lfsck_namespace); class_unregister_type(LUSTRE_MDD_NAME); lu_kmem_fini(mdd_caches); diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index 248a42a..8d8f4d8 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -94,6 +94,7 @@ struct mdd_dot_lustre_objs { }; extern const char lfsck_bookmark_name[]; +extern const char lfsck_namespace_name[]; struct mdd_device { struct md_device mdd_md_dev; diff --git a/lustre/mdd/mdd_lfsck.c b/lustre/mdd/mdd_lfsck.c index 5fc9914..04f3a52 100644 --- a/lustre/mdd/mdd_lfsck.c +++ b/lustre/mdd/mdd_lfsck.c @@ -50,6 +50,7 @@ #define MDS_DIR_DUMMY_START 0xffffffffffffffffULL const char lfsck_bookmark_name[] = "lfsck_bookmark"; +const char lfsck_namespace_name[] = "lfsck_namespace"; /* misc functions */ @@ -65,6 +66,11 @@ static inline char *mdd_lfsck2name(struct md_lfsck *lfsck) return mdd2obd_dev(mdd)->obd_name; } +static inline void mdd_lfsck_component_get(struct lfsck_component *com) +{ + atomic_inc(&com->lc_ref); +} + static inline void mdd_lfsck_component_put(const struct lu_env *env, struct lfsck_component *com) { @@ -146,6 +152,11 @@ static void mdd_lfsck_pos_fill(const struct lu_env *env, struct md_lfsck *lfsck, spin_unlock(&lfsck->ml_lock); } +static inline void mdd_lfsck_pos_set_zero(struct lfsck_position *pos) +{ + memset(pos, 0, sizeof(*pos)); +} + static inline int mdd_lfsck_pos_is_zero(const struct lfsck_position *pos) { return pos->lp_oit_cookie == 0 && fid_is_zero(&pos->lp_dir_parent); @@ -358,6 +369,694 @@ static int mdd_lfsck_bookmark_init(const struct lu_env *env, return rc; } +/* lfsck_namespace file ops */ + +static void inline mdd_lfsck_position_to_cpu(struct lfsck_position *des, + struct lfsck_position *src) +{ + des->lp_oit_cookie = le64_to_cpu(src->lp_oit_cookie); + fid_le_to_cpu(&des->lp_dir_parent, &src->lp_dir_parent); + des->lp_dir_cookie = le64_to_cpu(src->lp_dir_cookie); +} + +static void inline mdd_lfsck_position_to_le(struct lfsck_position *des, + struct lfsck_position *src) +{ + des->lp_oit_cookie = cpu_to_le64(src->lp_oit_cookie); + fid_cpu_to_le(&des->lp_dir_parent, &src->lp_dir_parent); + des->lp_dir_cookie = cpu_to_le64(src->lp_dir_cookie); +} + +static void inline mdd_lfsck_namespace_to_cpu(struct lfsck_namespace *des, + struct lfsck_namespace *src) +{ + des->ln_magic = le32_to_cpu(src->ln_magic); + des->ln_status = le32_to_cpu(src->ln_status); + des->ln_flags = le32_to_cpu(src->ln_flags); + des->ln_success_count = le32_to_cpu(src->ln_success_count); + des->ln_run_time_phase1 = le32_to_cpu(src->ln_run_time_phase1); + des->ln_run_time_phase2 = le32_to_cpu(src->ln_run_time_phase2); + des->ln_time_last_complete = le64_to_cpu(src->ln_time_last_complete); + des->ln_time_latest_start = le64_to_cpu(src->ln_time_latest_start); + des->ln_time_last_checkpoint = + le64_to_cpu(src->ln_time_last_checkpoint); + mdd_lfsck_position_to_cpu(&des->ln_pos_latest_start, + &src->ln_pos_latest_start); + mdd_lfsck_position_to_cpu(&des->ln_pos_last_checkpoint, + &src->ln_pos_last_checkpoint); + mdd_lfsck_position_to_cpu(&des->ln_pos_first_inconsistent, + &src->ln_pos_first_inconsistent); + des->ln_items_checked = le64_to_cpu(src->ln_items_checked); + des->ln_items_repaired = le64_to_cpu(src->ln_items_repaired); + des->ln_items_failed = le64_to_cpu(src->ln_items_failed); + des->ln_dirs_checked = le64_to_cpu(src->ln_dirs_checked); + des->ln_mlinked_checked = le64_to_cpu(src->ln_mlinked_checked); + des->ln_objs_checked_phase2 = le64_to_cpu(src->ln_objs_checked_phase2); + des->ln_objs_repaired_phase2 = + le64_to_cpu(src->ln_objs_repaired_phase2); + des->ln_objs_failed_phase2 = le64_to_cpu(src->ln_objs_failed_phase2); + des->ln_objs_nlink_repaired = le64_to_cpu(src->ln_objs_nlink_repaired); + des->ln_objs_lost_found = le64_to_cpu(src->ln_objs_lost_found); + fid_le_to_cpu(&des->ln_fid_latest_scanned_phase2, + &src->ln_fid_latest_scanned_phase2); +} + +static void inline mdd_lfsck_namespace_to_le(struct lfsck_namespace *des, + struct lfsck_namespace *src) +{ + des->ln_magic = cpu_to_le32(src->ln_magic); + des->ln_status = cpu_to_le32(src->ln_status); + des->ln_flags = cpu_to_le32(src->ln_flags); + des->ln_success_count = cpu_to_le32(src->ln_success_count); + des->ln_run_time_phase1 = cpu_to_le32(src->ln_run_time_phase1); + des->ln_run_time_phase2 = cpu_to_le32(src->ln_run_time_phase2); + des->ln_time_last_complete = cpu_to_le64(src->ln_time_last_complete); + des->ln_time_latest_start = cpu_to_le64(src->ln_time_latest_start); + des->ln_time_last_checkpoint = + cpu_to_le64(src->ln_time_last_checkpoint); + mdd_lfsck_position_to_le(&des->ln_pos_latest_start, + &src->ln_pos_latest_start); + mdd_lfsck_position_to_le(&des->ln_pos_last_checkpoint, + &src->ln_pos_last_checkpoint); + mdd_lfsck_position_to_le(&des->ln_pos_first_inconsistent, + &src->ln_pos_first_inconsistent); + des->ln_items_checked = cpu_to_le64(src->ln_items_checked); + des->ln_items_repaired = cpu_to_le64(src->ln_items_repaired); + des->ln_items_failed = cpu_to_le64(src->ln_items_failed); + des->ln_dirs_checked = cpu_to_le64(src->ln_dirs_checked); + des->ln_mlinked_checked = cpu_to_le64(src->ln_mlinked_checked); + des->ln_objs_checked_phase2 = cpu_to_le64(src->ln_objs_checked_phase2); + des->ln_objs_repaired_phase2 = + cpu_to_le64(src->ln_objs_repaired_phase2); + des->ln_objs_failed_phase2 = cpu_to_le64(src->ln_objs_failed_phase2); + des->ln_objs_nlink_repaired = cpu_to_le64(src->ln_objs_nlink_repaired); + des->ln_objs_lost_found = cpu_to_le64(src->ln_objs_lost_found); + fid_cpu_to_le(&des->ln_fid_latest_scanned_phase2, + &src->ln_fid_latest_scanned_phase2); +} + +/** + * \retval +ve: the lfsck_namespace is broken, the caller should reset it. + * \retval 0: succeed. + * \retval -ve: failed cases. + */ +static int mdd_lfsck_namespace_load(const struct lu_env *env, + struct lfsck_component *com) +{ + int len = com->lc_file_size; + int rc; + + rc = dt_xattr_get(env, com->lc_obj, + mdd_buf_get(env, com->lc_file_disk, len), + XATTR_NAME_LFSCK_NAMESPACE, BYPASS_CAPA); + if (rc == len) { + struct lfsck_namespace *ns = com->lc_file_ram; + + mdd_lfsck_namespace_to_cpu(ns, + (struct lfsck_namespace *)com->lc_file_disk); + if (ns->ln_magic != LFSCK_NAMESPACE_MAGIC) { + CWARN("%.16s: invalid lfsck_namespace magic " + "0x%x != 0x%x\n", + mdd_lfsck2name(com->lc_lfsck), + ns->ln_magic, LFSCK_NAMESPACE_MAGIC); + rc = 1; + } else { + rc = 0; + } + } else if (rc != -ENODATA) { + CERROR("%.16s: fail to load lfsck_namespace, expected = %d, " + "rc = %d\n", mdd_lfsck2name(com->lc_lfsck), len, rc); + if (rc >= 0) + rc = 1; + } + return rc; +} + +static int mdd_lfsck_namespace_store(const struct lu_env *env, + struct lfsck_component *com, bool init) +{ + struct dt_object *obj = com->lc_obj; + struct md_lfsck *lfsck = com->lc_lfsck; + struct mdd_device *mdd = mdd_lfsck2mdd(lfsck); + struct thandle *handle; + int len = com->lc_file_size; + int rc; + ENTRY; + + mdd_lfsck_namespace_to_le((struct lfsck_namespace *)com->lc_file_disk, + (struct lfsck_namespace *)com->lc_file_ram); + handle = dt_trans_create(env, mdd->mdd_bottom); + if (IS_ERR(handle)) { + rc = PTR_ERR(handle); + CERROR("%.16s: fail to create trans for storing " + "lfsck_namespace: %d\n,", mdd_lfsck2name(lfsck), rc); + RETURN(rc); + } + + rc = dt_declare_xattr_set(env, obj, + mdd_buf_get(env, com->lc_file_disk, len), + XATTR_NAME_LFSCK_NAMESPACE, 0, handle); + if (rc != 0) { + CERROR("%.16s: fail to declare trans for storing " + "lfsck_namespace: %d\n,", mdd_lfsck2name(lfsck), rc); + GOTO(out, rc); + } + + rc = dt_trans_start_local(env, mdd->mdd_bottom, handle); + if (rc != 0) { + CERROR("%.16s: fail to start trans for storing " + "lfsck_namespace: %d\n,", mdd_lfsck2name(lfsck), rc); + GOTO(out, rc); + } + + rc = dt_xattr_set(env, obj, + mdd_buf_get(env, com->lc_file_disk, len), + XATTR_NAME_LFSCK_NAMESPACE, + init ? LU_XATTR_CREATE : LU_XATTR_REPLACE, + handle, BYPASS_CAPA); + if (rc != 0) + CERROR("%.16s: fail to store lfsck_namespace, len = %d, " + "rc = %d\n", mdd_lfsck2name(lfsck), len, rc); + + GOTO(out, rc); + +out: + dt_trans_stop(env, mdd->mdd_bottom, handle); + return rc; +} + +static int mdd_lfsck_namespace_init(const struct lu_env *env, + struct lfsck_component *com) +{ + struct lfsck_namespace *ns = (struct lfsck_namespace *)com->lc_file_ram; + int rc; + + memset(ns, 0, sizeof(*ns)); + ns->ln_magic = LFSCK_NAMESPACE_MAGIC; + ns->ln_status = LS_INIT; + down_write(&com->lc_sem); + rc = mdd_lfsck_namespace_store(env, com, true); + up_write(&com->lc_sem); + return rc; +} + +static int mdd_declare_lfsck_namespace_unlink(const struct lu_env *env, + struct mdd_device *mdd, + struct dt_object *p, + struct dt_object *c, + const char *name, + struct thandle *handle) +{ + int rc; + + rc = dt_declare_delete(env, p, (const struct dt_key *)name, handle); + if (rc != 0) + return rc; + + rc = dt_declare_ref_del(env, c, handle); + if (rc != 0) + return rc; + + rc = dt_declare_destroy(env, c, handle); + return rc; +} + +static int mdd_lfsck_namespace_unlink(const struct lu_env *env, + struct mdd_device *mdd, + struct lfsck_component *com) +{ + struct mdd_thread_info *info = mdd_env_info(env); + struct lu_fid *fid = &info->mti_fid; + struct dt_object *child = com->lc_obj; + struct dt_object *parent; + struct thandle *handle; + int rc; + ENTRY; + + parent = dt_store_resolve(env, mdd->mdd_bottom, "", fid); + if (IS_ERR(parent)) + RETURN(rc = PTR_ERR(parent)); + + if (dt_try_as_dir(env, parent)) + GOTO(out, rc = -ENOTDIR); + + handle = dt_trans_create(env, mdd->mdd_bottom); + if (IS_ERR(handle)) + GOTO(out, rc = PTR_ERR(handle)); + + rc = mdd_declare_lfsck_namespace_unlink(env, mdd, parent, child, + lfsck_namespace_name, handle); + if (rc != 0) + GOTO(stop, rc); + + rc = dt_trans_start_local(env, mdd->mdd_bottom, handle); + if (rc != 0) + GOTO(stop, rc); + + rc = dt_delete(env, parent, (struct dt_key *)lfsck_namespace_name, + handle, BYPASS_CAPA); + if (rc != 0) + GOTO(stop, rc); + + rc = child->do_ops->do_ref_del(env, child, handle); + if (rc != 0) { + lu_local_obj_fid(fid, LFSCK_NAMESPACE_OID); + rc = dt_insert(env, parent, + (const struct dt_rec*)fid, + (const struct dt_key *)lfsck_namespace_name, + handle, BYPASS_CAPA, 1); + + GOTO(stop, rc); + } + + + rc = dt_destroy(env, child, handle); + if (rc == 0) { + lu_object_put(env, &child->do_lu); + com->lc_obj = NULL; + } + + GOTO(stop, rc); + +stop: + dt_trans_stop(env, mdd->mdd_bottom, handle); + +out: + lu_object_put(env, &parent->do_lu); + return rc; +} + +/* namespace APIs */ + +static int mdd_lfsck_namespace_reset(const struct lu_env *env, + struct lfsck_component *com, bool init) +{ + struct mdd_thread_info *info = mdd_env_info(env); + struct lu_fid *fid = &info->mti_fid; + struct lfsck_namespace *ns = (struct lfsck_namespace *)com->lc_file_ram; + struct mdd_device *mdd = mdd_lfsck2mdd(com->lc_lfsck); + struct md_object *mdo; + struct dt_object *dto; + int rc; + ENTRY; + + down_write(&com->lc_sem); + if (init) { + memset(ns, 0, sizeof(*ns)); + } else { + __u32 count = ns->ln_success_count; + __u64 last_time = ns->ln_time_last_complete; + + memset(ns, 0, sizeof(*ns)); + ns->ln_success_count = count; + ns->ln_time_last_complete = last_time; + } + ns->ln_magic = LFSCK_NAMESPACE_MAGIC; + ns->ln_status = LS_INIT; + + rc = mdd_lfsck_namespace_unlink(env, mdd, com); + if (rc != 0) + GOTO(out, rc); + + lu_local_obj_fid(fid, LFSCK_NAMESPACE_OID); + mdo = llo_store_create_index(env, &mdd->mdd_md_dev, mdd->mdd_bottom, "", + lfsck_namespace_name, fid, + &dt_lfsck_features); + if (IS_ERR(mdo)) + GOTO(out, rc = PTR_ERR(mdo)); + + lu_object_put(env, &mdo->mo_lu); + dto = dt_store_open(env, mdd->mdd_bottom, "", lfsck_namespace_name, fid); + if (IS_ERR(dto)) + GOTO(out, rc = PTR_ERR(dto)); + + com->lc_obj = dto; + rc = dto->do_ops->do_index_try(env, dto, &dt_lfsck_features); + if (rc != 0) + GOTO(out, rc); + + rc = mdd_lfsck_namespace_store(env, com, true); + + GOTO(out, rc); + +out: + up_write(&com->lc_sem); + return rc; +} + +static void +mdd_lfsck_namespace_fail(const struct lu_env *env, struct lfsck_component *com, + bool oit, bool new_checked) +{ + struct lfsck_namespace *ns = (struct lfsck_namespace *)com->lc_file_ram; + + down_write(&com->lc_sem); + if (new_checked) + com->lc_new_checked++; + ns->ln_items_failed++; + if (mdd_lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) + mdd_lfsck_pos_fill(env, com->lc_lfsck, + &ns->ln_pos_first_inconsistent, oit, !oit); + up_write(&com->lc_sem); +} + +static int mdd_lfsck_namespace_checkpoint(const struct lu_env *env, + struct lfsck_component *com, + bool init) +{ + struct md_lfsck *lfsck = com->lc_lfsck; + struct lfsck_namespace *ns = + (struct lfsck_namespace *)com->lc_file_ram; + int rc; + + if (com->lc_new_checked == 0 && !init) + return 0; + + down_write(&com->lc_sem); + + ns->ln_pos_last_checkpoint = lfsck->ml_pos_current; + if (init) { + ns->ln_time_last_checkpoint = ns->ln_time_latest_start; + ns->ln_pos_latest_start = lfsck->ml_pos_current; + } else { + ns->ln_run_time_phase1 += cfs_duration_sec(cfs_time_current() + + HALF_SEC - lfsck->ml_time_last_checkpoint); + ns->ln_time_last_checkpoint = cfs_time_current_sec(); + ns->ln_items_checked += com->lc_new_checked; + com->lc_new_checked = 0; + } + + rc = mdd_lfsck_namespace_store(env, com, false); + + up_write(&com->lc_sem); + return rc; +} + +static int mdd_lfsck_namespace_prep(const struct lu_env *env, + struct lfsck_component *com) +{ + struct md_lfsck *lfsck = com->lc_lfsck; + struct lfsck_namespace *ns = + (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_position *pos = &com->lc_pos_start; + + if (ns->ln_status == LS_COMPLETED) { + int rc; + + rc = mdd_lfsck_namespace_reset(env, com, false); + if (rc != 0) + return rc; + } + + down_write(&com->lc_sem); + + ns->ln_time_latest_start = cfs_time_current_sec(); + + spin_lock(&lfsck->ml_lock); + if (ns->ln_flags & LF_SCANNED_ONCE) { + if (!lfsck->ml_drop_dryrun || + mdd_lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) { + ns->ln_status = LS_SCANNING_PHASE2; + cfs_list_del_init(&com->lc_link); + cfs_list_add_tail(&com->lc_link, + &lfsck->ml_list_double_scan); + if (!cfs_list_empty(&com->lc_link_dir)) + cfs_list_del_init(&com->lc_link_dir); + mdd_lfsck_pos_set_zero(pos); + } else { + ns->ln_status = LS_SCANNING_PHASE1; + ns->ln_run_time_phase1 = 0; + ns->ln_run_time_phase2 = 0; + ns->ln_items_checked = 0; + ns->ln_items_repaired = 0; + ns->ln_items_failed = 0; + ns->ln_dirs_checked = 0; + ns->ln_mlinked_checked = 0; + ns->ln_objs_checked_phase2 = 0; + ns->ln_objs_repaired_phase2 = 0; + ns->ln_objs_failed_phase2 = 0; + ns->ln_objs_nlink_repaired = 0; + ns->ln_objs_lost_found = 0; + fid_zero(&ns->ln_fid_latest_scanned_phase2); + if (cfs_list_empty(&com->lc_link_dir)) + cfs_list_add_tail(&com->lc_link_dir, + &lfsck->ml_list_dir); + *pos = ns->ln_pos_first_inconsistent; + } + } else { + ns->ln_status = LS_SCANNING_PHASE1; + if (cfs_list_empty(&com->lc_link_dir)) + cfs_list_add_tail(&com->lc_link_dir, + &lfsck->ml_list_dir); + if (!lfsck->ml_drop_dryrun || + mdd_lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) { + *pos = ns->ln_pos_last_checkpoint; + pos->lp_oit_cookie++; + if (!fid_is_zero(&pos->lp_dir_parent)) { + if (pos->lp_dir_cookie == MDS_DIR_END_OFF) { + fid_zero(&pos->lp_dir_parent); + } else { + pos->lp_dir_cookie++; + } + } + } else { + *pos = ns->ln_pos_first_inconsistent; + } + } + spin_unlock(&lfsck->ml_lock); + + up_write(&com->lc_sem); + return 0; +} + +static int mdd_lfsck_namespace_exec_oit(const struct lu_env *env, + struct lfsck_component *com, + struct mdd_object *obj) +{ + down_write(&com->lc_sem); + com->lc_new_checked++; + if (S_ISDIR(mdd_object_type(obj))) + ((struct lfsck_namespace *)com->lc_file_ram)->ln_dirs_checked++; + up_write(&com->lc_sem); + return 0; +} + +/* XXX: to be implemented in other patch. */ +static int mdd_lfsck_namespace_exec_dir(const struct lu_env *env, + struct lfsck_component *com, + struct mdd_object *obj, + struct lu_dirent *ent) +{ + struct lfsck_namespace *ns = + (struct lfsck_namespace *)com->lc_file_ram; + const struct lu_name *cname; + int repaired; + + cname = mdd_name_get_const(env, ent->lde_name, ent->lde_namelen); + down_write(&com->lc_sem); + com->lc_new_checked++; + + if (ent->lde_attrs & LUDA_UPGRADE) { + ns->ln_flags |= LF_UPGRADE; + repaired = 1; + } else if (ent->lde_attrs & LUDA_REPAIR) { + ns->ln_flags |= LF_INCONSISTENT; + repaired = 1; + } else { + repaired = 0; + } + + ns->ln_items_repaired += repaired; + up_write(&com->lc_sem); + return 0; +} + +static int mdd_lfsck_namespace_post(const struct lu_env *env, + struct lfsck_component *com, + int result) +{ + struct md_lfsck *lfsck = com->lc_lfsck; + struct lfsck_namespace *ns = + (struct lfsck_namespace *)com->lc_file_ram; + int rc; + + down_write(&com->lc_sem); + + spin_lock(&lfsck->ml_lock); + if (result > 0) { + ns->ln_status = LS_SCANNING_PHASE2; + ns->ln_flags |= LF_SCANNED_ONCE; + ns->ln_flags &= ~LF_UPGRADE; + cfs_list_del_init(&com->lc_link); + cfs_list_del_init(&com->lc_link_dir); + cfs_list_add_tail(&com->lc_link, &lfsck->ml_list_double_scan); + } else if (result == 0) { + if (lfsck->ml_paused) { + ns->ln_status = LS_PAUSED; + } else { + ns->ln_status = LS_STOPPED; + cfs_list_del_init(&com->lc_link); + cfs_list_del_init(&com->lc_link_dir); + cfs_list_add_tail(&com->lc_link, &lfsck->ml_list_idle); + } + } else { + ns->ln_status = LS_FAILED; + cfs_list_del_init(&com->lc_link); + cfs_list_del_init(&com->lc_link_dir); + cfs_list_add_tail(&com->lc_link, &lfsck->ml_list_idle); + } + spin_unlock(&lfsck->ml_lock); + + ns->ln_run_time_phase1 += cfs_duration_sec(cfs_time_current() + + HALF_SEC - lfsck->ml_time_last_checkpoint); + ns->ln_time_last_checkpoint = cfs_time_current_sec(); + ns->ln_items_checked += com->lc_new_checked; + com->lc_new_checked = 0; + + rc = mdd_lfsck_namespace_store(env, com, false); + + up_write(&com->lc_sem); + return rc; +} + +/* XXX: to be implemented in other patch. */ +static int +mdd_lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + char *buf, int len) +{ + return 0; +} + +/* XXX: to be implemented in other patch. */ +static int mdd_lfsck_namespace_double_scan(const struct lu_env *env, + struct lfsck_component *com) +{ + struct md_lfsck *lfsck = com->lc_lfsck; + struct lfsck_bookmark *bk = &lfsck->ml_bookmark_ram; + struct lfsck_namespace *ns = + (struct lfsck_namespace *)com->lc_file_ram; + int rc; + + down_write(&com->lc_sem); + + ns->ln_time_last_checkpoint = cfs_time_current_sec(); + com->lc_new_checked = 0; + com->lc_journal = 0; + + ns->ln_status = LS_COMPLETED; + if (!(bk->lb_param & LPF_DRYRUN)) + ns->ln_flags &= + ~(LF_SCANNED_ONCE | LF_INCONSISTENT | LF_UPGRADE); + ns->ln_time_last_complete = ns->ln_time_last_checkpoint; + ns->ln_success_count++; + + spin_lock(&lfsck->ml_lock); + cfs_list_del_init(&com->lc_link); + cfs_list_add_tail(&com->lc_link, &lfsck->ml_list_idle); + spin_unlock(&lfsck->ml_lock); + + rc = mdd_lfsck_namespace_store(env, com, false); + + up_write(&com->lc_sem); + return rc; +} + +static struct lfsck_operations mdd_lfsck_namespace_ops = { + .lfsck_reset = mdd_lfsck_namespace_reset, + .lfsck_fail = mdd_lfsck_namespace_fail, + .lfsck_checkpoint = mdd_lfsck_namespace_checkpoint, + .lfsck_prep = mdd_lfsck_namespace_prep, + .lfsck_exec_oit = mdd_lfsck_namespace_exec_oit, + .lfsck_exec_dir = mdd_lfsck_namespace_exec_dir, + .lfsck_post = mdd_lfsck_namespace_post, + .lfsck_dump = mdd_lfsck_namespace_dump, + .lfsck_double_scan = mdd_lfsck_namespace_double_scan, +}; + +/* LFSCK component setup/cleanup functions */ + +static int mdd_lfsck_namespace_setup(const struct lu_env *env, + struct md_lfsck *lfsck) +{ + struct mdd_device *mdd = mdd_lfsck2mdd(lfsck); + struct lfsck_component *com; + struct lfsck_namespace *ns; + struct dt_object *obj; + int rc; + ENTRY; + + OBD_ALLOC_PTR(com); + if (com == NULL) + RETURN(-ENOMEM); + + CFS_INIT_LIST_HEAD(&com->lc_link); + CFS_INIT_LIST_HEAD(&com->lc_link_dir); + init_rwsem(&com->lc_sem); + atomic_set(&com->lc_ref, 1); + com->lc_lfsck = lfsck; + com->lc_type = LT_NAMESPACE; + com->lc_ops = &mdd_lfsck_namespace_ops; + com->lc_file_size = sizeof(struct lfsck_namespace); + OBD_ALLOC(com->lc_file_ram, com->lc_file_size); + if (com->lc_file_ram == NULL) + GOTO(out, rc = -ENOMEM); + + OBD_ALLOC(com->lc_file_disk, com->lc_file_size); + if (com->lc_file_disk == NULL) + GOTO(out, rc = -ENOMEM); + + obj = dt_store_open(env, mdd->mdd_bottom, "", lfsck_namespace_name, + &mdd_env_info(env)->mti_fid); + if (IS_ERR(obj)) + GOTO(out, rc = PTR_ERR(obj)); + + com->lc_obj = obj; + rc = obj->do_ops->do_index_try(env, obj, &dt_lfsck_features); + if (rc != 0) + GOTO(out, rc); + + rc = mdd_lfsck_namespace_load(env, com); + if (rc > 0) + rc = mdd_lfsck_namespace_reset(env, com, true); + else if (rc == -ENODATA) + rc = mdd_lfsck_namespace_init(env, com); + if (rc != 0) + GOTO(out, rc); + + ns = (struct lfsck_namespace *)com->lc_file_ram; + switch (ns->ln_status) { + case LS_INIT: + case LS_COMPLETED: + case LS_FAILED: + case LS_STOPPED: + cfs_list_add_tail(&com->lc_link, &lfsck->ml_list_idle); + break; + default: + CERROR("%s: unknown status: %u\n", + mdd_lfsck2name(lfsck), ns->ln_status); + /* fall through */ + case LS_SCANNING_PHASE1: + case LS_SCANNING_PHASE2: + /* No need to store the status to disk right now. + * If the system crashed before the status stored, + * it will be loaded back when next time. */ + ns->ln_status = LS_CRASHED; + /* fall through */ + case LS_PAUSED: + case LS_CRASHED: + cfs_list_add_tail(&com->lc_link, &lfsck->ml_list_scan); + cfs_list_add_tail(&com->lc_link_dir, &lfsck->ml_list_dir); + break; + } + + GOTO(out, rc = 0); + +out: + if (rc != 0) + mdd_lfsck_component_cleanup(env, com); + return rc; +} + /* helper functions for framework */ static int object_is_client_visible(const struct lu_env *env, @@ -1200,7 +1899,10 @@ int mdd_lfsck_setup(const struct lu_env *env, struct mdd_device *mdd) rc = mdd_lfsck_bookmark_load(env, lfsck); if (rc == -ENODATA) rc = mdd_lfsck_bookmark_init(env, lfsck); + if (rc != 0) + RETURN(rc); + rc = mdd_lfsck_namespace_setup(env, lfsck); /* XXX: LFSCK components initialization to be added here. */ RETURN(rc); diff --git a/lustre/obdclass/dt_object.c b/lustre/obdclass/dt_object.c index 8afaf2f..55b2be3 100644 --- a/lustre/obdclass/dt_object.c +++ b/lustre/obdclass/dt_object.c @@ -286,10 +286,9 @@ int dt_path_parser(const struct lu_env *env, return rc; } -static struct dt_object *dt_store_resolve(const struct lu_env *env, - struct dt_device *dt, - const char *path, - struct lu_fid *fid) +struct dt_object * +dt_store_resolve(const struct lu_env *env, struct dt_device *dt, + const char *path, struct lu_fid *fid) { struct dt_thread_info *info = dt_info(env); struct dt_find_hint *dfh = &info->dti_dfh; @@ -320,6 +319,7 @@ static struct dt_object *dt_store_resolve(const struct lu_env *env, } return obj; } +EXPORT_SYMBOL(dt_store_resolve); static struct dt_object *dt_reg_open(const struct lu_env *env, struct dt_device *dt, @@ -564,6 +564,17 @@ EXPORT_SYMBOL(dt_directory_features); const struct dt_index_features dt_otable_features; EXPORT_SYMBOL(dt_otable_features); +/* lfsck */ +const struct dt_index_features dt_lfsck_features = { + .dif_flags = DT_IND_UPDATE, + .dif_keysize_min = sizeof(struct lu_fid), + .dif_keysize_max = sizeof(struct lu_fid), + .dif_recsize_min = sizeof(__u8), + .dif_recsize_max = sizeof(__u8), + .dif_ptrsize = 4 +}; +EXPORT_SYMBOL(dt_lfsck_features); + /* accounting indexes */ const struct dt_index_features dt_acct_features = { .dif_flags = DT_IND_UPDATE, diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c index ed6868a..464c132 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c @@ -1136,6 +1136,10 @@ static const struct osd_lf_map osd_lf_maps[] = { { HEALTH_CHECK, { FID_SEQ_LOCAL_FILE, OFD_HEALTH_CHECK_OID, 0 }, OLF_SHOW_NAME, NULL, NULL }, + /* lfsck_namespace */ + { "lfsck_namespace", { FID_SEQ_LOCAL_FILE, LFSCK_NAMESPACE_OID, 0 }, 0, + NULL, NULL }, + /* OBJECTS, upgrade from old device */ { OBJECTS, { 0, 0, 0 }, OLF_SCAN_SUBITEMS, osd_ios_OBJECTS_scan, NULL },