From 0347ad57ee875b730c3ec0da203857a5c86fc394 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Fri, 10 Jan 2014 01:35:32 +0800 Subject: [PATCH 1/1] LU-1267 lfsck: framework (1) for MDT-OST consistency 1) New LFSCK component - lfsck_layout, its data structure, tracing file, lFSCK APIs, internal shared functions, and so on. 2) Extend the existing LFSCK: 2.1) new flag - LF_INCOMPLETE, for the case of some target (MDT/OST) not join the LFSCK or crashed during the LFSCK. 2.2) New status - LS_PARTIAL, corresponding to above LF_INCOMPLETE, if some target (MDT/OST) does not join the LFSCK processing or crashed during the LFSCK, when it finished, its status will be set as LS_PARTIAL. 3) Control the LFSCK speed by each component itself during the second-phase scanning. 4) Avoid lfsck engines to access freed lfsck_instance. 5) Some code cleanup. Signed-off-by: Fan Yong Change-Id: I6dc7bb881dc831f6c760be14aac2a066ad75ffec Reviewed-on: http://review.whamcloud.com/7146 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Reviewed-by: Oleg Drokin --- lustre/include/lustre_lfsck.h | 36 +++- lustre/lfsck/Makefile.in | 1 + lustre/lfsck/lfsck_bookmark.c | 29 +-- lustre/lfsck/lfsck_engine.c | 56 +++--- lustre/lfsck/lfsck_internal.h | 177 +++++++++++++--- lustre/lfsck/lfsck_layout.c | 443 +++++++++++++++++++++++++++++++++++++++++ lustre/lfsck/lfsck_lib.c | 310 ++++++++++++++++------------ lustre/lfsck/lfsck_namespace.c | 105 +++++----- 8 files changed, 900 insertions(+), 257 deletions(-) create mode 100644 lustre/lfsck/lfsck_layout.c diff --git a/lustre/include/lustre_lfsck.h b/lustre/include/lustre_lfsck.h index f75d507..a833018 100644 --- a/lustre/include/lustre_lfsck.h +++ b/lustre/include/lustre_lfsck.h @@ -38,6 +38,40 @@ #include #include +enum lfsck_status { + /* The lfsck file is new created, for new MDT, upgrading from old disk, + * or re-creating the lfsck file manually. */ + LS_INIT = 0, + + /* The first-step system scanning. */ + LS_SCANNING_PHASE1 = 1, + + /* The second-step system scanning. */ + LS_SCANNING_PHASE2 = 2, + + /* The LFSCK processing has completed for all objects. */ + LS_COMPLETED = 3, + + /* The LFSCK exited automatically for failure, will not auto restart. */ + LS_FAILED = 4, + + /* The LFSCK is stopped manually, will not auto restart. */ + LS_STOPPED = 5, + + /* LFSCK is paused automatically when umount, + * will be restarted automatically when remount. */ + LS_PAUSED = 6, + + /* System crashed during the LFSCK, + * will be restarted automatically after recovery. */ + LS_CRASHED = 7, + + /* Some OST/MDT failed during the LFSCK, or not join the LFSCK. */ + LS_PARTIAL = 8, + + LS_MAX +}; + struct lfsck_start_param { struct lfsck_start *lsp_start; struct ldlm_namespace *lsp_namespace; @@ -55,6 +89,6 @@ int lfsck_stop(const struct lu_env *env, struct dt_device *key, int lfsck_get_speed(struct dt_device *key, void *buf, int len); int lfsck_set_speed(struct dt_device *key, int val); -int lfsck_dump(struct dt_device *key, void *buf, int len, __u16 type); +int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type); #endif /* _LUSTRE_LFSCK_H */ diff --git a/lustre/lfsck/Makefile.in b/lustre/lfsck/Makefile.in index a703886..c2f5f32 100644 --- a/lustre/lfsck/Makefile.in +++ b/lustre/lfsck/Makefile.in @@ -1,4 +1,5 @@ MODULES := lfsck lfsck-objs := lfsck_lib.o lfsck_engine.o lfsck_bookmark.o lfsck_namespace.o +lfsck-objs += lfsck_layout.o @INCLUDE_RULES@ diff --git a/lustre/lfsck/lfsck_bookmark.c b/lustre/lfsck/lfsck_bookmark.c index d56d5fd..8275bf1 100644 --- a/lustre/lfsck/lfsck_bookmark.c +++ b/lustre/lfsck/lfsck_bookmark.c @@ -74,9 +74,9 @@ static int lfsck_bookmark_load(const struct lu_env *env, lfsck_bookmark_le_to_cpu(bm, &lfsck->li_bookmark_disk); if (bm->lb_magic != LFSCK_BOOKMARK_MAGIC) { - CWARN("%.16s: invalid lfsck_bookmark magic " - "0x%x != 0x%x\n", lfsck_lfsck2name(lfsck), - bm->lb_magic, LFSCK_BOOKMARK_MAGIC); + CWARN("%s: invalid lfsck_bookmark magic %#x != %#x\n", + lfsck_lfsck2name(lfsck), bm->lb_magic, + LFSCK_BOOKMARK_MAGIC); /* Process it as new lfsck_bookmark. */ rc = -ENODATA; } @@ -85,7 +85,7 @@ static int lfsck_bookmark_load(const struct lu_env *env, /* return -ENODATA for empty lfsck_bookmark. */ rc = -ENODATA; else - CERROR("%.16s: fail to load lfsck_bookmark, " + CERROR("%s: fail to load lfsck_bookmark: " "expected = %d, rc = %d\n", lfsck_lfsck2name(lfsck), len, rc); } @@ -106,22 +106,22 @@ int lfsck_bookmark_store(const struct lu_env *env, struct lfsck_instance *lfsck) handle = dt_trans_create(env, lfsck->li_bottom); if (IS_ERR(handle)) { rc = PTR_ERR(handle); - CERROR("%.16s: fail to create trans for storing " - "lfsck_bookmark: %d\n,", lfsck_lfsck2name(lfsck), rc); + CERROR("%s: fail to create trans for storing lfsck_bookmark: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); RETURN(rc); } rc = dt_declare_record_write(env, obj, len, 0, handle); if (rc != 0) { - CERROR("%.16s: fail to declare trans for storing " - "lfsck_bookmark: %d\n,", lfsck_lfsck2name(lfsck), rc); + CERROR("%s: fail to declare trans for storing lfsck_bookmark: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); GOTO(out, rc); } rc = dt_trans_start_local(env, lfsck->li_bottom, handle); if (rc != 0) { - CERROR("%.16s: fail to start trans for storing " - "lfsck_bookmark: %d\n,", lfsck_lfsck2name(lfsck), rc); + CERROR("%s: fail to start trans for storing lfsck_bookmark: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); GOTO(out, rc); } @@ -129,7 +129,7 @@ int lfsck_bookmark_store(const struct lu_env *env, struct lfsck_instance *lfsck) lfsck_buf_get(env, &lfsck->li_bookmark_disk, len), &pos, handle); if (rc != 0) - CERROR("%.16s: fail to store lfsck_bookmark, expected = %d, " + CERROR("%s: fail to store lfsck_bookmark: expected = %d, " "rc = %d\n", lfsck_lfsck2name(lfsck), len, rc); GOTO(out, rc); @@ -166,7 +166,12 @@ int lfsck_bookmark_setup(const struct lu_env *env, if (IS_ERR(root)) RETURN(PTR_ERR(root)); - dt_try_as_dir(env, root); + if (unlikely(!dt_try_as_dir(env, root))) { + lu_object_put(env, &root->do_lu); + + RETURN(-ENOTDIR); + } + obj = local_file_find_or_create(env, lfsck->li_los, root, lfsck_bookmark_name, S_IFREG | S_IRUGO | S_IWUSR); diff --git a/lustre/lfsck/lfsck_engine.c b/lustre/lfsck/lfsck_engine.c index e55c04f..7f8e3fc 100644 --- a/lustre/lfsck/lfsck_engine.c +++ b/lustre/lfsck/lfsck_engine.c @@ -361,38 +361,33 @@ checkpoint: int lfsck_master_engine(void *args) { - struct lu_env env; - struct lfsck_instance *lfsck = (struct lfsck_instance *)args; - struct ptlrpc_thread *thread = &lfsck->li_thread; - struct dt_object *oit_obj = lfsck->li_obj_oit; - const struct dt_it_ops *oit_iops = &oit_obj->do_index_ops->dio_it; - struct dt_it *oit_di; - int rc; + struct lfsck_thread_args *lta = args; + struct lu_env *env = <a->lta_env; + struct lfsck_instance *lfsck = lta->lta_lfsck; + struct ptlrpc_thread *thread = &lfsck->li_thread; + struct dt_object *oit_obj = lfsck->li_obj_oit; + const struct dt_it_ops *oit_iops = &oit_obj->do_index_ops->dio_it; + struct dt_it *oit_di; + int rc; ENTRY; - rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD); - if (rc != 0) { - CERROR("%s: LFSCK, fail to init env, rc = %d\n", - lfsck_lfsck2name(lfsck), rc); - GOTO(noenv, rc); - } - - oit_di = oit_iops->init(&env, oit_obj, lfsck->li_args_oit, BYPASS_CAPA); + oit_di = oit_iops->init(env, oit_obj, lfsck->li_args_oit, BYPASS_CAPA); if (IS_ERR(oit_di)) { rc = PTR_ERR(oit_di); - CERROR("%s: LFSCK, fail to init iteration, rc = %d\n", + CERROR("%s: LFSCK, fail to init iteration: rc = %d\n", lfsck_lfsck2name(lfsck), rc); - GOTO(fini_env, rc); + + GOTO(fini_args, rc); } spin_lock(&lfsck->li_lock); lfsck->li_di_oit = oit_di; spin_unlock(&lfsck->li_lock); - rc = lfsck_prep(&env, lfsck); + rc = lfsck_prep(env, lfsck); if (rc != 0) GOTO(fini_oit, rc); - CDEBUG(D_LFSCK, "LFSCK entry: oit_flags = 0x%x, dir_flags = 0x%x, " + CDEBUG(D_LFSCK, "LFSCK entry: oit_flags = %#x, dir_flags = %#x, " "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID ", pid = %d\n", lfsck->li_args_oit, lfsck->li_args_dir, lfsck->li_pos_current.lp_oit_cookie, @@ -407,11 +402,11 @@ int lfsck_master_engine(void *args) if (!cfs_list_empty(&lfsck->li_list_scan) || cfs_list_empty(&lfsck->li_list_double_scan)) - rc = lfsck_master_oit_engine(&env, lfsck); + rc = lfsck_master_oit_engine(env, lfsck); else rc = 1; - CDEBUG(D_LFSCK, "LFSCK exit: oit_flags = 0x%x, dir_flags = 0x%x, " + CDEBUG(D_LFSCK, "LFSCK exit: oit_flags = %#x, dir_flags = %#x, " "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID ", pid = %d, rc = %d\n", lfsck->li_args_oit, lfsck->li_args_dir, lfsck->li_pos_current.lp_oit_cookie, @@ -420,29 +415,28 @@ int lfsck_master_engine(void *args) current_pid(), rc); if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH)) - rc = lfsck_post(&env, lfsck, rc); + rc = lfsck_post(env, lfsck, rc); + if (lfsck->li_di_dir != NULL) - lfsck_close_dir(&env, lfsck); + lfsck_close_dir(env, lfsck); fini_oit: - lfsck_di_oit_put(&env, lfsck); - oit_iops->fini(&env, oit_di); + lfsck_di_oit_put(env, lfsck); + oit_iops->fini(env, oit_di); if (rc == 1) { if (!cfs_list_empty(&lfsck->li_list_double_scan)) - rc = lfsck_double_scan(&env, lfsck); + rc = lfsck_double_scan(env, lfsck); else rc = 0; } /* XXX: Purge the pinned objects in the future. */ -fini_env: - lu_env_fini(&env); - -noenv: +fini_args: spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPED); - wake_up_all(&thread->t_ctl_waitq); spin_unlock(&lfsck->li_lock); + wake_up_all(&thread->t_ctl_waitq); + lfsck_thread_args_fini(lta); return rc; } diff --git a/lustre/lfsck/lfsck_internal.h b/lustre/lfsck/lfsck_internal.h index b316731..3676341 100644 --- a/lustre/lfsck/lfsck_internal.h +++ b/lustre/lfsck/lfsck_internal.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -51,44 +52,19 @@ #define LFSCK_NAMEENTRY_REMOVED 2 /* The entry has been removed. */ #define LFSCK_NAMEENTRY_RECREATED 3 /* The entry has been recreated. */ -enum lfsck_status { - /* The lfsck file is new created, for new MDT, upgrading from old disk, - * or re-creating the lfsck file manually. */ - LS_INIT = 0, - - /* The first-step system scanning. */ - LS_SCANNING_PHASE1 = 1, - - /* The second-step system scanning. */ - LS_SCANNING_PHASE2 = 2, - - /* The LFSCK processing has completed for all objects. */ - LS_COMPLETED = 3, - - /* The LFSCK exited automatically for failure, will not auto restart. */ - LS_FAILED = 4, - - /* The LFSCK is stopped manually, will not auto restart. */ - LS_STOPPED = 5, - - /* LFSCK is paused automatically when umount, - * will be restarted automatically when remount. */ - LS_PAUSED = 6, - - /* System crashed during the LFSCK, - * will be restarted automatically after recovery. */ - LS_CRASHED = 7, -}; - enum lfsck_flags { /* Finish the first cycle scanning. */ - LF_SCANNED_ONCE = 0x00000001ULL, + LF_SCANNED_ONCE = 0x00000001ULL, /* There is some namespace inconsistency. */ - LF_INCONSISTENT = 0x00000002ULL, + LF_INCONSISTENT = 0x00000002ULL, /* The device is upgraded from 1.8 format. */ - LF_UPGRADE = 0x00000004ULL, + LF_UPGRADE = 0x00000004ULL, + + /* The server ever restarted during the LFSCK, and may miss to process + * some objects check/repair. */ + LF_INCOMPLETE = 0x00000008ULL, }; struct lfsck_position { @@ -196,6 +172,78 @@ struct lfsck_namespace { __u64 ln_reserved[2]; }; +enum lfsck_layout_inconsistency_type { + LLIT_NONE = 0, + LLIT_DANGLING = 1, + LLIT_UNMATCHED_PAIR = 2, + LLIT_MULTIPLE_REFERENCED = 3, + LLIT_ORPHAN = 4, + LLIT_INCONSISTENT_OWNER = 5, + LLIT_OTHERS = 6, + LLIT_MAX = LLIT_OTHERS +}; + +struct lfsck_layout { + /* Magic number to detect that this struct contains valid data. */ + __u32 ll_magic; + + /* See 'enum lfsck_status'. */ + __u32 ll_status; + + /* See 'enum lfsck_flags'. */ + __u32 ll_flags; + + /* How many completed LFSCK runs on the device. */ + __u32 ll_success_count; + + /* How long the LFSCK phase1 has run in seconds. */ + __u32 ll_run_time_phase1; + + /* How long the LFSCK phase2 has run in seconds. */ + __u32 ll_run_time_phase2; + + /* Time for the last LFSCK completed in seconds since epoch. */ + __u64 ll_time_last_complete; + + /* Time for the latest LFSCK ran in seconds since epoch. */ + __u64 ll_time_latest_start; + + /* Time for the last LFSCK checkpoint in seconds since epoch. */ + __u64 ll_time_last_checkpoint; + + /* Position for the latest LFSCK started from. */ + __u64 ll_pos_latest_start; + + /* Position for the last LFSCK checkpoint. */ + __u64 ll_pos_last_checkpoint; + + /* Position for the first should be updated object. */ + __u64 ll_pos_first_inconsistent; + + /* How many objects have been checked. */ + __u64 ll_objs_checked_phase1; + + /* How many objects failed to be processed. */ + __u64 ll_objs_failed_phase1; + + /* How many objects have been double scanned. */ + __u64 ll_objs_checked_phase2; + + /* How many objects failed to be processed during double scan. */ + __u64 ll_objs_failed_phase2; + + /* kinds of inconsistency have been repaired. + * ll_objs_repaired[type - 1] is the count for the given @type. */ + __u64 ll_objs_repaired[LLIT_MAX]; + + /* How many objects have been skipped because of related + * MDT(s)/OST(s) do not participate in the LFSCK */ + __u64 ll_objs_skipped; + + /* For further using. 256-bytes aligned now. */ + __u64 ll_reserved[12]; +}; + struct lfsck_component; struct lfsck_operations { @@ -252,10 +300,21 @@ struct lfsck_component { struct lfsck_operations *lc_ops; void *lc_file_ram; void *lc_file_disk; + + /* The time for last checkpoint, jiffies */ + cfs_time_t lc_time_last_checkpoint; + + /* The time for next checkpoint, jiffies */ + cfs_time_t lc_time_next_checkpoint; + __u32 lc_file_size; /* How many objects have been checked since last checkpoint. */ __u32 lc_new_checked; + + /* How many objects have been scanned since last sleep. */ + __u32 lc_new_scanned; + unsigned int lc_journal:1; __u16 lc_type; }; @@ -346,6 +405,12 @@ enum lfsck_linkea_flags { LLF_REPAIR_FAILED = 0x02, }; +struct lfsck_thread_args { + struct lu_env lta_env; + struct lfsck_instance *lta_lfsck; + struct lfsck_component *lta_com; +}; + struct lfsck_thread_info { struct lu_name lti_name; struct lu_buf lti_buf; @@ -366,8 +431,11 @@ struct lfsck_thread_info { }; /* lfsck_lib.c */ +const char *lfsck_status2names(enum lfsck_status status); void lfsck_component_cleanup(const struct lu_env *env, struct lfsck_component *com); +void lfsck_instance_cleanup(const struct lu_env *env, + struct lfsck_instance *lfsck); int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[], const char *prefix); int lfsck_time_dump(char **buf, int *len, __u64 time, const char *prefix); @@ -376,8 +444,12 @@ int lfsck_pos_dump(char **buf, int *len, struct lfsck_position *pos, void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck, struct lfsck_position *pos, bool init); void lfsck_control_speed(struct lfsck_instance *lfsck); +void lfsck_control_speed_by_self(struct lfsck_component *com); int lfsck_reset(const struct lu_env *env, struct lfsck_instance *lfsck, bool init); +struct lfsck_thread_args *lfsck_thread_args_init(struct lfsck_instance *lfsck, + struct lfsck_component *com); +void lfsck_thread_args_fini(struct lfsck_thread_args *lta); void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck, bool new_checked); int lfsck_checkpoint(const struct lu_env *env, struct lfsck_instance *lfsck); @@ -403,7 +475,9 @@ int lfsck_bookmark_setup(const struct lu_env *env, int lfsck_namespace_setup(const struct lu_env *env, struct lfsck_instance *lfsck); -extern const char *lfsck_status_names[]; +/* lfsck_layout.c */ +int lfsck_layout_setup(const struct lu_env *env, struct lfsck_instance *lfsck); + extern const char *lfsck_flags_names[]; extern const char *lfsck_param_names[]; extern struct lu_context_key lfsck_thread_key; @@ -551,6 +625,43 @@ static inline void lfsck_object_put(const struct lu_env *env, lu_object_put(env, &obj->do_lu); } +static inline struct lfsck_component * +lfsck_component_get(struct lfsck_component *com) +{ + atomic_inc(&com->lc_ref); + + return com; +} + +static inline void lfsck_component_put(const struct lu_env *env, + struct lfsck_component *com) +{ + if (atomic_dec_and_test(&com->lc_ref)) { + if (com->lc_obj != NULL) + lu_object_put_nocache(env, &com->lc_obj->do_lu); + if (com->lc_file_ram != NULL) + OBD_FREE(com->lc_file_ram, com->lc_file_size); + if (com->lc_file_disk != NULL) + OBD_FREE(com->lc_file_disk, com->lc_file_size); + OBD_FREE_PTR(com); + } +} + +static inline struct lfsck_instance * +lfsck_instance_get(struct lfsck_instance *lfsck) +{ + atomic_inc(&lfsck->li_ref); + + return lfsck; +} + +static inline void lfsck_instance_put(const struct lu_env *env, + struct lfsck_instance *lfsck) +{ + if (atomic_dec_and_test(&lfsck->li_ref)) + lfsck_instance_cleanup(env, lfsck); +} + static inline mdsno_t lfsck_dev_idx(struct dt_device *dev) { return dev->dd_lu_dev.ld_site->ld_seq_site->ss_node_id; diff --git a/lustre/lfsck/lfsck_layout.c b/lustre/lfsck/lfsck_layout.c new file mode 100644 index 0000000..402cca7 --- /dev/null +++ b/lustre/lfsck/lfsck_layout.c @@ -0,0 +1,443 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. A copy is + * included in the COPYING file that accompanied this code. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * GPL HEADER END + */ +/* + * Copyright (c) 2013, Intel Corporation. + */ +/* + * lustre/lfsck/lfsck_layout.c + * + * Author: Fan, Yong + */ + +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif +#define DEBUG_SUBSYSTEM S_LFSCK + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lfsck_internal.h" + +#define LFSCK_LAYOUT_MAGIC 0xB173AE14 + +static const char lfsck_layout_name[] = "lfsck_layout"; + +static void lfsck_layout_le_to_cpu(struct lfsck_layout *des, + const struct lfsck_layout *src) +{ + int i; + + des->ll_magic = le32_to_cpu(src->ll_magic); + des->ll_status = le32_to_cpu(src->ll_status); + des->ll_flags = le32_to_cpu(src->ll_flags); + des->ll_success_count = le32_to_cpu(src->ll_success_count); + des->ll_run_time_phase1 = le32_to_cpu(src->ll_run_time_phase1); + des->ll_run_time_phase2 = le32_to_cpu(src->ll_run_time_phase2); + des->ll_time_last_complete = le64_to_cpu(src->ll_time_last_complete); + des->ll_time_latest_start = le64_to_cpu(src->ll_time_latest_start); + des->ll_time_last_checkpoint = + le64_to_cpu(src->ll_time_last_checkpoint); + des->ll_pos_latest_start = le64_to_cpu(src->ll_pos_latest_start); + des->ll_pos_last_checkpoint = le64_to_cpu(src->ll_pos_last_checkpoint); + des->ll_pos_first_inconsistent = + le64_to_cpu(src->ll_pos_first_inconsistent); + des->ll_objs_checked_phase1 = le64_to_cpu(src->ll_objs_checked_phase1); + des->ll_objs_failed_phase1 = le64_to_cpu(src->ll_objs_failed_phase1); + des->ll_objs_checked_phase2 = le64_to_cpu(src->ll_objs_checked_phase2); + des->ll_objs_failed_phase2 = le64_to_cpu(src->ll_objs_failed_phase2); + for (i = 0; i < LLIT_MAX; i++) + des->ll_objs_repaired[i] = + le64_to_cpu(src->ll_objs_repaired[i]); + des->ll_objs_skipped = le64_to_cpu(src->ll_objs_skipped); +} + +static void lfsck_layout_cpu_to_le(struct lfsck_layout *des, + const struct lfsck_layout *src) +{ + int i; + + des->ll_magic = cpu_to_le32(src->ll_magic); + des->ll_status = cpu_to_le32(src->ll_status); + des->ll_flags = cpu_to_le32(src->ll_flags); + des->ll_success_count = cpu_to_le32(src->ll_success_count); + des->ll_run_time_phase1 = cpu_to_le32(src->ll_run_time_phase1); + des->ll_run_time_phase2 = cpu_to_le32(src->ll_run_time_phase2); + des->ll_time_last_complete = cpu_to_le64(src->ll_time_last_complete); + des->ll_time_latest_start = cpu_to_le64(src->ll_time_latest_start); + des->ll_time_last_checkpoint = + cpu_to_le64(src->ll_time_last_checkpoint); + des->ll_pos_latest_start = cpu_to_le64(src->ll_pos_latest_start); + des->ll_pos_last_checkpoint = cpu_to_le64(src->ll_pos_last_checkpoint); + des->ll_pos_first_inconsistent = + cpu_to_le64(src->ll_pos_first_inconsistent); + des->ll_objs_checked_phase1 = cpu_to_le64(src->ll_objs_checked_phase1); + des->ll_objs_failed_phase1 = cpu_to_le64(src->ll_objs_failed_phase1); + des->ll_objs_checked_phase2 = cpu_to_le64(src->ll_objs_checked_phase2); + des->ll_objs_failed_phase2 = cpu_to_le64(src->ll_objs_failed_phase2); + for (i = 0; i < LLIT_MAX; i++) + des->ll_objs_repaired[i] = + cpu_to_le64(src->ll_objs_repaired[i]); + des->ll_objs_skipped = cpu_to_le64(src->ll_objs_skipped); +} + +/** + * \retval +ve: the lfsck_layout is broken, the caller should reset it. + * \retval 0: succeed. + * \retval -ve: failed cases. + */ +static int lfsck_layout_load(const struct lu_env *env, + struct lfsck_component *com) +{ + struct lfsck_layout *lo = com->lc_file_ram; + const struct dt_body_operations *dbo = com->lc_obj->do_body_ops; + ssize_t size = com->lc_file_size; + loff_t pos = 0; + int rc; + + rc = dbo->dbo_read(env, com->lc_obj, + lfsck_buf_get(env, com->lc_file_disk, size), &pos, + BYPASS_CAPA); + if (rc == 0) { + return -ENOENT; + } else if (rc < 0) { + CWARN("%s: failed to load lfsck_layout: rc = %d\n", + lfsck_lfsck2name(com->lc_lfsck), rc); + return rc; + } else if (rc != size) { + CWARN("%s: crashed lfsck_layout, to be reset: rc = %d\n", + lfsck_lfsck2name(com->lc_lfsck), rc); + return 1; + } + + lfsck_layout_le_to_cpu(lo, com->lc_file_disk); + if (lo->ll_magic != LFSCK_LAYOUT_MAGIC) { + CWARN("%s: invalid lfsck_layout magic %#x != %#x, " + "to be reset\n", lfsck_lfsck2name(com->lc_lfsck), + lo->ll_magic, LFSCK_LAYOUT_MAGIC); + return 1; + } + + return 0; +} + +static int lfsck_layout_store(const struct lu_env *env, + struct lfsck_component *com) +{ + struct dt_object *obj = com->lc_obj; + struct lfsck_instance *lfsck = com->lc_lfsck; + struct lfsck_layout *lo = com->lc_file_disk; + struct thandle *handle; + ssize_t size = com->lc_file_size; + loff_t pos = 0; + int rc; + ENTRY; + + lfsck_layout_cpu_to_le(lo, com->lc_file_ram); + handle = dt_trans_create(env, lfsck->li_bottom); + if (IS_ERR(handle)) { + rc = PTR_ERR(handle); + CERROR("%s: fail to create trans for storing lfsck_layout: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); + RETURN(rc); + } + + rc = dt_declare_record_write(env, obj, size, pos, handle); + if (rc != 0) { + CERROR("%s: fail to declare trans for storing lfsck_layout(1): " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); + GOTO(out, rc); + } + + rc = dt_trans_start_local(env, lfsck->li_bottom, handle); + if (rc != 0) { + CERROR("%s: fail to start trans for storing lfsck_layout: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); + GOTO(out, rc); + } + + rc = dt_record_write(env, obj, lfsck_buf_get(env, lo, size), &pos, + handle); + if (rc != 0) + CERROR("%s: fail to store lfsck_layout(1): size = %d, " + "rc = %d\n", lfsck_lfsck2name(lfsck), (int)size, rc); + + GOTO(out, rc); + +out: + dt_trans_stop(env, lfsck->li_bottom, handle); + + return rc; +} + +static int lfsck_layout_init(const struct lu_env *env, + struct lfsck_component *com) +{ + struct lfsck_layout *lo = com->lc_file_ram; + int rc; + + memset(lo, 0, com->lc_file_size); + lo->ll_magic = LFSCK_LAYOUT_MAGIC; + lo->ll_status = LS_INIT; + down_write(&com->lc_sem); + rc = lfsck_layout_store(env, com); + up_write(&com->lc_sem); + + return rc; +} + +/* layout APIs */ +/* XXX: Some to be implemented in other patch(es). */ + +static int lfsck_layout_reset(const struct lu_env *env, + struct lfsck_component *com, bool init) +{ + struct lfsck_layout *lo = com->lc_file_ram; + int rc; + + down_write(&com->lc_sem); + if (init) { + memset(lo, 0, com->lc_file_size); + } else { + __u32 count = lo->ll_success_count; + __u64 last_time = lo->ll_time_last_complete; + + memset(lo, 0, com->lc_file_size); + lo->ll_success_count = count; + lo->ll_time_last_complete = last_time; + } + + lo->ll_magic = LFSCK_LAYOUT_MAGIC; + lo->ll_status = LS_INIT; + + rc = lfsck_layout_store(env, com); + up_write(&com->lc_sem); + + return rc; +} + +static void lfsck_layout_fail(const struct lu_env *env, + struct lfsck_component *com, bool new_checked) +{ +} + +static int lfsck_layout_checkpoint(const struct lu_env *env, + struct lfsck_component *com, bool init) +{ + return 0; +} + +static int lfsck_layout_master_prep(const struct lu_env *env, + struct lfsck_component *com) +{ + return 0; +} + +static int lfsck_layout_slave_prep(const struct lu_env *env, + struct lfsck_component *com) +{ + return 0; +} + +static int lfsck_layout_master_exec_oit(const struct lu_env *env, + struct lfsck_component *com, + struct dt_object *obj) +{ + return 0; +} + +static int lfsck_layout_slave_exec_oit(const struct lu_env *env, + struct lfsck_component *com, + struct dt_object *obj) +{ + return 0; +} + +static int lfsck_layout_exec_dir(const struct lu_env *env, + struct lfsck_component *com, + struct dt_object *obj, + struct lu_dirent *ent) +{ + return 0; +} + +static int lfsck_layout_master_post(const struct lu_env *env, + struct lfsck_component *com, + int result, bool init) +{ + return 0; +} + +static int lfsck_layout_slave_post(const struct lu_env *env, + struct lfsck_component *com, + int result, bool init) +{ + return 0; +} + +static int lfsck_layout_dump(const struct lu_env *env, + struct lfsck_component *com, char *buf, int len) +{ + return 0; +} + +static int lfsck_layout_master_double_scan(const struct lu_env *env, + struct lfsck_component *com) +{ + return 0; +} + +static int lfsck_layout_slave_double_scan(const struct lu_env *env, + struct lfsck_component *com) +{ + return 0; +} + +static struct lfsck_operations lfsck_layout_master_ops = { + .lfsck_reset = lfsck_layout_reset, + .lfsck_fail = lfsck_layout_fail, + .lfsck_checkpoint = lfsck_layout_checkpoint, + .lfsck_prep = lfsck_layout_master_prep, + .lfsck_exec_oit = lfsck_layout_master_exec_oit, + .lfsck_exec_dir = lfsck_layout_exec_dir, + .lfsck_post = lfsck_layout_master_post, + .lfsck_dump = lfsck_layout_dump, + .lfsck_double_scan = lfsck_layout_master_double_scan, +}; + +static struct lfsck_operations lfsck_layout_slave_ops = { + .lfsck_reset = lfsck_layout_reset, + .lfsck_fail = lfsck_layout_fail, + .lfsck_checkpoint = lfsck_layout_checkpoint, + .lfsck_prep = lfsck_layout_slave_prep, + .lfsck_exec_oit = lfsck_layout_slave_exec_oit, + .lfsck_exec_dir = lfsck_layout_exec_dir, + .lfsck_post = lfsck_layout_slave_post, + .lfsck_dump = lfsck_layout_dump, + .lfsck_double_scan = lfsck_layout_slave_double_scan, +}; + +int lfsck_layout_setup(const struct lu_env *env, struct lfsck_instance *lfsck) +{ + struct lfsck_component *com; + struct lfsck_layout *lo; + struct dt_object *root = NULL; + struct dt_object *obj; + int rc; + ENTRY; + + OBD_ALLOC_PTR(com); + if (com == NULL) + RETURN(-ENOMEM); + + INIT_LIST_HEAD(&com->lc_link); + INIT_LIST_HEAD(&com->lc_link_dir); + init_rwsem(&com->lc_sem); + atomic_set(&com->lc_ref, 1); + com->lc_lfsck = lfsck; + com->lc_type = LT_LAYOUT; + if (lfsck->li_master) + com->lc_ops = &lfsck_layout_master_ops; + else + com->lc_ops = &lfsck_layout_slave_ops; + com->lc_file_size = sizeof(*lo); + 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); + + root = dt_locate(env, lfsck->li_bottom, &lfsck->li_local_root_fid); + if (IS_ERR(root)) + GOTO(out, rc = PTR_ERR(root)); + + if (unlikely(!dt_try_as_dir(env, root))) + GOTO(out, rc = -ENOTDIR); + + obj = local_file_find_or_create(env, lfsck->li_los, root, + lfsck_layout_name, + S_IFREG | S_IRUGO | S_IWUSR); + if (IS_ERR(obj)) + GOTO(out, rc = PTR_ERR(obj)); + + com->lc_obj = obj; + rc = lfsck_layout_load(env, com); + if (rc > 0) + rc = lfsck_layout_reset(env, com, true); + else if (rc == -ENOENT) + rc = lfsck_layout_init(env, com); + + if (rc != 0) + GOTO(out, rc); + + lo = com->lc_file_ram; + switch (lo->ll_status) { + case LS_INIT: + case LS_COMPLETED: + case LS_FAILED: + case LS_STOPPED: + case LS_PARTIAL: + spin_lock(&lfsck->li_lock); + list_add_tail(&com->lc_link, &lfsck->li_list_idle); + spin_unlock(&lfsck->li_lock); + break; + default: + CERROR("%s: unknown lfsck_layout status: rc = %u\n", + lfsck_lfsck2name(lfsck), lo->ll_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. */ + lo->ll_status = LS_CRASHED; + lo->ll_flags |= LF_INCOMPLETE; + /* fall through */ + case LS_PAUSED: + case LS_CRASHED: + spin_lock(&lfsck->li_lock); + list_add_tail(&com->lc_link, &lfsck->li_list_scan); + spin_unlock(&lfsck->li_lock); + break; + } + + GOTO(out, rc = 0); + +out: + if (root != NULL && !IS_ERR(root)) + lu_object_put(env, &root->do_lu); + + if (rc != 0) + lfsck_component_cleanup(env, com); + + return rc; +} diff --git a/lustre/lfsck/lfsck_lib.c b/lustre/lfsck/lfsck_lib.c index a4c963c..37efbcc 100644 --- a/lustre/lfsck/lfsck_lib.c +++ b/lustre/lfsck/lfsck_lib.c @@ -60,48 +60,39 @@ LU_KEY_INIT_GENERIC(lfsck); static CFS_LIST_HEAD(lfsck_instance_list); static DEFINE_SPINLOCK(lfsck_instance_lock); -const char *lfsck_status_names[] = { - "init", - "scanning-phase1", - "scanning-phase2", - "completed", - "failed", - "stopped", - "paused", - "crashed", - NULL +static const char *lfsck_status_names[] = { + [LS_INIT] = "init", + [LS_SCANNING_PHASE1] = "scanning-phase1", + [LS_SCANNING_PHASE2] = "scanning-phase2", + [LS_COMPLETED] = "completed", + [LS_FAILED] = "failed", + [LS_STOPPED] = "stopped", + [LS_PAUSED] = "paused", + [LS_CRASHED] = "crashed", + [LS_PARTIAL] = "partial" }; const char *lfsck_flags_names[] = { "scanned-once", "inconsistent", "upgrade", + "incomplete", NULL }; const char *lfsck_param_names[] = { + NULL, "failout", "dryrun", NULL }; -static inline void lfsck_component_get(struct lfsck_component *com) +const char *lfsck_status2names(enum lfsck_status status) { - atomic_inc(&com->lc_ref); -} + if (unlikely(status < 0 || status >= LS_MAX)) + return "unknown"; -static inline void lfsck_component_put(const struct lu_env *env, - struct lfsck_component *com) -{ - if (atomic_dec_and_test(&com->lc_ref)) { - if (com->lc_obj != NULL) - lu_object_put_nocache(env, &com->lc_obj->do_lu); - if (com->lc_file_ram != NULL) - OBD_FREE(com->lc_file_ram, com->lc_file_size); - if (com->lc_file_disk != NULL) - OBD_FREE(com->lc_file_disk, com->lc_file_size); - OBD_FREE_PTR(com); - } + return lfsck_status_names[status]; } static inline struct lfsck_component * @@ -151,8 +142,8 @@ void lfsck_component_cleanup(const struct lu_env *env, lfsck_component_put(env, com); } -static void lfsck_instance_cleanup(const struct lu_env *env, - struct lfsck_instance *lfsck) +void lfsck_instance_cleanup(const struct lu_env *env, + struct lfsck_instance *lfsck) { struct ptlrpc_thread *thread = &lfsck->li_thread; struct lfsck_component *com; @@ -204,18 +195,6 @@ static void lfsck_instance_cleanup(const struct lu_env *env, OBD_FREE_PTR(lfsck); } -static inline void lfsck_instance_get(struct lfsck_instance *lfsck) -{ - atomic_inc(&lfsck->li_ref); -} - -static inline void lfsck_instance_put(const struct lu_env *env, - struct lfsck_instance *lfsck) -{ - if (atomic_dec_and_test(&lfsck->li_ref)) - lfsck_instance_cleanup(env, lfsck); -} - static inline struct lfsck_instance *lfsck_instance_find(struct dt_device *key, bool ref, bool unlink) { @@ -270,13 +249,15 @@ int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[], for (i = 0, flag = 1; bits != 0; i++, flag = 1 << i) { if (flag & bits) { bits &= ~flag; - rc = snprintf(*buf, *len, "%s%c", names[i], - bits != 0 ? ',' : '\n'); - if (rc <= 0) - return -ENOSPC; - - *buf += rc; - *len -= rc; + if (names[i] != NULL) { + rc = snprintf(*buf, *len, "%s%c", names[i], + bits != 0 ? ',' : '\n'); + if (rc <= 0) + return -ENOSPC; + + *buf += rc; + *len -= rc; + } } } return save - *len; @@ -350,7 +331,7 @@ void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck, fid_zero(&pos->lp_dir_parent); pos->lp_dir_cookie = 0; } else { - pos->lp_dir_parent = *lu_object_fid(&dto->do_lu); + pos->lp_dir_parent = *lfsck_dto2fid(dto); } } else { fid_zero(&pos->lp_dir_parent); @@ -382,20 +363,31 @@ void lfsck_control_speed(struct lfsck_instance *lfsck) if (lfsck->li_sleep_jif > 0 && lfsck->li_new_scanned >= lfsck->li_sleep_rate) { - spin_lock(&lfsck->li_lock); - if (likely(lfsck->li_sleep_jif > 0 && - lfsck->li_new_scanned >= lfsck->li_sleep_rate)) { - lwi = LWI_TIMEOUT_INTR(lfsck->li_sleep_jif, NULL, - LWI_ON_SIGNAL_NOOP, NULL); - spin_unlock(&lfsck->li_lock); - - l_wait_event(thread->t_ctl_waitq, - !thread_is_running(thread), - &lwi); - lfsck->li_new_scanned = 0; - } else { - spin_unlock(&lfsck->li_lock); - } + lwi = LWI_TIMEOUT_INTR(lfsck->li_sleep_jif, NULL, + LWI_ON_SIGNAL_NOOP, NULL); + + l_wait_event(thread->t_ctl_waitq, + !thread_is_running(thread), + &lwi); + lfsck->li_new_scanned = 0; + } +} + +void lfsck_control_speed_by_self(struct lfsck_component *com) +{ + struct lfsck_instance *lfsck = com->lc_lfsck; + struct ptlrpc_thread *thread = &lfsck->li_thread; + struct l_wait_info lwi; + + if (lfsck->li_sleep_jif > 0 && + com->lc_new_scanned >= lfsck->li_sleep_rate) { + lwi = LWI_TIMEOUT_INTR(lfsck->li_sleep_jif, NULL, + LWI_ON_SIGNAL_NOOP, NULL); + + l_wait_event(thread->t_ctl_waitq, + !thread_is_running(thread), + &lwi); + com->lc_new_scanned = 0; } } @@ -496,6 +488,38 @@ static int lfsck_needs_scan_dir(const struct lu_env *env, return 0; } +struct lfsck_thread_args *lfsck_thread_args_init(struct lfsck_instance *lfsck, + struct lfsck_component *com) +{ + struct lfsck_thread_args *lta; + int rc; + + OBD_ALLOC_PTR(lta); + if (lta == NULL) + return ERR_PTR(-ENOMEM); + + rc = lu_env_init(<a->lta_env, LCT_MD_THREAD | LCT_DT_THREAD); + if (rc != 0) { + OBD_FREE_PTR(lta); + return ERR_PTR(rc); + } + + lta->lta_lfsck = lfsck_instance_get(lfsck); + if (com != NULL) + lta->lta_com = lfsck_component_get(com); + + return lta; +} + +void lfsck_thread_args_fini(struct lfsck_thread_args *lta) +{ + if (lta->lta_com != NULL) + lfsck_component_put(<a->lta_env, lta->lta_com); + lfsck_instance_put(<a->lta_env, lta->lta_lfsck); + lu_env_fini(<a->lta_env); + OBD_FREE_PTR(lta); +} + /* LFSCK wrap functions */ void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck, @@ -511,7 +535,8 @@ void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck, int lfsck_checkpoint(const struct lu_env *env, struct lfsck_instance *lfsck) { struct lfsck_component *com; - int rc; + int rc = 0; + int rc1 = 0; if (likely(cfs_time_beforeq(cfs_time_current(), lfsck->li_time_next_checkpoint))) @@ -521,13 +546,13 @@ int lfsck_checkpoint(const struct lu_env *env, struct lfsck_instance *lfsck) cfs_list_for_each_entry(com, &lfsck->li_list_scan, lc_link) { rc = com->lc_ops->lfsck_checkpoint(env, com, false); if (rc != 0) - return rc;; + rc1 = rc; } lfsck->li_time_last_checkpoint = cfs_time_current(); lfsck->li_time_next_checkpoint = lfsck->li_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); - return 0; + return rc1 != 0 ? rc1 : rc; } int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck) @@ -553,7 +578,7 @@ int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck) rc = com->lc_ops->lfsck_prep(env, com); if (rc != 0) - RETURN(rc); + GOTO(out, rc); if ((pos == NULL) || (!lfsck_pos_is_zero(&com->lc_pos_start) && @@ -725,18 +750,21 @@ int lfsck_post(const struct lu_env *env, struct lfsck_instance *lfsck, { struct lfsck_component *com; struct lfsck_component *next; - int rc; + int rc = 0; + int rc1 = 0; lfsck_pos_fill(env, lfsck, &lfsck->li_pos_current, false); cfs_list_for_each_entry_safe(com, next, &lfsck->li_list_scan, lc_link) { rc = com->lc_ops->lfsck_post(env, com, result, false); if (rc != 0) - return rc; + rc1 = rc; } lfsck->li_time_last_checkpoint = cfs_time_current(); lfsck->li_time_next_checkpoint = lfsck->li_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); + + /* Ignore some component post failure to make other can go ahead. */ return result; } @@ -767,22 +795,22 @@ int lfsck_get_speed(struct dt_device *key, void *buf, int len) int rc; ENTRY; - lfsck = lfsck_instance_find(key, true, false); - if (unlikely(lfsck == NULL)) - RETURN(-ENODEV); - rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD); if (rc != 0) - GOTO(out, rc); + RETURN(rc); - rc = snprintf(buf, len, "%u\n", lfsck->li_bookmark_ram.lb_speed_limit); - lu_env_fini(&env); + lfsck = lfsck_instance_find(key, true, false); + if (likely(lfsck != NULL)) { + rc = snprintf(buf, len, "%u\n", + lfsck->li_bookmark_ram.lb_speed_limit); + lfsck_instance_put(&env, lfsck); + } else { + rc = -ENODEV; + } - GOTO(out, rc); + lu_env_fini(&env); -out: - lfsck_instance_put(&env, lfsck); - return rc; + RETURN(rc); } EXPORT_SYMBOL(lfsck_get_speed); @@ -793,74 +821,75 @@ int lfsck_set_speed(struct dt_device *key, int val) int rc; ENTRY; - lfsck = lfsck_instance_find(key, true, false); - if (unlikely(lfsck == NULL)) - RETURN(-ENODEV); - rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD); if (rc != 0) - GOTO(out, rc); + RETURN(rc); - mutex_lock(&lfsck->li_mutex); - __lfsck_set_speed(lfsck, val); - rc = lfsck_bookmark_store(&env, lfsck); - mutex_unlock(&lfsck->li_mutex); - lu_env_fini(&env); + lfsck = lfsck_instance_find(key, true, false); + if (likely(lfsck != NULL)) { + mutex_lock(&lfsck->li_mutex); + __lfsck_set_speed(lfsck, val); + rc = lfsck_bookmark_store(&env, lfsck); + mutex_unlock(&lfsck->li_mutex); + lfsck_instance_put(&env, lfsck); + } else { + rc = -ENODEV; + } - GOTO(out, rc); + lu_env_fini(&env); -out: - lfsck_instance_put(&env, lfsck); - return rc; + RETURN(rc); } EXPORT_SYMBOL(lfsck_set_speed); -int lfsck_dump(struct dt_device *key, void *buf, int len, __u16 type) +int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type) { struct lu_env env; struct lfsck_instance *lfsck; - struct lfsck_component *com = NULL; + struct lfsck_component *com; int rc; ENTRY; - lfsck = lfsck_instance_find(key, true, false); - if (unlikely(lfsck == NULL)) - RETURN(-ENODEV); - - com = lfsck_component_find(lfsck, type); - if (com == NULL) - GOTO(out, rc = -ENOTSUPP); - rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD); if (rc != 0) - GOTO(out, rc); + RETURN(rc); - rc = com->lc_ops->lfsck_dump(&env, com, buf, len); - lu_env_fini(&env); + lfsck = lfsck_instance_find(key, true, false); + if (likely(lfsck != NULL)) { + com = lfsck_component_find(lfsck, type); + if (likely(com != NULL)) { + rc = com->lc_ops->lfsck_dump(&env, com, buf, len); + lfsck_component_put(&env, com); + } else { + rc = -ENOTSUPP; + } - GOTO(out, rc); + lfsck_instance_put(&env, lfsck); + } else { + rc = -ENODEV; + } -out: - if (com != NULL) - lfsck_component_put(&env, com); - lfsck_instance_put(&env, lfsck); - return rc; + lu_env_fini(&env); + + RETURN(rc); } EXPORT_SYMBOL(lfsck_dump); int lfsck_start(const struct lu_env *env, struct dt_device *key, struct lfsck_start_param *lsp) { - struct lfsck_start *start = lsp->lsp_start; - struct lfsck_instance *lfsck; - struct lfsck_bookmark *bk; - struct ptlrpc_thread *thread; - struct lfsck_component *com; - struct l_wait_info lwi = { 0 }; - bool dirty = false; - long rc = 0; - __u16 valid = 0; - __u16 flags = 0; + struct lfsck_start *start = lsp->lsp_start; + struct lfsck_instance *lfsck; + struct lfsck_bookmark *bk; + struct ptlrpc_thread *thread; + struct lfsck_component *com; + struct l_wait_info lwi = { 0 }; + struct lfsck_thread_args *lta; + bool dirty = false; + long rc = 0; + __u16 valid = 0; + __u16 flags = 0; + __u16 type = 1; ENTRY; lfsck = lfsck_instance_find(key, true, false); @@ -878,10 +907,27 @@ int lfsck_start(const struct lu_env *env, struct dt_device *key, mutex_lock(&lfsck->li_mutex); spin_lock(&lfsck->li_lock); if (!thread_is_init(thread) && !thread_is_stopped(thread)) { + rc = -EALREADY; + while (start->ls_active != 0) { + if (type & start->ls_active) { + com = __lfsck_component_find(lfsck, type, + &lfsck->li_list_scan); + if (com == NULL) + com = __lfsck_component_find(lfsck, + type, + &lfsck->li_list_double_scan); + if (com == NULL) { + rc = -EBUSY; + break; + } else { + start->ls_active &= ~type; + } + } + type <<= 1; + } spin_unlock(&lfsck->li_lock); - GOTO(out, rc = -EALREADY); + GOTO(out, rc); } - spin_unlock(&lfsck->li_lock); lfsck->li_namespace = lsp->lsp_namespace; @@ -944,7 +990,6 @@ int lfsck_start(const struct lu_env *env, struct dt_device *key, if (start->ls_active != 0) { struct lfsck_component *next; - __u16 type = 1; if (start->ls_active == LFSCK_TYPES_ALL) start->ls_active = LFSCK_TYPES_SUPPORTED; @@ -1009,10 +1054,15 @@ trigger: lfsck->li_args_oit = (flags << DT_OTABLE_IT_FLAGS_SHIFT) | valid; thread_set_flags(thread, 0); - rc = PTR_ERR(kthread_run(lfsck_master_engine, lfsck, "lfsck")); + lta = lfsck_thread_args_init(lfsck, NULL); + if (IS_ERR(lta)) + GOTO(out, rc = PTR_ERR(lta)); + + rc = PTR_ERR(kthread_run(lfsck_master_engine, lta, "lfsck")); if (IS_ERR_VALUE(rc)) { - CERROR("%s: cannot start LFSCK thread, rc = %ld\n", + CERROR("%s: cannot start LFSCK thread: rc = %ld\n", lfsck_lfsck2name(lfsck), rc); + lfsck_thread_args_fini(lta); } else { rc = 0; l_wait_event(thread->t_ctl_waitq, @@ -1113,8 +1163,10 @@ int lfsck_register(const struct lu_env *env, struct dt_device *key, if (IS_ERR(root)) GOTO(out, rc = PTR_ERR(root)); + if (unlikely(!dt_try_as_dir(env, root))) + GOTO(out, rc = -ENOTDIR); + lfsck->li_local_root_fid = *fid; - dt_try_as_dir(env, root); if (master) { lfsck->li_master = 1; if (lfsck_dev_idx(lfsck->li_bottom) == 0) { @@ -1152,6 +1204,10 @@ int lfsck_register(const struct lu_env *env, struct dt_device *key, GOTO(out, rc); } + rc = lfsck_layout_setup(env, lfsck); + if (rc < 0) + GOTO(out, rc); + /* XXX: more LFSCK components initialization to be added here. */ add: diff --git a/lustre/lfsck/lfsck_namespace.c b/lustre/lfsck/lfsck_namespace.c index 3cc043d..d1ba149 100644 --- a/lustre/lfsck/lfsck_namespace.c +++ b/lustre/lfsck/lfsck_namespace.c @@ -134,16 +134,15 @@ static int lfsck_namespace_load(const struct lu_env *env, lfsck_namespace_le_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", - lfsck_lfsck2name(com->lc_lfsck), - ns->ln_magic, LFSCK_NAMESPACE_MAGIC); + CWARN("%s: invalid lfsck_namespace magic %#x != %#x\n", + lfsck_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, " + CERROR("%s: fail to load lfsck_namespace: expected = %d, " "rc = %d\n", lfsck_lfsck2name(com->lc_lfsck), len, rc); if (rc >= 0) rc = 1; @@ -166,8 +165,8 @@ static int lfsck_namespace_store(const struct lu_env *env, handle = dt_trans_create(env, lfsck->li_bottom); if (IS_ERR(handle)) { rc = PTR_ERR(handle); - CERROR("%.16s: fail to create trans for storing " - "lfsck_namespace: %d\n,", lfsck_lfsck2name(lfsck), rc); + CERROR("%s: fail to create trans for storing lfsck_namespace: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); RETURN(rc); } @@ -175,15 +174,15 @@ static int lfsck_namespace_store(const struct lu_env *env, lfsck_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,", lfsck_lfsck2name(lfsck), rc); + CERROR("%s: fail to declare trans for storing lfsck_namespace: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); GOTO(out, rc); } rc = dt_trans_start_local(env, lfsck->li_bottom, handle); if (rc != 0) { - CERROR("%.16s: fail to start trans for storing " - "lfsck_namespace: %d\n,", lfsck_lfsck2name(lfsck), rc); + CERROR("%s: fail to start trans for storing lfsck_namespace: " + "rc = %d\n", lfsck_lfsck2name(lfsck), rc); GOTO(out, rc); } @@ -193,7 +192,7 @@ static int lfsck_namespace_store(const struct lu_env *env, init ? LU_XATTR_CREATE : LU_XATTR_REPLACE, handle, BYPASS_CAPA); if (rc != 0) - CERROR("%.16s: fail to store lfsck_namespace, len = %d, " + CERROR("%s: fail to store lfsck_namespace: len = %d, " "rc = %d\n", lfsck_lfsck2name(lfsck), len, rc); GOTO(out, rc); @@ -206,7 +205,7 @@ out: static int lfsck_namespace_init(const struct lu_env *env, struct lfsck_component *com) { - struct lfsck_namespace *ns = (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; int rc; memset(ns, 0, sizeof(*ns)); @@ -316,7 +315,7 @@ static int lfsck_namespace_update(const struct lu_env *env, rc = dt_delete(env, obj, (const struct dt_key *)key, handle, BYPASS_CAPA); if (rc != 0) { - CERROR("%s: fail to insert "DFID", rc = %d\n", + CERROR("%s: fail to insert "DFID": rc = %d\n", lfsck_lfsck2name(com->lc_lfsck), PFID(fid), rc); GOTO(out, rc); } @@ -473,8 +472,7 @@ static int lfsck_namespace_double_scan_one(const struct lu_env *env, struct lu_fid *cfid = &info->lti_fid2; struct lfsck_instance *lfsck = com->lc_lfsck; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; struct linkea_data ldata = { 0 }; struct thandle *handle = NULL; bool locked = false; @@ -625,7 +623,7 @@ stop: if (rc == 0 && !lfsck_is_dead_obj(child) && ldata.ld_leh != NULL && ldata.ld_leh->leh_reccount != la->la_nlink) - CWARN("%.16s: the object "DFID" linkEA entry count %u " + CWARN("%s: the object "DFID" linkEA entry count %u " "may not match its hardlink count %u\n", lfsck_lfsck2name(lfsck), PFID(cfid), ldata.ld_leh->leh_reccount, la->la_nlink); @@ -650,8 +648,7 @@ static int lfsck_namespace_reset(const struct lu_env *env, struct lfsck_component *com, bool init) { struct lfsck_instance *lfsck = com->lc_lfsck; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; struct dt_object *root; struct dt_object *dto; int rc; @@ -661,7 +658,10 @@ static int lfsck_namespace_reset(const struct lu_env *env, if (IS_ERR(root)) RETURN(PTR_ERR(root)); - dt_try_as_dir(env, root); + if (unlikely(!dt_try_as_dir(env, root))) { + lu_object_put(env, &root->do_lu); + RETURN(-ENOTDIR); + } down_write(&com->lc_sem); if (init) { @@ -710,7 +710,7 @@ static void lfsck_namespace_fail(const struct lu_env *env, struct lfsck_component *com, bool new_checked) { - struct lfsck_namespace *ns = (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; down_write(&com->lc_sem); if (new_checked) @@ -726,8 +726,7 @@ static int lfsck_namespace_checkpoint(const struct lu_env *env, struct lfsck_component *com, bool init) { struct lfsck_instance *lfsck = com->lc_lfsck; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; int rc; if (com->lc_new_checked == 0 && !init) @@ -756,8 +755,7 @@ static int lfsck_namespace_prep(const struct lu_env *env, struct lfsck_component *com) { struct lfsck_instance *lfsck = com->lc_lfsck; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; struct lfsck_position *pos = &com->lc_pos_start; if (ns->ln_status == LS_COMPLETED) { @@ -843,11 +841,9 @@ static int lfsck_namespace_exec_dir(const struct lu_env *env, struct lu_attr *la = &info->lti_la; struct lfsck_instance *lfsck = com->lc_lfsck; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; struct linkea_data ldata = { 0 }; - const struct lu_fid *pfid = - lu_object_fid(&lfsck->li_obj_dir->do_lu); + const struct lu_fid *pfid = lfsck_dto2fid(lfsck->li_obj_dir); const struct lu_fid *cfid = lfsck_dto2fid(obj); const struct lu_name *cname; struct thandle *handle = NULL; @@ -1043,8 +1039,7 @@ static int lfsck_namespace_post(const struct lu_env *env, int result, bool init) { struct lfsck_instance *lfsck = com->lc_lfsck; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; int rc; down_write(&com->lc_sem); @@ -1096,8 +1091,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, { struct lfsck_instance *lfsck = com->lc_lfsck; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; int save = len; int ret = -ENOSPC; int rc; @@ -1105,12 +1099,12 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, down_read(&com->lc_sem); rc = snprintf(buf, len, "name: lfsck_namespace\n" - "magic: 0x%x\n" + "magic: %#x\n" "version: %d\n" "status: %s\n", ns->ln_magic, bk->lb_version, - lfsck_status_names[ns->ln_status]); + lfsck_status2names(ns->ln_status)); if (rc <= 0) goto out; @@ -1230,7 +1224,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, pos.lp_dir_cookie = 0; } else { pos.lp_dir_parent = - *lu_object_fid(&lfsck->li_obj_dir->do_lu); + *lfsck_dto2fid(lfsck->li_obj_dir); } } else { fid_zero(&pos.lp_dir_parent); @@ -1359,8 +1353,7 @@ static int lfsck_namespace_double_scan(const struct lu_env *env, struct lfsck_instance *lfsck = com->lc_lfsck; struct ptlrpc_thread *thread = &lfsck->li_thread; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; + struct lfsck_namespace *ns = com->lc_file_ram; struct dt_object *obj = com->lc_obj; const struct dt_it_ops *iops = &obj->do_index_ops->dio_it; struct dt_object *target; @@ -1371,9 +1364,10 @@ static int lfsck_namespace_double_scan(const struct lu_env *env, __u8 flags = 0; ENTRY; - lfsck->li_new_scanned = 0; - lfsck->li_time_last_checkpoint = cfs_time_current(); - lfsck->li_time_next_checkpoint = lfsck->li_time_last_checkpoint + + com->lc_new_checked = 0; + com->lc_new_scanned = 0; + com->lc_time_last_checkpoint = cfs_time_current(); + com->lc_time_next_checkpoint = com->lc_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); di = iops->init(env, obj, 0, BYPASS_CAPA); @@ -1429,8 +1423,8 @@ static int lfsck_namespace_double_scan(const struct lu_env *env, lfsck_object_put(env, target); checkpoint: - lfsck->li_new_scanned++; com->lc_new_checked++; + com->lc_new_scanned++; ns->ln_fid_latest_scanned_phase2 = fid; if (rc > 0) ns->ln_objs_repaired_phase2++; @@ -1448,13 +1442,13 @@ checkpoint: if (rc < 0 && bk->lb_param & LPF_FAILOUT) GOTO(put, rc); - if (unlikely(cfs_time_beforeq(lfsck->li_time_next_checkpoint, + if (unlikely(cfs_time_beforeq(com->lc_time_next_checkpoint, cfs_time_current())) && com->lc_new_checked != 0) { 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; @@ -1463,13 +1457,13 @@ checkpoint: if (rc != 0) GOTO(put, rc); - lfsck->li_time_last_checkpoint = cfs_time_current(); - lfsck->li_time_next_checkpoint = - lfsck->li_time_last_checkpoint + + com->lc_time_last_checkpoint = cfs_time_current(); + com->lc_time_next_checkpoint = + com->lc_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); } - lfsck_control_speed(lfsck); + lfsck_control_speed_by_self(com); if (unlikely(!thread_is_running(thread))) GOTO(put, rc = 0); @@ -1495,8 +1489,7 @@ fini: 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_flags &= ~(LF_SCANNED_ONCE | LF_INCONSISTENT); ns->ln_time_last_complete = ns->ln_time_last_checkpoint; ns->ln_success_count++; } else if (rc == 0) { @@ -1569,7 +1562,9 @@ int lfsck_namespace_setup(const struct lu_env *env, if (IS_ERR(root)) GOTO(out, rc = PTR_ERR(root)); - dt_try_as_dir(env, root); + if (unlikely(!dt_try_as_dir(env, root))) + GOTO(out, rc = -ENOTDIR); + obj = local_index_find_or_create(env, lfsck->li_los, root, lfsck_namespace_name, S_IFREG | S_IRUGO | S_IWUSR, @@ -1590,16 +1585,18 @@ int lfsck_namespace_setup(const struct lu_env *env, if (rc != 0) GOTO(out, rc); - ns = (struct lfsck_namespace *)com->lc_file_ram; + ns = com->lc_file_ram; switch (ns->ln_status) { case LS_INIT: case LS_COMPLETED: case LS_FAILED: case LS_STOPPED: + spin_lock(&lfsck->li_lock); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle); + spin_unlock(&lfsck->li_lock); break; default: - CERROR("%s: unknown lfsck_namespace status: %u\n", + CERROR("%s: unknown lfsck_namespace status: rc = %u\n", lfsck_lfsck2name(lfsck), ns->ln_status); /* fall through */ case LS_SCANNING_PHASE1: @@ -1611,8 +1608,10 @@ int lfsck_namespace_setup(const struct lu_env *env, /* fall through */ case LS_PAUSED: case LS_CRASHED: + spin_lock(&lfsck->li_lock); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_scan); cfs_list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir); + spin_unlock(&lfsck->li_lock); break; } -- 1.8.3.1