Whamcloud - gitweb
LU-3950 lfsck: control LFSCK on all devices via single command
[fs/lustre-release.git] / lustre / lfsck / lfsck_lib.c
index d59a07a..3eb3a02 100644 (file)
@@ -90,6 +90,7 @@ const char *lfsck_param_names[] = {
        NULL,
        "failout",
        "dryrun",
+       "all_targets",
        NULL
 };
 
@@ -137,6 +138,7 @@ static void lfsck_tgt_descs_fini(struct lfsck_tgt_descs *ltds)
                ltd = LTD_TGT(ltds, idx);
                if (likely(ltd != NULL)) {
                        LASSERT(list_empty(&ltd->ltd_layout_list));
+                       LASSERT(list_empty(&ltd->ltd_layout_phase_list));
 
                        ltds->ltd_tgtnr--;
                        cfs_bitmap_clear(ltds->ltd_tgts_bitmap, idx);
@@ -329,9 +331,6 @@ void lfsck_instance_cleanup(const struct lu_env *env,
        LASSERT(list_empty(&lfsck->li_link));
        LASSERT(thread_is_init(thread) || thread_is_stopped(thread));
 
-       lfsck_tgt_descs_fini(&lfsck->li_ost_descs);
-       lfsck_tgt_descs_fini(&lfsck->li_mdt_descs);
-
        if (lfsck->li_obj_oit != NULL) {
                lu_object_put_nocache(env, &lfsck->li_obj_oit->do_lu);
                lfsck->li_obj_oit = NULL;
@@ -362,6 +361,9 @@ void lfsck_instance_cleanup(const struct lu_env *env,
                lfsck_component_cleanup(env, com);
        }
 
+       lfsck_tgt_descs_fini(&lfsck->li_ost_descs);
+       lfsck_tgt_descs_fini(&lfsck->li_mdt_descs);
+
        if (lfsck->li_bookmark_obj != NULL) {
                lu_object_put_nocache(env, &lfsck->li_bookmark_obj->do_lu);
                lfsck->li_bookmark_obj = NULL;
@@ -680,7 +682,8 @@ static int lfsck_needs_scan_dir(const struct lu_env *env,
 }
 
 struct lfsck_thread_args *lfsck_thread_args_init(struct lfsck_instance *lfsck,
-                                                struct lfsck_component *com)
+                                                struct lfsck_component *com,
+                                                struct lfsck_start_param *lsp)
 {
        struct lfsck_thread_args *lta;
        int                       rc;
@@ -699,6 +702,8 @@ struct lfsck_thread_args *lfsck_thread_args_init(struct lfsck_instance *lfsck,
        if (com != NULL)
                lta->lta_com = lfsck_component_get(com);
 
+       lta->lta_lsp = lsp;
+
        return lta;
 }
 
@@ -746,7 +751,8 @@ int lfsck_checkpoint(const struct lu_env *env, struct lfsck_instance *lfsck)
        return rc1 != 0 ? rc1 : rc;
 }
 
-int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck)
+int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck,
+              struct lfsck_start_param *lsp)
 {
        struct dt_object       *obj     = NULL;
        struct lfsck_component *com;
@@ -767,7 +773,7 @@ int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck)
                if (lfsck->li_bookmark_ram.lb_param & LPF_DRYRUN)
                        com->lc_journal = 0;
 
-               rc = com->lc_ops->lfsck_prep(env, com);
+               rc = com->lc_ops->lfsck_prep(env, com, lsp);
                if (rc != 0)
                        GOTO(out, rc);
 
@@ -981,7 +987,49 @@ int lfsck_double_scan(const struct lu_env *env, struct lfsck_instance *lfsck)
                     atomic_read(&lfsck->li_double_scan_count) == 0,
                     &lwi);
 
