diff --git a/cmd/zpios/zpios_util.c b/cmd/zpios/zpios_util.c index c923673702..407a5522a7 100644 --- a/cmd/zpios/zpios_util.c +++ b/cmd/zpios/zpios_util.c @@ -131,13 +131,6 @@ print_flags(char *str, uint32_t flags) return str; } -static double -timespec_to_double(struct timespec t) -{ - return ((double)(t.tv_sec) + - ((double)(t.tv_nsec) / (double)(1000*1000*1000))); -} - static int regex_match(const char *string, char *pattern) { @@ -352,11 +345,11 @@ print_stats_human_readable(cmd_args_t *args, zpios_cmd_t *cmd) } summary_stats = (zpios_stats_t *)cmd->cmd_data_str; - t_time = timespec_to_double(summary_stats->total_time.delta); - wr_time = timespec_to_double(summary_stats->wr_time.delta); - rd_time = timespec_to_double(summary_stats->rd_time.delta); - cr_time = timespec_to_double(summary_stats->cr_time.delta); - rm_time = timespec_to_double(summary_stats->rm_time.delta); + t_time = zpios_timespec_to_double(summary_stats->total_time.delta); + wr_time = zpios_timespec_to_double(summary_stats->wr_time.delta); + rd_time = zpios_timespec_to_double(summary_stats->rd_time.delta); + cr_time = zpios_timespec_to_double(summary_stats->cr_time.delta); + rm_time = zpios_timespec_to_double(summary_stats->rm_time.delta); printf("%.2f\t", t_time); printf("%.3f\t", cr_time); @@ -402,24 +395,24 @@ print_stats_table(cmd_args_t *args, zpios_cmd_t *cmd) } summary_stats = (zpios_stats_t *)cmd->cmd_data_str; - wr_time = timespec_to_double(summary_stats->wr_time.delta); - rd_time = timespec_to_double(summary_stats->rd_time.delta); + wr_time = zpios_timespec_to_double(summary_stats->wr_time.delta); + rd_time = zpios_timespec_to_double(summary_stats->rd_time.delta); printf("%ld.%02ld\t", - summary_stats->total_time.delta.tv_sec, - summary_stats->total_time.delta.tv_nsec); + (long)summary_stats->total_time.delta.ts_sec, + (long)summary_stats->total_time.delta.ts_nsec); printf("%ld.%02ld\t", - summary_stats->cr_time.delta.tv_sec, - summary_stats->cr_time.delta.tv_nsec); + (long)summary_stats->cr_time.delta.ts_sec, + (long)summary_stats->cr_time.delta.ts_nsec); printf("%ld.%02ld\t", - summary_stats->rm_time.delta.tv_sec, - summary_stats->rm_time.delta.tv_nsec); + (long)summary_stats->rm_time.delta.ts_sec, + (long)summary_stats->rm_time.delta.ts_nsec); printf("%ld.%02ld\t", - summary_stats->wr_time.delta.tv_sec, - summary_stats->wr_time.delta.tv_nsec); + (long)summary_stats->wr_time.delta.ts_sec, + (long)summary_stats->wr_time.delta.ts_nsec); printf("%ld.%02ld\t", - summary_stats->rd_time.delta.tv_sec, - summary_stats->rd_time.delta.tv_nsec); + (long)summary_stats->rd_time.delta.ts_sec, + (long)summary_stats->rd_time.delta.ts_nsec); printf("%lld\t", (long long unsigned)summary_stats->wr_data); printf("%lld\t", (long long unsigned)summary_stats->wr_chunks); diff --git a/module/zpios/include/zpios-ctl.h b/module/zpios/include/zpios-ctl.h index 25a04bba01..fafa59a0c8 100644 --- a/module/zpios/include/zpios-ctl.h +++ b/module/zpios/include/zpios-ctl.h @@ -78,10 +78,15 @@ typedef struct zpios_cfg { int32_t cfg_rc1; /* Config response 1 */ } zpios_cfg_t; +typedef struct zpios_timespec { + uint32_t ts_sec; + uint32_t ts_nsec; +} zpios_timespec_t; + typedef struct zpios_time { - struct timespec start; - struct timespec stop; - struct timespec delta; + zpios_timespec_t start; + zpios_timespec_t stop; + zpios_timespec_t delta; } zpios_time_t; typedef struct zpios_stats { @@ -118,11 +123,74 @@ typedef struct zpios_cmd { } zpios_cmd_t; /* Valid ioctls */ -#define ZPIOS_CFG _IOWR('f', 101, long) -#define ZPIOS_CMD _IOWR('f', 102, long) +#define ZPIOS_CFG _IOWR('f', 101, zpios_cfg_t) +#define ZPIOS_CMD _IOWR('f', 102, zpios_cmd_t) /* Valid configuration commands */ #define ZPIOS_CFG_BUFFER_CLEAR 0x001 /* Clear text buffer */ #define ZPIOS_CFG_BUFFER_SIZE 0x002 /* Resize text buffer */ +#ifndef NSEC_PER_SEC +#define NSEC_PER_SEC 1000000000L +#endif + +static inline +void zpios_timespec_normalize(zpios_timespec_t *ts, uint32_t sec, uint32_t nsec) +{ + while (nsec >= NSEC_PER_SEC) { + nsec -= NSEC_PER_SEC; + sec++; + } + while (nsec < 0) { + nsec += NSEC_PER_SEC; + sec--; + } + ts->ts_sec = sec; + ts->ts_nsec = nsec; +} + +static inline +zpios_timespec_t zpios_timespec_add(zpios_timespec_t lhs, zpios_timespec_t rhs) +{ + zpios_timespec_t ts_delta; + zpios_timespec_normalize(&ts_delta, lhs.ts_sec + rhs.ts_sec, + lhs.ts_nsec + rhs.ts_nsec); + return ts_delta; +} + +static inline +zpios_timespec_t zpios_timespec_sub(zpios_timespec_t lhs, zpios_timespec_t rhs) +{ + zpios_timespec_t ts_delta; + zpios_timespec_normalize(&ts_delta, lhs.ts_sec - rhs.ts_sec, + lhs.ts_nsec - rhs.ts_nsec); + return ts_delta; +} + +#ifdef _KERNEL + +static inline +zpios_timespec_t zpios_timespec_now(void) +{ + zpios_timespec_t zts_now; + struct timespec ts_now; + + ts_now = current_kernel_time(); + zts_now.ts_sec = ts_now.tv_sec; + zts_now.ts_nsec = ts_now.tv_nsec; + + return zts_now; +} + +#else + +static inline +double zpios_timespec_to_double(zpios_timespec_t ts) +{ + return ((double)(ts.ts_sec) + + ((double)(ts.ts_nsec) / (double)(NSEC_PER_SEC))); +} + +#endif /* _KERNEL */ + #endif /* _ZPIOS_CTL_H */ diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index bf811c67ae..157025c50b 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -43,15 +43,6 @@ static struct class *zpios_class; -static inline -struct timespec timespec_add(struct timespec lhs, struct timespec rhs) -{ - struct timespec ts_delta; - set_normalized_timespec(&ts_delta, lhs.tv_sec + rhs.tv_sec, - lhs.tv_nsec + rhs.tv_nsec); - return ts_delta; -} - static int zpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) { @@ -175,7 +166,7 @@ zpios_dmu_setup(run_args_t *run_args) int i, rc = 0; (void)zpios_upcall(run_args->pre, PHASE_PRE_CREATE, run_args, 0); - t->start = current_kernel_time(); + t->start = zpios_timespec_now(); rc = dmu_objset_open(run_args->pool, DMU_OST_ZFS, DS_MODE_USER, &os); if (rc) { @@ -224,8 +215,8 @@ zpios_dmu_setup(run_args_t *run_args) run_args->os = os; out: - t->stop = current_kernel_time(); - t->delta = timespec_sub(t->stop, t->start); + t->stop = zpios_timespec_now(); + t->delta = zpios_timespec_sub(t->stop, t->start); (void)zpios_upcall(run_args->post, PHASE_POST_CREATE, run_args, rc); return rc; @@ -320,9 +311,9 @@ zpios_get_work_item(run_args_t *run_args, dmu_obj_t *obj, __u64 *offset, i++; count++; - if (unlikely(rw_time->stop.tv_sec == 0) && - unlikely(rw_time->stop.tv_nsec == 0)) - rw_time->stop = current_kernel_time(); + if (unlikely(rw_time->stop.ts_sec == 0) && + unlikely(rw_time->stop.ts_nsec == 0)) + rw_time->stop = zpios_timespec_now(); continue; } @@ -357,7 +348,7 @@ zpios_remove_objects(run_args_t *run_args) int rc = 0, i; (void)zpios_upcall(run_args->pre, PHASE_PRE_REMOVE, run_args, 0); - t->start = current_kernel_time(); + t->start = zpios_timespec_now(); if (run_args->flags & DMU_REMOVE) { if (run_args->flags & DMU_FPP) { @@ -385,8 +376,8 @@ zpios_remove_objects(run_args_t *run_args) dmu_objset_close(run_args->os); - t->stop = current_kernel_time(); - t->delta = timespec_sub(t->stop, t->start); + t->stop = zpios_timespec_now(); + t->delta = zpios_timespec_sub(t->stop, t->start); (void)zpios_upcall(run_args->post, PHASE_POST_REMOVE, run_args, rc); } @@ -514,7 +505,7 @@ zpios_thread_main(void *data) /* Write phase */ mutex_enter(&thr->lock); - thr->stats.wr_time.start = current_kernel_time(); + thr->stats.wr_time.start = zpios_timespec_now(); mutex_exit(&thr->lock); while (zpios_get_work_item(run_args, &obj, &offset, @@ -526,11 +517,11 @@ zpios_thread_main(void *data) schedule_timeout(thread_delay_tmp); /* In jiffies */ } - t.start = current_kernel_time(); + t.start = zpios_timespec_now(); rc = zpios_dmu_write(run_args, obj.os, obj.obj, offset, chunk_size, buf); - t.stop = current_kernel_time(); - t.delta = timespec_sub(t.stop, t.start); + t.stop = zpios_timespec_now(); + t.delta = zpios_timespec_sub(t.stop, t.start); if (rc) { zpios_print(run_args->file, "IO error while doing " @@ -541,14 +532,14 @@ zpios_thread_main(void *data) mutex_enter(&thr->lock); thr->stats.wr_data += chunk_size; thr->stats.wr_chunks++; - thr->stats.wr_time.delta = timespec_add( + thr->stats.wr_time.delta = zpios_timespec_add( thr->stats.wr_time.delta, t.delta); mutex_exit(&thr->lock); mutex_enter(®ion->lock); region->stats.wr_data += chunk_size; region->stats.wr_chunks++; - region->stats.wr_time.delta = timespec_add( + region->stats.wr_time.delta = zpios_timespec_add( region->stats.wr_time.delta, t.delta); /* First time region was accessed */ @@ -564,7 +555,7 @@ zpios_thread_main(void *data) mutex_enter(&thr->lock); thr->rc = rc; - thr->stats.wr_time.stop = current_kernel_time(); + thr->stats.wr_time.stop = zpios_timespec_now(); mutex_exit(&thr->lock); wake_up(&run_args->waitq); @@ -580,7 +571,7 @@ zpios_thread_main(void *data) /* Read phase */ mutex_enter(&thr->lock); - thr->stats.rd_time.start = current_kernel_time(); + thr->stats.rd_time.start = zpios_timespec_now(); mutex_exit(&thr->lock); while (zpios_get_work_item(run_args, &obj, &offset, @@ -595,11 +586,11 @@ zpios_thread_main(void *data) if (run_args->flags & DMU_VERIFY) memset(buf, 0, chunk_size); - t.start = current_kernel_time(); + t.start = zpios_timespec_now(); rc = zpios_dmu_read(run_args, obj.os, obj.obj, offset, chunk_size, buf); - t.stop = current_kernel_time(); - t.delta = timespec_sub(t.stop, t.start); + t.stop = zpios_timespec_now(); + t.delta = zpios_timespec_sub(t.stop, t.start); if (rc) { zpios_print(run_args->file, "IO error while doing " @@ -623,14 +614,14 @@ zpios_thread_main(void *data) mutex_enter(&thr->lock); thr->stats.rd_data += chunk_size; thr->stats.rd_chunks++; - thr->stats.rd_time.delta = timespec_add( + thr->stats.rd_time.delta = zpios_timespec_add( thr->stats.rd_time.delta, t.delta); mutex_exit(&thr->lock); mutex_enter(®ion->lock); region->stats.rd_data += chunk_size; region->stats.rd_chunks++; - region->stats.rd_time.delta = timespec_add( + region->stats.rd_time.delta = zpios_timespec_add( region->stats.rd_time.delta, t.delta); /* First time region was accessed */ @@ -646,7 +637,7 @@ zpios_thread_main(void *data) mutex_enter(&thr->lock); thr->rc = rc; - thr->stats.rd_time.stop = current_kernel_time(); + thr->stats.rd_time.stop = zpios_timespec_now(); mutex_exit(&thr->lock); wake_up(&run_args->waitq); @@ -713,7 +704,7 @@ zpios_threads_run(run_args_t *run_args) tsks[i] = tsk; } - tt->start = current_kernel_time(); + tt->start = zpios_timespec_now(); /* Wake up all threads for write phase */ (void)zpios_upcall(run_args->pre, PHASE_PRE_WRITE, run_args, 0); @@ -721,9 +712,9 @@ zpios_threads_run(run_args_t *run_args) wake_up_process(tsks[i]); /* Wait for write phase to complete */ - tw->start = current_kernel_time(); + tw->start = zpios_timespec_now(); wait_event(run_args->waitq, zpios_thread_done(run_args)); - tw->stop = current_kernel_time(); + tw->stop = zpios_timespec_now(); (void)zpios_upcall(run_args->post, PHASE_POST_WRITE, run_args, rc); for (i = 0; i < tc; i++) { @@ -762,9 +753,9 @@ zpios_threads_run(run_args_t *run_args) wake_up_process(tsks[i]); /* Wait for read phase to complete */ - tr->start = current_kernel_time(); + tr->start = zpios_timespec_now(); wait_event(run_args->waitq, zpios_thread_done(run_args)); - tr->stop = current_kernel_time(); + tr->stop = zpios_timespec_now(); (void)zpios_upcall(run_args->post, PHASE_POST_READ, run_args, rc); for (i = 0; i < tc; i++) { @@ -780,10 +771,10 @@ zpios_threads_run(run_args_t *run_args) mutex_exit(&thr->lock); } out: - tt->stop = current_kernel_time(); - tt->delta = timespec_sub(tt->stop, tt->start); - tw->delta = timespec_sub(tw->stop, tw->start); - tr->delta = timespec_sub(tr->stop, tr->start); + tt->stop = zpios_timespec_now(); + tt->delta = zpios_timespec_sub(tt->stop, tt->start); + tw->delta = zpios_timespec_sub(tw->stop, tw->start); + tr->delta = zpios_timespec_sub(tr->stop, tr->start); cleanup: kmem_free(tsks, sizeof(struct task_struct *) * tc); @@ -1082,7 +1073,7 @@ static int zpios_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(inode); int rc = 0; /* Ignore tty ioctls */ @@ -1108,6 +1099,15 @@ zpios_ioctl(struct inode *inode, struct file *file, return rc; } +#ifdef CONFIG_COMPAT +/* Compatibility handler for ioctls from 32-bit ELF binaries */ +static long +zpios_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return zpios_ioctl(file->f_dentry->d_inode, file, cmd, arg); +} +#endif /* CONFIG_COMPAT */ + /* I'm not sure why you would want to write in to this buffer from * user space since its principle use is to pass test status info * back to the user space, but I don't see any reason to prevent it. @@ -1223,13 +1223,16 @@ static loff_t zpios_seek(struct file *file, loff_t offset, int origin) } static struct file_operations zpios_fops = { - .owner = THIS_MODULE, - .open = zpios_open, - .release = zpios_release, - .ioctl = zpios_ioctl, - .read = zpios_read, - .write = zpios_write, - .llseek = zpios_seek, + .owner = THIS_MODULE, + .open = zpios_open, + .release = zpios_release, + .ioctl = zpios_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = zpios_compat_ioctl, +#endif + .read = zpios_read, + .write = zpios_write, + .llseek = zpios_seek, }; static struct cdev zpios_cdev = {