X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Flfsck%2Flfsck_lib.c;h=37efbcc1d8f77b9310d4564ef2b561914839a511;hp=a4c963cbb8016415af8bf46a87c3cef1e533d3b3;hb=0347ad57ee875b730c3ec0da203857a5c86fc394;hpb=8931d9070415e808e09bb4befd7cd38ef2431149 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: