Whamcloud - gitweb
LU-13453 osd-ldiskfs: do not leak inode if OI insertion fails
[fs/lustre-release.git] / lustre / obdclass / scrub.c
index 3ab8540..adcffa9 100644 (file)
 
 static inline struct dt_device *scrub_obj2dev(struct dt_object *obj)
 {
-       return container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
+       return container_of_safe(obj->do_lu.lo_dev, struct dt_device,
+                                dd_lu_dev);
 }
 
 static void scrub_file_to_cpu(struct scrub_file *des, struct scrub_file *src)
 {
-       memcpy(des->sf_uuid, src->sf_uuid, 16);
+       uuid_copy(&des->sf_uuid, &src->sf_uuid);
        des->sf_flags   = le64_to_cpu(src->sf_flags);
        des->sf_magic   = le32_to_cpu(src->sf_magic);
        des->sf_status  = le16_to_cpu(src->sf_status);
@@ -80,7 +81,7 @@ static void scrub_file_to_cpu(struct scrub_file *des, struct scrub_file *src)
 
 static void scrub_file_to_le(struct scrub_file *des, struct scrub_file *src)
 {
-       memcpy(des->sf_uuid, src->sf_uuid, 16);
+       uuid_copy(&des->sf_uuid, &src->sf_uuid);
        des->sf_flags   = cpu_to_le64(src->sf_flags);
        des->sf_magic   = cpu_to_le32(src->sf_magic);
        des->sf_status  = cpu_to_le16(src->sf_status);
@@ -112,18 +113,18 @@ static void scrub_file_to_le(struct scrub_file *des, struct scrub_file *src)
        memcpy(des->sf_oi_bitmap, src->sf_oi_bitmap, SCRUB_OI_BITMAP_SIZE);
 }
 
-void scrub_file_init(struct lustre_scrub *scrub, __u8 *uuid)
+void scrub_file_init(struct lustre_scrub *scrub, uuid_t uuid)
 {
        struct scrub_file *sf = &scrub->os_file;
 
        memset(sf, 0, sizeof(*sf));
-       memcpy(sf->sf_uuid, uuid, 16);
+       uuid_copy(&sf->sf_uuid, &uuid);
        sf->sf_magic = SCRUB_MAGIC_V1;
        sf->sf_status = SS_INIT;
 }
 EXPORT_SYMBOL(scrub_file_init);
 
-void scrub_file_reset(struct lustre_scrub *scrub, __u8 *uuid, __u64 flags)
+void scrub_file_reset(struct lustre_scrub *scrub, uuid_t uuid, u64 flags)
 {
        struct scrub_file *sf = &scrub->os_file;
 
@@ -131,7 +132,7 @@ void scrub_file_reset(struct lustre_scrub *scrub, __u8 *uuid, __u64 flags)
               "%#llx, add flags = %#llx\n",
               scrub->os_name, sf->sf_flags, flags);
 
-       memcpy(sf->sf_uuid, uuid, 16);
+       uuid_copy(&sf->sf_uuid, &uuid);
        sf->sf_status = SS_INIT;
        sf->sf_flags |= flags;
        sf->sf_flags &= ~SF_AUTO;
@@ -238,9 +239,9 @@ log:
                CDEBUG(D_LFSCK, "%s: store scrub file: rc = %d\n",
                       scrub->os_name, rc);
 
-       scrub->os_time_last_checkpoint = cfs_time_current();
+       scrub->os_time_last_checkpoint = ktime_get_seconds();
        scrub->os_time_next_checkpoint = scrub->os_time_last_checkpoint +
-                               cfs_time_seconds(SCRUB_CHECKPOINT_INTERVAL);
+                                        SCRUB_CHECKPOINT_INTERVAL;
        return rc;
 }
 EXPORT_SYMBOL(scrub_file_store);
