Whamcloud - gitweb
LU-6684 lfsck: set the lfsck notify as interruptable
[fs/lustre-release.git] / lustre / lfsck / lfsck_lib.c
index 2a41620..139c95b 100644 (file)
@@ -20,7 +20,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2013, 2014, Intel Corporation.
+ * Copyright (c) 2013, 2015, Intel Corporation.
  */
 /*
  * lustre/lfsck/lfsck_lib.c
@@ -31,6 +31,7 @@
 #define DEBUG_SUBSYSTEM S_LFSCK
 
 #include <linux/kthread.h>
+#include <linux/sched.h>
 #include <libcfs/list.h>
 #include <lu_object.h>
 #include <dt_object.h>
@@ -364,13 +365,12 @@ int lfsck_fid_alloc(const struct lu_env *env, struct lfsck_instance *lfsck,
 
 static int __lfsck_ibits_lock(const struct lu_env *env,
                              struct lfsck_instance *lfsck,
-                             struct dt_object *obj,
-                             struct ldlm_res_id *resid,
-                             struct lustre_handle *lh,
-                             __u64 bits, ldlm_mode_t mode)
+                             struct dt_object *obj, struct ldlm_res_id *resid,
+                             struct lustre_handle *lh, __u64 bits,
+                             enum ldlm_mode mode)
 {
        struct lfsck_thread_info        *info   = lfsck_env_info(env);
-       ldlm_policy_data_t              *policy = &info->lti_policy;
+       union ldlm_policy_data          *policy = &info->lti_policy;
        __u64                            flags  = LDLM_FL_ATOMIC_CB;
        int                              rc;
 
@@ -425,7 +425,7 @@ static int __lfsck_ibits_lock(const struct lu_env *env,
  */
 int lfsck_ibits_lock(const struct lu_env *env, struct lfsck_instance *lfsck,
                     struct dt_object *obj, struct lustre_handle *lh,
-                    __u64 bits, ldlm_mode_t mode)
+                    __u64 bits, enum ldlm_mode mode)
 {
        struct ldlm_res_id *resid = &lfsck_env_info(env)->lti_resid;
 
@@ -444,7 +444,7 @@ int lfsck_ibits_lock(const struct lu_env *env, struct lfsck_instance *lfsck,
  * \param[in] lh       pointer to the lock handle
  * \param[in] mode     the mode for the ldlm lock to be released
  */
-void lfsck_ibits_unlock(struct lustre_handle *lh, ldlm_mode_t mode)
+void lfsck_ibits_unlock(struct lustre_handle *lh, enum ldlm_mode mode)
 {
        if (lustre_handle_is_used(lh)) {
                ldlm_lock_decref(lh, mode);
@@ -477,8 +477,8 @@ void lfsck_ibits_unlock(struct lustre_handle *lh, ldlm_mode_t mode)
  * \retval             negative error number on failure
  */
 int lfsck_lock(const struct lu_env *env, struct lfsck_instance *lfsck,
-                  struct dt_object *obj, const char *name,
-                  struct lfsck_lock_handle *llh, __u64 bits, ldlm_mode_t mode)
+              struct dt_object *obj, const char *name,
+              struct lfsck_lock_handle *llh, __u64 bits, enum ldlm_mode mode)
 {
        struct ldlm_res_id *resid = &lfsck_env_info(env)->lti_resid;
        int                 rc;
@@ -664,12 +664,30 @@ static int lfsck_create_lpf_local(const struct lu_env *env,
        if (rc != 0)
                GOTO(stop, rc);
 
+       if (!dt_try_as_dir(env, child))
+               GOTO(stop, rc = -ENOTDIR);
+
        /* 2a. increase child nlink */
        rc = dt_declare_ref_add(env, child, th);
        if (rc != 0)
                GOTO(stop, rc);
 
-       /* 3a. insert linkEA for child */
+       /* 3a. insert dot into child dir */
+       rec->rec_type = S_IFDIR;
+       rec->rec_fid = cfid;
+       rc = dt_declare_insert(env, child, (const struct dt_rec *)rec,
+                              (const struct dt_key *)dot, th);
+       if (rc != 0)
+               GOTO(stop, rc);
+
+       /* 4a. insert dotdot into child dir */
+       rec->rec_fid = &LU_LPF_FID;
+       rc = dt_declare_insert(env, child, (const struct dt_rec *)rec,
+                              (const struct dt_key *)dotdot, th);
+       if (rc != 0)
+               GOTO(stop, rc);
+
+       /* 5a. insert linkEA for child */
        lfsck_buf_init(&linkea_buf, ldata.ld_buf->lb_buf,
                       ldata.ld_leh->leh_len);
        rc = dt_declare_xattr_set(env, child, &linkea_buf,
@@ -677,7 +695,7 @@ static int lfsck_create_lpf_local(const struct lu_env *env,
        if (rc != 0)
                GOTO(stop, rc);
 
-       /* 4a. insert name into parent dir */
+       /* 6a. insert name into parent dir */
        rec->rec_type = S_IFDIR;
        rec->rec_fid = cfid;
        rc = dt_declare_insert(env, parent, (const struct dt_rec *)rec,
@@ -685,12 +703,12 @@ static int lfsck_create_lpf_local(const struct lu_env *env,
        if (rc != 0)
                GOTO(stop, rc);
 
-       /* 5a. increase parent nlink */
+       /* 7a. increase parent nlink */
        rc = dt_declare_ref_add(env, parent, th);
        if (rc != 0)
                GOTO(stop, rc);
 
-       /* 6a. update bookmark */
+       /* 8a. update bookmark */
        rc = dt_declare_record_write(env, bk_obj,
                                     lfsck_buf_get(env, bk, len), 0, th);
        if (rc != 0)
@@ -701,41 +719,38 @@ static int lfsck_create_lpf_local(const struct lu_env *env,
                GOTO(stop, rc);
 
        dt_write_lock(env, child, 0);
-       /* 1b.1. create child */
+       /* 1b. create child */
        rc = dt_create(env, child, la, NULL, dof, th);
        if (rc != 0)
                GOTO(unlock, rc);
 
-       if (unlikely(!dt_try_as_dir(env, child)))
-               GOTO(unlock, rc = -ENOTDIR);
+       /* 2b. increase child nlink */
+       rc = dt_ref_add(env, child, th);
+       if (rc != 0)
+               GOTO(unlock, rc);
 
-       /* 1b.2. insert dot into child dir */
+       /* 3b. insert dot into child dir */
        rec->rec_fid = cfid;
        rc = dt_insert(env, child, (const struct dt_rec *)rec,
                       (const struct dt_key *)dot, th, 1);
        if (rc != 0)
                GOTO(unlock, rc);
 
-       /* 1b.3. insert dotdot into child dir */
+       /* 4b. insert dotdot into child dir */
        rec->rec_fid = &LU_LPF_FID;
        rc = dt_insert(env, child, (const struct dt_rec *)rec,
                       (const struct dt_key *)dotdot, th, 1);
        if (rc != 0)
                GOTO(unlock, rc);
 
-       /* 2b. increase child nlink */
-       rc = dt_ref_add(env, child, th);
-       if (rc != 0)
-               GOTO(unlock, rc);
-
-       /* 3b. insert linkEA for child. */
+       /* 5b. insert linkEA for child. */
        rc = dt_xattr_set(env, child, &linkea_buf,
                          XATTR_NAME_LINK, 0, th);
        dt_write_unlock(env, child);
        if (rc != 0)
                GOTO(stop, rc);
 
-       /* 4b. insert name into parent dir */
+       /* 6b. insert name into parent dir */
        rec->rec_fid = cfid;
        rc = dt_insert(env, parent, (const struct dt_rec *)rec,
                       (const struct dt_key *)name, th, 1);
@@ -743,7 +758,7 @@ static int lfsck_create_lpf_local(const struct lu_env *env,
                GOTO(stop, rc);
 
        dt_write_lock(env, parent, 0);
-       /* 5b. increase parent nlink */
+       /* 7b. increase parent nlink */
        rc = dt_ref_add(env, parent, th);
        dt_write_unlock(env, parent);
        if (rc != 0)
@@ -752,7 +767,7 @@ static int lfsck_create_lpf_local(const struct lu_env *env,
        bk->lb_lpf_fid = *cfid;
        lfsck_bookmark_cpu_to_le(&lfsck->li_bookmark_disk, bk);
 
-       /* 6b. update bookmark */
+       /* 8b. update bookmark */
        rc = dt_record_write(env, bk_obj,
                             lfsck_buf_get(env, bk, len), &pos, th);
 
@@ -831,12 +846,30 @@ static int lfsck_create_lpf_remote(const struct lu_env *env,
        if (rc != 0)
                GOTO(stop, rc);
 
+       if (!dt_try_as_dir(env, child))
+               GOTO(stop, rc = -ENOTDIR);
+
        /* 2a. increase child nlink */
        rc = dt_declare_ref_add(env, child, th);
        if (rc != 0)
                GOTO(stop, rc);
 
-       /* 3a. insert linkEA for child */
+       /* 3a. insert dot into child dir */
+       rec->rec_type = S_IFDIR;
+       rec->rec_fid = cfid;
+       rc = dt_declare_insert(env, child, (const struct dt_rec *)rec,
+                              (const struct dt_key *)dot, th);
+       if (rc != 0)
+               GOTO(stop, rc);
+
+       /* 4a. insert dotdot into child dir */
+       rec->rec_fid = &LU_LPF_FID;
+       rc = dt_declare_insert(env, child, (const struct dt_rec *)rec,
+                              (const struct dt_key *)dotdot, th);
+       if (rc != 0)
+               GOTO(stop, rc);
+
+       /* 5a. insert linkEA for child */
        lfsck_buf_init(&linkea_buf, ldata.ld_buf->lb_buf,
                       ldata.ld_leh->leh_len);
        rc = dt_declare_xattr_set(env, child, &linkea_buf,
@@ -844,7 +877,7 @@ static int lfsck_create_lpf_remote(const struct lu_env *env,
        if (rc != 0)
                GOTO(stop, rc);
 
-       /* 4a. update bookmark */
+       /* 6a. update bookmark */
        rc = dt_declare_record_write(env, bk_obj,
                                     lfsck_buf_get(env, bk, len), 0, th);
        if (rc != 0)
@@ -855,15 +888,17 @@ static int lfsck_create_lpf_remote(const struct lu_env *env,
                GOTO(stop, rc);
 
        dt_write_lock(env, child, 0);
-       /* 1b.1. create child */
+       /* 1b. create child */
        rc = dt_create(env, child, la, NULL, dof, th);
        if (rc != 0)
                GOTO(unlock, rc);
 
-       if (unlikely(!dt_try_as_dir(env, child)))
-               GOTO(unlock, rc = -ENOTDIR);
+       /* 2b. increase child nlink */
+       rc = dt_ref_add(env, child, th);
+       if (rc != 0)
+               GOTO(unlock, rc);
 
-       /* 1b.2. insert dot into child dir */
+       /* 3b. insert dot into child dir */
        rec->rec_type = S_IFDIR;
        rec->rec_fid = cfid;
        rc = dt_insert(env, child, (const struct dt_rec *)rec,
@@ -871,19 +906,14 @@ static int lfsck_create_lpf_remote(const struct lu_env *env,
        if (rc != 0)
                GOTO(unlock, rc);
 
-       /* 1b.3. insert dotdot into child dir */
+       /* 4b. insert dotdot into child dir */
        rec->rec_fid = &LU_LPF_FID;
        rc = dt_insert(env, child, (const struct dt_rec *)rec,
                       (const struct dt_key *)dotdot, th, 1);
        if (rc != 0)
                GOTO(unlock, rc);
 
-       /* 2b. increase child nlink */
-       rc = dt_ref_add(env, child, th);
-       if (rc != 0)
-               GOTO(unlock, rc);
-
-       /* 3b. insert linkEA for child */
+       /* 5b. insert linkEA for child */
        rc = dt_xattr_set(env, child, &linkea_buf,
                          XATTR_NAME_LINK, 0, th);
        if (rc != 0)
@@ -892,7 +922,7 @@ static int lfsck_create_lpf_remote(const struct lu_env *env,
        bk->lb_lpf_fid = *cfid;
        lfsck_bookmark_cpu_to_le(&lfsck->li_bookmark_disk, bk);
 
-       /* 4b. update bookmark */
+       /* 6b. update bookmark */
        rc = dt_record_write(env, bk_obj,
                             lfsck_buf_get(env, bk, len), &pos, th);
 
@@ -1406,61 +1436,13 @@ int lfsck_verify_lpf(const struct lu_env *env, struct lfsck_instance *lfsck)
                               lfsck_lfsck2name(lfsck), rc);
        }
 
-       if (!fid_is_zero(&bk->lb_lpf_fid)) {
-               if (unlikely(!fid_is_norm(&bk->lb_lpf_fid))) {
-                       struct lu_fid tfid = bk->lb_lpf_fid;
-
-                       /* Invalid FID record in the bookmark file, reset it. */
-                       fid_zero(&bk->lb_lpf_fid);
-                       rc = lfsck_bookmark_store(env, lfsck);
-
-                       CDEBUG(D_LFSCK, "%s: reset invalid LPF fid "DFID
-                              " in the bookmark file: rc = %d\n",
-                              lfsck_lfsck2name(lfsck), PFID(&tfid), rc);
-
-                       if (rc != 0)
-                               GOTO(put, rc);
-               } else {
-                       child1 = lfsck_object_find_bottom(env, lfsck,
-                                                         &bk->lb_lpf_fid);
-                       if (IS_ERR(child1)) {
-                               child1 = NULL;
-                               goto find_child2;
-                       }
-
-                       if (unlikely(!dt_object_exists(child1) ||
-                                    dt_object_remote(child1)) ||
-                                    !S_ISDIR(lfsck_object_type(child1))) {
-                               /* Invalid FID record in the bookmark file,
-                                * reset it. */
-                               fid_zero(&bk->lb_lpf_fid);
-                               rc = lfsck_bookmark_store(env, lfsck);
-
-                               CDEBUG(D_LFSCK, "%s: reset invalid LPF fid "DFID
-                                      " in the bookmark file: rc = %d\n",
-                                      lfsck_lfsck2name(lfsck),
-                                      PFID(lfsck_dto2fid(child1)), rc);
-
-                               if (rc != 0)
-                                       GOTO(put, rc);
-
-                               lfsck_object_put(env, child1);
-                               child1 = NULL;
-                       } else if (unlikely(!dt_try_as_dir(env, child1))) {
-                               GOTO(put, rc = -ENOTDIR);
-                       }
-               }
-       }
-
-find_child2:
+       /* child2 */
        snprintf(name, 8, "MDT%04x", node);
        rc = dt_lookup(env, parent, (struct dt_rec *)cfid,
                       (const struct dt_key *)name);
        if (rc == -ENOENT) {
-               if (!fid_is_zero(&bk->lb_lpf_fid))
-                       goto check_child1;
-
-               GOTO(put, rc = 0);
+               rc = 0;
+               goto find_child1;
        }
 
        if (rc != 0)
@@ -1472,7 +1454,7 @@ find_child2:
                if (rc != 0)
                        GOTO(put, rc);
 
-               goto check_child1;
+               goto find_child1;
        }
 
        child2 = lfsck_object_find_bottom(env, lfsck, cfid);
@@ -1486,23 +1468,20 @@ find_child2:
                if (rc != 0)
                        GOTO(put, rc);
 
-               goto check_child1;
+               goto find_child1;
        }
 
-       if (unlikely(!dt_try_as_dir(env, child2)))
-               GOTO(put, rc = -ENOTDIR);
+       if (unlikely(!dt_try_as_dir(env, child2))) {
+               lfsck_object_put(env, child2);
+               child2 = NULL;
+               rc = -ENOTDIR;
+       }
 
-       if (child1 == NULL) {
-               rc = lfsck_verify_lpf_pairs(env, lfsck, child2, name,
-                                           pfid, LVLT_BY_NAMEENTRY);
-       } else if (!lu_fid_eq(cfid, &bk->lb_lpf_fid)) {
-               rc = lfsck_verify_lpf_pairs(env, lfsck, child1, name,
-                                           pfid, LVLT_BY_BOOKMARK);
-               if (!lu_fid_eq(pfid, &LU_LPF_FID))
-                       rc = lfsck_verify_lpf_pairs(env, lfsck, child2,
-                                                   name, pfid,
-                                                   LVLT_BY_NAMEENTRY);
-       } else {
+find_child1:
+       if (fid_is_zero(&bk->lb_lpf_fid))
+               goto check_child2;
+
+       if (likely(lu_fid_eq(cfid, &bk->lb_lpf_fid))) {
                if (lfsck->li_lpf_obj == NULL) {
                        lu_object_get(&child2->do_lu);
                        lfsck->li_lpf_obj = child2;
@@ -1510,14 +1489,69 @@ find_child2:
 
                cname = lfsck_name_get_const(env, name, strlen(name));
                rc = lfsck_verify_linkea(env, child2, cname, &LU_LPF_FID);
+
+               GOTO(put, rc);
        }
 
-       GOTO(put, rc);
+       if (unlikely(!fid_is_norm(&bk->lb_lpf_fid))) {
+               struct lu_fid tfid = bk->lb_lpf_fid;
+
+               /* Invalid FID record in the bookmark file, reset it. */
+               fid_zero(&bk->lb_lpf_fid);
+               rc = lfsck_bookmark_store(env, lfsck);
+
+               CDEBUG(D_LFSCK, "%s: reset invalid LPF fid "DFID
+                      " in the bookmark file: rc = %d\n",
+                      lfsck_lfsck2name(lfsck), PFID(&tfid), rc);
+
+               if (rc != 0)
+                       GOTO(put, rc);
+
+               goto check_child2;
+       }
+
+       child1 = lfsck_object_find_bottom(env, lfsck, &bk->lb_lpf_fid);
+       if (IS_ERR(child1)) {
+               child1 = NULL;
+               goto check_child2;
+       }
+
+       if (unlikely(!dt_object_exists(child1) ||
+                    dt_object_remote(child1)) ||
+                    !S_ISDIR(lfsck_object_type(child1))) {
+               /* Invalid FID record in the bookmark file, reset it. */
+               fid_zero(&bk->lb_lpf_fid);
+               rc = lfsck_bookmark_store(env, lfsck);
+
+               CDEBUG(D_LFSCK, "%s: reset invalid LPF fid "DFID
+                      " in the bookmark file: rc = %d\n",
+                      lfsck_lfsck2name(lfsck),
+                      PFID(lfsck_dto2fid(child1)), rc);
+
+               if (rc != 0)
+                       GOTO(put, rc);
 
-check_child1:
-       if (child1 != NULL)
-               rc = lfsck_verify_lpf_pairs(env, lfsck, child1, name,
-                                           pfid, LVLT_BY_BOOKMARK);
+               lfsck_object_put(env, child1);
+               child1 = NULL;
+               goto check_child2;
+       }
+
+       if (unlikely(!dt_try_as_dir(env, child1))) {
+               lfsck_object_put(env, child1);
+               child1 = NULL;
+               rc = -ENOTDIR;
+               goto check_child2;
+       }
+
+       rc = lfsck_verify_lpf_pairs(env, lfsck, child1, name, pfid,
+                                   LVLT_BY_BOOKMARK);
+       if (lu_fid_eq(pfid, &LU_LPF_FID))
+               GOTO(put, rc);
+
+check_child2:
+       if (child2 != NULL)
+               rc = lfsck_verify_lpf_pairs(env, lfsck, child2, name,
+                                           pfid, LVLT_BY_NAMEENTRY);
 
        GOTO(put, rc);
 
@@ -2379,6 +2413,7 @@ int lfsck_async_request(const struct lu_env *env, struct obd_export *exp,
        if (laia->laia_com != NULL)
                lfsck_component_get(laia->laia_com);
        req->rq_interpret_reply = interpreter;
+       req->rq_allow_intr = 1;
        ptlrpc_set_add_req(set, req);
 
        return 0;
@@ -2464,6 +2499,9 @@ void lfsck_post_generic(const struct lu_env *env,
                lad->lad_exit = 1;
        lad->lad_to_post = 1;
 
+       CDEBUG(D_LFSCK, "%s: waiting for assistant to do %s post, rc = %d\n",
+              lfsck_lfsck2name(com->lc_lfsck), lad->lad_name, *result);
+
        wake_up_all(&athread->t_ctl_waitq);
        l_wait_event(mthread->t_ctl_waitq,
                     (*result > 0 && list_empty(&lad->lad_req_list)) ||
@@ -2472,6 +2510,9 @@ void lfsck_post_generic(const struct lu_env *env,
 
        if (lad->lad_assistant_status < 0)
                *result = lad->lad_assistant_status;
+
+       CDEBUG(D_LFSCK, "%s: the assistant has done %s post, rc = %d\n",
+              lfsck_lfsck2name(com->lc_lfsck), lad->lad_name, *result);
 }
 
 int lfsck_double_scan_generic(const struct lu_env *env,
@@ -2487,12 +2528,20 @@ int lfsck_double_scan_generic(const struct lu_env *env,
        else
                lad->lad_to_double_scan = 1;
 
+       CDEBUG(D_LFSCK, "%s: waiting for assistant to do %s double_scan, "
+              "status %d\n",
+              lfsck_lfsck2name(com->lc_lfsck), lad->lad_name, status);
+
        wake_up_all(&athread->t_ctl_waitq);
        l_wait_event(mthread->t_ctl_waitq,
                     lad->lad_in_double_scan ||
                     thread_is_stopped(athread),
                     &lwi);
 
+       CDEBUG(D_LFSCK, "%s: the assistant has done %s double_scan, "
+              "status %d\n", lfsck_lfsck2name(com->lc_lfsck), lad->lad_name,
+              lad->lad_assistant_status);
+
        if (lad->lad_assistant_status < 0)
                return lad->lad_assistant_status;
 
@@ -3110,6 +3159,28 @@ int lfsck_stop(const struct lu_env *env, struct dt_device *key,
        }
 
        thread_set_flags(thread, SVC_STOPPING);
+
+       if (lfsck->li_master) {
+               struct lfsck_component *com;
+               struct lfsck_assistant_data *lad;
+
+               list_for_each_entry(com, &lfsck->li_list_scan, lc_link) {
+                       lad = com->lc_data;
+                       spin_lock(&lad->lad_lock);
+                       if (lad->lad_task != NULL)
+                               force_sig(SIGINT, lad->lad_task);
+                       spin_unlock(&lad->lad_lock);
+               }
+
+               list_for_each_entry(com, &lfsck->li_list_double_scan, lc_link) {
+                       lad = com->lc_data;
+                       spin_lock(&lad->lad_lock);
+                       if (lad->lad_task != NULL)
+                               force_sig(SIGINT, lad->lad_task);
+                       spin_unlock(&lad->lad_lock);
+               }
+       }
+
        spin_unlock(&lfsck->li_lock);
 
        wake_up_all(&thread->t_ctl_waitq);
@@ -3592,8 +3663,8 @@ static void __exit lfsck_exit(void)
        lu_context_key_degister(&lfsck_thread_key);
 }
 
-MODULE_AUTHOR("Intel Corporation <http://www.intel.com/>");
-MODULE_DESCRIPTION("LFSCK");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
+MODULE_DESCRIPTION("Lustre File System Checker");
 MODULE_VERSION(LUSTRE_VERSION_STRING);
 MODULE_LICENSE("GPL");