-       return (rc1 != 0 ? rc1 : rc);
+       return rc1 != 0 ? rc1 : rc;
+}
+
+int lfsck_stop_notify(const struct lu_env *env, struct lfsck_instance *lfsck,
+                     struct lfsck_tgt_descs *ltds, struct lfsck_tgt_desc *ltd)
+{
+       struct ptlrpc_request_set *set;
+       struct lfsck_component    *com;
+       int                        cnt = 0;
+       int                        rc  = 0;
+       int                        rc1 = 0;
+
+       set = ptlrpc_prep_set();
+       if (set == NULL)
+               return -ENOMEM;
+
+       list_for_each_entry(com, &lfsck->li_list_scan, lc_link) {
+               if (com->lc_ops->lfsck_stop_notify != NULL) {
+                       rc = com->lc_ops->lfsck_stop_notify(env, com, ltds,
+                                                           ltd, set);
+                       if (rc != 0)
+                               rc1 = rc;
+                       else
+                               cnt++;
+               }
+       }
+
+       list_for_each_entry(com, &lfsck->li_list_double_scan, lc_link) {
+               if (com->lc_ops->lfsck_stop_notify != NULL) {
+                       rc = com->lc_ops->lfsck_stop_notify(env, com, ltds,
+                                                           ltd, set);
+                       if (rc != 0)
+                               rc1 = rc;
+                       else
+                               cnt++;
+               }
+       }
+
+       if (cnt > 0)
+               rc = ptlrpc_set_wait(set);
+       ptlrpc_set_destroy(set);
+
+       return rc1 != 0 ? rc1 : rc;
 }
 
 void lfsck_quit(const struct lu_env *env, struct lfsck_instance *lfsck)
@@ -1002,6 +1050,58 @@ void lfsck_quit(const struct lu_env *env, struct lfsck_instance *lfsck)
        }
 }
 
+int lfsck_async_request(const struct lu_env *env, struct obd_export *exp,
+                       struct lfsck_request *lr,
+                       struct ptlrpc_request_set *set,
+                       ptlrpc_interpterer_t interpreter,
+                       void *args, int request)
+{
+       struct lfsck_async_interpret_args *laia;
+       struct ptlrpc_request             *req;
+       struct lfsck_request              *tmp;
+       struct req_format                 *format;
+       int                                rc;
+
+       if (!(exp_connect_flags(exp) & OBD_CONNECT_LFSCK))
+               return -EOPNOTSUPP;
+
+       switch (request) {
+       case LFSCK_NOTIFY:
+               format = &RQF_LFSCK_NOTIFY;
+               break;
+       case LFSCK_QUERY:
+               format = &RQF_LFSCK_QUERY;
+               break;
+       default:
+               CERROR("%s: unknown async request: opc = %d\n",
+                      exp->exp_obd->obd_name, request);
+               return -EINVAL;
+       }
+
+       req = ptlrpc_request_alloc(class_exp2cliimp(exp), format);
+       if (req == NULL)
+               return -ENOMEM;
+
+       rc = ptlrpc_request_pack(req, LUSTRE_OBD_VERSION, request);
+       if (rc != 0) {
+               ptlrpc_request_free(req);
+
+               return rc;
+       }
+
+       tmp = req_capsule_client_get(&req->rq_pill, &RMF_LFSCK_REQUEST);
+       *tmp = *lr;
+       ptlrpc_request_set_replen(req);
+
+       laia = ptlrpc_req_async_args(req);
+       *laia = *(struct lfsck_async_interpret_args *)args;
+       lfsck_component_get(laia->laia_com);
+       req->rq_interpret_reply = interpreter;
+       ptlrpc_set_add_req(set, req);
+
+       return 0;
+}
+
 /* external interfaces */
 
 int lfsck_get_speed(struct dt_device *key, void *buf, int len)