@@ -248,10 +249,10 @@ EXPORT_SYMBOL(scrub_file_store);
 int scrub_checkpoint(const struct lu_env *env, struct lustre_scrub *scrub)
 {
        struct scrub_file *sf = &scrub->os_file;
+       time64_t now = ktime_get_seconds();
        int rc;
 
-       if (likely(cfs_time_before(cfs_time_current(),
-                                  scrub->os_time_next_checkpoint) ||
+       if (likely(now < scrub->os_time_next_checkpoint ||
                   scrub->os_new_checked == 0))
                return 0;
 
@@ -262,9 +263,8 @@ int scrub_checkpoint(const struct lu_env *env, struct lustre_scrub *scrub)
        sf->sf_items_checked += scrub->os_new_checked;
        scrub->os_new_checked = 0;
        sf->sf_pos_last_checkpoint = scrub->os_pos_current;
-       sf->sf_time_last_checkpoint = cfs_time_current_sec();
-       sf->sf_run_time += cfs_duration_sec(cfs_time_current() + HALF_SEC -
-                                           scrub->os_time_last_checkpoint);
+       sf->sf_time_last_checkpoint = ktime_get_real_seconds();
+       sf->sf_run_time += now - scrub->os_time_last_checkpoint;
        rc = scrub_file_store(env, scrub);
        up_write(&scrub->os_rwsem);
 
@@ -275,28 +275,12 @@ EXPORT_SYMBOL(scrub_checkpoint);
 int scrub_start(int (*threadfn)(void *data), struct lustre_scrub *scrub,
                void *data, __u32 flags)
 {
-       struct ptlrpc_thread *thread = &scrub->os_thread;
-       struct l_wait_info lwi = { 0 };
        struct task_struct *task;
        int rc;
        ENTRY;
 
-again:
-       /* os_lock: sync status between stop and scrub thread */
-       spin_lock(&scrub->os_lock);
-       if (thread_is_running(thread)) {
-               spin_unlock(&scrub->os_lock);
+       if (scrub->os_task)
                RETURN(-EALREADY);
-       }
-
-       if (unlikely(thread_is_stopping(thread))) {
-               spin_unlock(&scrub->os_lock);
-               l_wait_event(thread->t_ctl_waitq,
-                            thread_is_stopped(thread),
-                            &lwi);
-               goto again;
-       }
-       spin_unlock(&scrub->os_lock);
 
        if (scrub->os_file.sf_status == SS_COMPLETED) {
                if (!(flags & SS_SET_FAILOUT))
@@ -308,19 +292,25 @@ again:
                flags |= SS_RESET;
        }
 
-       scrub->os_start_flags = flags;
-       thread_set_flags(thread, 0);
-       task = kthread_run(threadfn, data, "OI_scrub");
+       task = kthread_create(threadfn, data, "OI_scrub");
        if (IS_ERR(task)) {
                rc = PTR_ERR(task);
                CERROR("%s: cannot start iteration thread: rc = %d\n",
                       scrub->os_name, rc);
                RETURN(rc);
        }
-
-       l_wait_event(thread->t_ctl_waitq,
-                    thread_is_running(thread) || thread_is_stopped(thread),
-                    &lwi);
+       spin_lock(&scrub->os_lock);
+       if (scrub->os_task) {
+               /* Lost a race */
+               spin_unlock(&scrub->os_lock);
+               kthread_stop(task);
+               RETURN(-EALREADY);
+       }
+       scrub->os_start_flags = flags;
+       scrub->os_task = task;
+       wake_up_process(task);
+       spin_unlock(&scrub->os_lock);
+       wait_var_event(scrub, scrub->os_running || !scrub->os_task);
 
        RETURN(0);
 }
@@ -328,23 +318,14 @@ EXPORT_SYMBOL(scrub_start);
 
 void scrub_stop(struct lustre_scrub *scrub)
 {
-       struct ptlrpc_thread *thread = &scrub->os_thread;
-       struct l_wait_info lwi = { 0 };
+       struct task_struct *task;
 
-       /* os_lock: sync status between stop and scrub thread */
        spin_lock(&scrub->os_lock);
-       if (!thread_is_init(thread) && !thread_is_stopped(thread)) {
-               thread_set_flags(thread, SVC_STOPPING);
-               spin_unlock(&scrub->os_lock);
-               wake_up_all(&thread->t_ctl_waitq);
-               l_wait_event(thread->t_ctl_waitq,
-                            thread_is_stopped(thread),
-                            &lwi);
-               /* Do not skip the last lock/unlock, which can guarantee that
-                * the caller cannot return until the OI scrub thread exit. */
-               spin_lock(&scrub->os_lock);
-       }
+       scrub->os_running = 0;
        spin_unlock(&scrub->os_lock);
+       task = xchg(&scrub->os_task, NULL);
+       if (task)
+               kthread_stop(task);
 }
 EXPORT_SYMBOL(scrub_stop);
 
@@ -381,7 +362,7 @@ static void scrub_bits_dump(struct seq_file *m, int bits, const char *names[],
 
        seq_printf(m, "%s:%c", prefix, bits != 0 ? ' ' : '\n');
 
-       for (i = 0, flag = 1; bits != 0; i++, flag = 1 << i) {
+       for (i = 0, flag = 1; bits != 0; i++, flag = BIT(i)) {
                if (flag & bits) {
                        bits &= ~flag;
                        seq_printf(m, "%s%c", names[i],
@@ -390,11 +371,12 @@ static void scrub_bits_dump(struct seq_file *m, int bits, const char *names[],
        }
 }
 
-static void scrub_time_dump(struct seq_file *m, __u64 time, const char *prefix)
+static void scrub_time_dump(struct seq_file *m, time64_t time,
+                           const char *prefix)
 {
        if (time != 0)
                seq_printf(m, "%s: %llu seconds\n", prefix,
-                          cfs_time_current_sec() - time);
+                          ktime_get_real_seconds() - time);
        else
                seq_printf(m, "%s: N/A\n", prefix);
 }
@@ -410,8 +392,8 @@ static void scrub_pos_dump(struct seq_file *m, __u64 pos, const char *prefix)
 void scrub_dump(struct seq_file *m, struct lustre_scrub *scrub)
 {
        struct scrub_file *sf = &scrub->os_file;
-       __u64 checked;
-       __u64 speed;
+       u64 checked;
+       s64 speed;
 
        down_read(&scrub->os_rwsem);
        seq_printf(m, "name: OI_scrub\n"
@@ -459,35 +441,42 @@ void scrub_dump(struct seq_file *m, struct lustre_scrub *scrub)
                   sf->sf_items_igif, sf->sf_success_count);
 
        speed = checked;
-       if (thread_is_running(&scrub->os_thread)) {
-               cfs_duration_t duration = cfs_time_current() -
-                                         scrub->os_time_last_checkpoint;
-               __u64 new_checked = msecs_to_jiffies(scrub->os_new_checked *
-                                                    MSEC_PER_SEC);
-               __u32 rtime = sf->sf_run_time +
-                             cfs_duration_sec(duration + HALF_SEC);
-
+       if (scrub->os_running) {
+               s64 new_checked = scrub->os_new_checked;
+               time64_t duration;
+               time64_t rtime;
+
+               /* Since the time resolution is in seconds for new system
+                * or small devices it ismore likely that duration will be
+                * zero which will lead to inaccurate results.
+                */
+               duration = ktime_get_seconds() -
+                          scrub->os_time_last_checkpoint;
                if (duration != 0)
-                       do_div(new_checked, duration);
+                       new_checked = div_s64(new_checked, duration);
+
+               rtime = sf->sf_run_time + duration;
                if (rtime != 0)
-                       do_div(speed, rtime);
-               seq_printf(m, "run_time: %u seconds\n"
-                          "average_speed: %llu objects/sec\n"
-                          "real-time_speed: %llu objects/sec\n"
+                       speed = div_s64(speed, rtime);
+
+               seq_printf(m, "run_time: %lld seconds\n"
+                          "average_speed: %lld objects/sec\n"
+                          "real_time_speed: %lld objects/sec\n"
                           "current_position: %llu\n"
                           "scrub_in_prior: %s\n"
                           "scrub_full_speed: %s\n"
                           "partial_scan: %s\n",
-                          rtime, speed, new_checked, scrub->os_pos_current,
+                          rtime, speed, new_checked,
+                          scrub->os_pos_current,
                           scrub->os_in_prior ? "yes" : "no",
                           scrub->os_full_speed ? "yes" : "no",
                           scrub->os_partial_scan ? "yes" : "no");
        } else {
                if (sf->sf_run_time != 0)
-                       do_div(speed, sf->sf_run_time);
-               seq_printf(m, "run_time: %u seconds\n"
-                          "average_speed: %llu objects/sec\n"
-                          "real-time_speed: N/A\n"
+                       speed = div_s64(speed, sf->sf_run_time);
+               seq_printf(m, "run_time: %d seconds\n"
+                          "average_speed: %lld objects/sec\n"
+                          "real_time_speed: N/A\n"
                           "current_position: N/A\n",
                           sf->sf_run_time, speed);
        }
@@ -1073,6 +1062,10 @@ int lustre_index_restore(const struct lu_env *env, struct dt_device *dev,
        if (rc)
                GOTO(stop, rc);
 
+       rc = dt_declare_ref_del(env, tgt_obj, th);
+       if (rc)
+               GOTO(stop, rc);
+
        rc = dt_declare_destroy(env, tgt_obj, th);
        if (rc)
                GOTO(stop, rc);
@@ -1086,7 +1079,12 @@ int lustre_index_restore(const struct lu_env *env, struct dt_device *dev,
                GOTO(stop, rc);
 
        dt_write_lock(env, tgt_obj, 0);
-       rc = dt_destroy(env, tgt_obj, th);
+       rc = dt_ref_del(env, tgt_obj, th);
+       if (rc == 0) {
+               if (S_ISDIR(tgt_obj->do_lu.lo_header->loh_attr))
+                       dt_ref_del(env, tgt_obj, th);
+               rc = dt_destroy(env, tgt_obj, th);
+       }
        dt_write_unlock(env, tgt_obj);
        dt_trans_stop(env, dev, th);
        if (rc)
@@ -1133,7 +1131,7 @@ int lustre_index_restore(const struct lu_env *env, struct dt_device *dev,
                GOTO(stop, rc);
 
        rc = dt_insert(env, parent_obj, (const struct dt_rec *)&ent,
-                      (const struct dt_key *)name, th, 1);
+                      (const struct dt_key *)name, th);
        dt_trans_stop(env, dev, th);
        /* Some index name may has been inserted by OSD
         * automatically when create the index object. */
@@ -1179,7 +1177,7 @@ int lustre_index_restore(const struct lu_env *env, struct dt_device *dev,
                        if (rc)
                                GOTO(stop, rc);
 
-                       rc = dt_insert(env, tgt_obj, rec, key, th, 1);
+                       rc = dt_insert(env, tgt_obj, rec, key, th);
                        if (unlikely(rc == -EEXIST))
                                rc = 0;