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);
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);
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;
"%#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;
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);
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;
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);
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))
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);
}
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);
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],
}
}
-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);
}
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"
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);
}
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);
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)
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. */
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;