Update linux-zpios to use updated DMU API

The DMU API has been modified to remove the dmu_objset_open, and
dmu_objset_close functions.  Now you must explicitly *_create an
objset, then *_own it, *_disown it when not in use, and *_destroy
it when your through.  All and all I like the API much better.

Additionally, while I was here I moved the zpios_cmd_t off the
stack because previous analysis showed it was very stack heavy.
This commit is contained in:
Brian Behlendorf 2010-06-14 15:48:55 -07:00
parent 541bbe3109
commit 21690470e3
1 changed files with 65 additions and 29 deletions

View File

@ -40,7 +40,7 @@
static spl_class *zpios_class; static spl_class *zpios_class;
static spl_device *zpios_device; static spl_device *zpios_device;
static char *zpios_tag = "zpios_tag";
static static
int zpios_upcall(char *path, char *phase, run_args_t *run_args, int rc) int zpios_upcall(char *path, char *phase, run_args_t *run_args, int rc)
@ -161,26 +161,35 @@ zpios_dmu_setup(run_args_t *run_args)
{ {
zpios_time_t *t = &(run_args->stats.cr_time); zpios_time_t *t = &(run_args->stats.cr_time);
objset_t *os; objset_t *os;
char name[32];
uint64_t obj = 0ULL; uint64_t obj = 0ULL;
int i, rc = 0; int i, rc = 0, rc2;
(void)zpios_upcall(run_args->pre, PHASE_PRE_CREATE, run_args, 0); (void)zpios_upcall(run_args->pre, PHASE_PRE_CREATE, run_args, 0);
t->start = zpios_timespec_now(); t->start = zpios_timespec_now();
rc = dmu_objset_open(run_args->pool, DMU_OST_ZFS, DS_MODE_USER, &os); (void)snprintf(name, 32, "%s/id_%d", run_args->pool, run_args->id);
rc = dmu_objset_create(name, DMU_OST_OTHER, 0, NULL, NULL);
if (rc) { if (rc) {
zpios_print(run_args->file, "Error dmu_objset_open() " zpios_print(run_args->file, "Error dmu_objset_create(%s, ...) "
"failed: %d\n", rc); "failed: %d\n", name, rc);
goto out; goto out;
} }
rc = dmu_objset_own(name, DMU_OST_OTHER, 0, zpios_tag, &os);
if (rc) {
zpios_print(run_args->file, "Error dmu_objset_own(%s, ...) "
"failed: %d\n", name, rc);
goto out_destroy;
}
if (!(run_args->flags & DMU_FPP)) { if (!(run_args->flags & DMU_FPP)) {
obj = zpios_dmu_object_create(run_args, os); obj = zpios_dmu_object_create(run_args, os);
if (obj == 0) { if (obj == 0) {
rc = -EBADF; rc = -EBADF;
zpios_print(run_args->file, "Error zpios_dmu_" zpios_print(run_args->file, "Error zpios_dmu_"
"object_create() failed, %d\n", rc); "object_create() failed, %d\n", rc);
goto out; goto out_destroy;
} }
} }
@ -213,6 +222,13 @@ zpios_dmu_setup(run_args_t *run_args)
} }
run_args->os = os; run_args->os = os;
out_destroy:
if (rc) {
rc2 = dmu_objset_destroy(name, B_FALSE);
if (rc2)
zpios_print(run_args->file, "Error dmu_objset_destroy"
"(%s, ...) failed: %d\n", name, rc2);
}
out: out:
t->stop = zpios_timespec_now(); t->stop = zpios_timespec_now();
t->delta = zpios_timespec_sub(t->stop, t->start); t->delta = zpios_timespec_sub(t->stop, t->start);
@ -340,15 +356,18 @@ zpios_get_work_item(run_args_t *run_args, dmu_obj_t *obj, __u64 *offset,
} }
static void static void
zpios_remove_objects(run_args_t *run_args) zpios_remove_objset(run_args_t *run_args)
{ {
zpios_time_t *t = &(run_args->stats.rm_time); zpios_time_t *t = &(run_args->stats.rm_time);
zpios_region_t *region; zpios_region_t *region;
char name[32];
int rc = 0, i; int rc = 0, i;
(void)zpios_upcall(run_args->pre, PHASE_PRE_REMOVE, run_args, 0); (void)zpios_upcall(run_args->pre, PHASE_PRE_REMOVE, run_args, 0);
t->start = zpios_timespec_now(); t->start = zpios_timespec_now();
(void)snprintf(name, 32, "%s/id_%d", run_args->pool, run_args->id);
if (run_args->flags & DMU_REMOVE) { if (run_args->flags & DMU_REMOVE) {
if (run_args->flags & DMU_FPP) { if (run_args->flags & DMU_FPP) {
for (i = 0; i < run_args->region_count; i++) { for (i = 0; i < run_args->region_count; i++) {
@ -373,7 +392,14 @@ zpios_remove_objects(run_args_t *run_args)
} }
} }
dmu_objset_close(run_args->os); dmu_objset_disown(run_args->os, zpios_tag);
if (run_args->flags & DMU_REMOVE) {
rc = dmu_objset_destroy(name, B_FALSE);
if (rc)
zpios_print(run_args->file, "Error dmu_objset_destroy"
"(%s, ...) failed: %d\n", name, rc);
}
t->stop = zpios_timespec_now(); t->stop = zpios_timespec_now();
t->delta = zpios_timespec_sub(t->stop, t->start); t->delta = zpios_timespec_sub(t->stop, t->start);
@ -843,7 +869,7 @@ zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd,
return rc; return rc;
rc = zpios_threads_run(run_args); rc = zpios_threads_run(run_args);
zpios_remove_objects(run_args); zpios_remove_objset(run_args);
if (rc) if (rc)
goto cleanup; goto cleanup;
@ -1009,61 +1035,71 @@ zpios_ioctl_cfg(struct file *file, unsigned long arg)
static int static int
zpios_ioctl_cmd(struct file *file, unsigned long arg) zpios_ioctl_cmd(struct file *file, unsigned long arg)
{ {
zpios_cmd_t kcmd; zpios_cmd_t *kcmd;
int rc = -EINVAL;
void *data = NULL; void *data = NULL;
int rc = -EINVAL;
rc = copy_from_user(&kcmd, (zpios_cfg_t *)arg, sizeof(kcmd)); kcmd = kmem_alloc(sizeof(zpios_cmd_t), KM_SLEEP);
if (rc) { if (kcmd == NULL) {
zpios_print(file, "Unable to copy command structure " zpios_print(file, "Unable to kmem_alloc() %ld byte for "
"from user to kernel memory, %d\n", rc); "zpios_cmd_t\n", sizeof(zpios_cmd_t));
return -EFAULT;
}
if (kcmd.cmd_magic != ZPIOS_CMD_MAGIC) {
zpios_print(file, "Bad command magic 0x%x != 0x%x\n",
kcmd.cmd_magic, ZPIOS_CFG_MAGIC);
return -EINVAL;
}
/* Allocate memory for any opaque data the caller needed to pass on */
if (kcmd.cmd_data_size > 0) {
data = (void *)vmem_alloc(kcmd.cmd_data_size, KM_SLEEP);
if (data == NULL) {
zpios_print(file, "Unable to vmem_alloc() %ld "
"bytes for data buffer\n",
(long)kcmd.cmd_data_size);
return -ENOMEM; return -ENOMEM;
} }
rc = copy_from_user(kcmd, (zpios_cfg_t *)arg, sizeof(zpios_cmd_t));
if (rc) {
zpios_print(file, "Unable to copy command structure "
"from user to kernel memory, %d\n", rc);
goto out_cmd;
}
if (kcmd->cmd_magic != ZPIOS_CMD_MAGIC) {
zpios_print(file, "Bad command magic 0x%x != 0x%x\n",
kcmd->cmd_magic, ZPIOS_CFG_MAGIC);
rc = -EINVAL;
goto out_cmd;
}
/* Allocate memory for any opaque data the caller needed to pass on */
if (kcmd->cmd_data_size > 0) {
data = (void *)vmem_alloc(kcmd->cmd_data_size, KM_SLEEP);
if (data == NULL) {
zpios_print(file, "Unable to vmem_alloc() %ld "
"bytes for data buffer\n",
(long)kcmd->cmd_data_size);
rc = -ENOMEM;
goto out_cmd;
}
rc = copy_from_user(data, (void *)(arg + offsetof(zpios_cmd_t, rc = copy_from_user(data, (void *)(arg + offsetof(zpios_cmd_t,
cmd_data_str)), kcmd.cmd_data_size); cmd_data_str)), kcmd->cmd_data_size);
if (rc) { if (rc) {
zpios_print(file, "Unable to copy data buffer " zpios_print(file, "Unable to copy data buffer "
"from user to kernel memory, %d\n", rc); "from user to kernel memory, %d\n", rc);
vmem_free(data, kcmd.cmd_data_size); goto out_data;
return -EFAULT;
} }
} }
rc = zpios_do_one_run(file, &kcmd, kcmd.cmd_data_size, data); rc = zpios_do_one_run(file, kcmd, kcmd->cmd_data_size, data);
if (data != NULL) { if (data != NULL) {
/* If the test failed do not print out the stats */ /* If the test failed do not print out the stats */
if (rc) if (rc)
goto cleanup; goto out_data;
rc = copy_to_user((void *)(arg + offsetof(zpios_cmd_t, rc = copy_to_user((void *)(arg + offsetof(zpios_cmd_t,
cmd_data_str)), data, kcmd.cmd_data_size); cmd_data_str)), data, kcmd->cmd_data_size);
if (rc) { if (rc) {
zpios_print(file, "Unable to copy data buffer " zpios_print(file, "Unable to copy data buffer "
"from kernel to user memory, %d\n", rc); "from kernel to user memory, %d\n", rc);
rc = -EFAULT; rc = -EFAULT;
} }
cleanup: out_data:
vmem_free(data, kcmd.cmd_data_size); vmem_free(data, kcmd->cmd_data_size);
} }
out_cmd:
kmem_free(kcmd, sizeof(zpios_cmd_t));
return rc; return rc;
} }