@@ -1189,20 +1289,27 @@ int lfsck_start(const struct lu_env *env, struct dt_device *key,
        if (!thread_is_init(thread) && !thread_is_stopped(thread)) {
                rc = -EALREADY;
                while (start->ls_active != 0) {
-                       if (type & start->ls_active) {
+                       if (!(type & start->ls_active)) {
+                               type <<= 1;
+                               continue;
+                       }
+
+                       com = __lfsck_component_find(lfsck, type,
+                                                    &lfsck->li_list_scan);
+                       if (com == NULL)
                                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;
+                       if (com == NULL) {
+                               rc = -EOPNOTSUPP;
+                               break;
+                       }
+
+                       if (com->lc_ops->lfsck_join != NULL) {
+                               rc = com->lc_ops->lfsck_join( env, com, lsp);
+                               if (rc != 0 && rc != -EALREADY)
                                        break;
-                               } else {
-                                       start->ls_active &= ~type;
-                               }
                        }
+                       start->ls_active &= ~type;
                        type <<= 1;
                }
                spin_unlock(&lfsck->li_lock);
@@ -1265,6 +1372,16 @@ int lfsck_start(const struct lu_env *env, struct dt_device *key,
                }
        }
 
+       if (bk->lb_param & LPF_ALL_MDT &&
+           !(start->ls_flags & LPF_ALL_MDT)) {
+               bk->lb_param &= ~LPF_ALL_MDT;
+               dirty = true;
+       } else if (!(bk->lb_param & LPF_ALL_MDT) &&
+                  start->ls_flags & LPF_ALL_MDT) {
+               bk->lb_param |= LPF_ALL_MDT;
+               dirty = true;
+       }
+
        if (dirty) {
                rc = lfsck_bookmark_store(env, lfsck);
                if (rc != 0)
@@ -1340,7 +1457,7 @@ trigger:
 
        lfsck->li_args_oit = (flags << DT_OTABLE_IT_FLAGS_SHIFT) | valid;
        thread_set_flags(thread, 0);
-       lta = lfsck_thread_args_init(lfsck, NULL);
+       lta = lfsck_thread_args_init(lfsck, NULL, lsp);
        if (IS_ERR(lta))
                GOTO(out, rc = PTR_ERR(lta));
 
@@ -1388,10 +1505,13 @@ int lfsck_stop(const struct lu_env *env, struct dt_device *key,
                GOTO(out, rc = -EALREADY);
        }
 
-       if (stop != NULL)
+       if (stop != NULL) {
                lfsck->li_status = stop->ls_status;
-       else
+               lfsck->li_flags = stop->ls_flags;
+       } else {
                lfsck->li_status = LS_STOPPED;
+               lfsck->li_flags = 0;
+       }
 
        thread_set_flags(thread, SVC_STOPPING);
        spin_unlock(&lfsck->li_lock);
@@ -1473,8 +1593,8 @@ int lfsck_query(const struct lu_env *env, struct dt_device *key,
 EXPORT_SYMBOL(lfsck_query);
 
 int lfsck_register(const struct lu_env *env, struct dt_device *key,
-                  struct dt_device *next, lfsck_out_notify notify,
-                  void *notify_data, bool master)
+                  struct dt_device *next, struct obd_device *obd,
+                  lfsck_out_notify notify, void *notify_data, bool master)
 {
        struct lfsck_instance   *lfsck;
        struct dt_object        *root  = NULL;
@@ -1505,6 +1625,7 @@ int lfsck_register(const struct lu_env *env, struct dt_device *key,
        lfsck->li_out_notify_data = notify_data;
        lfsck->li_next = next;
        lfsck->li_bottom = key;
+       lfsck->li_obd = obd;
 
        rc = lfsck_tgt_descs_init(&lfsck->li_ost_descs);
        if (rc != 0)
@@ -1617,6 +1738,7 @@ int lfsck_add_target(const struct lu_env *env, struct dt_device *key,
        ltd->ltd_exp = exp;
        INIT_LIST_HEAD(&ltd->ltd_orphan_list);
        INIT_LIST_HEAD(&ltd->ltd_layout_list);
+       INIT_LIST_HEAD(&ltd->ltd_layout_phase_list);
        atomic_set(&ltd->ltd_ref, 1);
        ltd->ltd_index = index;
 
@@ -1653,6 +1775,7 @@ void lfsck_del_target(const struct lu_env *env, struct dt_device *key,
        struct lfsck_tgt_desc   *ltd;
        struct list_head        *head;
        bool                     found = false;
+       bool                     stop  = false;
 
        if (for_ost)
                head = &lfsck_ost_orphan_list;
@@ -1692,11 +1815,19 @@ void lfsck_del_target(const struct lu_env *env, struct dt_device *key,
                goto unlock;
 
        found = true;
+       spin_lock(&ltds->ltd_lock);
+       ltd->ltd_dead = 1;
        if (!list_empty(&ltd->ltd_layout_list)) {
-               spin_lock(&ltds->ltd_lock);
+               list_del_init(&ltd->ltd_layout_phase_list);
                list_del_init(&ltd->ltd_layout_list);
-               spin_unlock(&ltds->ltd_lock);
+               stop = true;
+       } else {
+               LASSERT(list_empty(&ltd->ltd_layout_phase_list));
        }
+       spin_unlock(&ltds->ltd_lock);
+
+       if (stop && lfsck->li_master)
+               lfsck_stop_notify(env, lfsck, ltds, ltd);
 
        LASSERT(ltds->ltd_tgtnr > 0);