diff options
-rw-r--r-- | lib/libzfs/libzfs_diff.c | 2 | ||||
-rw-r--r-- | lib/libzfs/libzfs_sendrecv.c | 4 | ||||
-rw-r--r-- | module/zfs/include/sys/zfs_ioctl.h | 32 | ||||
-rw-r--r-- | module/zfs/zfs_ioctl.c | 430 | ||||
-rw-r--r-- | module/zfs/zfs_onexit.c | 11 | ||||
-rw-r--r-- | scripts/common.sh | 443 | ||||
-rw-r--r-- | scripts/common.sh.in | 69 | ||||
-rwxr-xr-x | scripts/zconfig.sh | 50 |
8 files changed, 791 insertions, 250 deletions
diff --git a/lib/libzfs/libzfs_diff.c b/lib/libzfs/libzfs_diff.c index 5b3f93465..31e18aad2 100644 --- a/lib/libzfs/libzfs_diff.c +++ b/lib/libzfs/libzfs_diff.c @@ -726,7 +726,7 @@ setup_differ_info(zfs_handle_t *zhp, const char *fromsnap, { di->zhp = zhp; - di->cleanupfd = open(ZFS_DEV, O_RDWR|O_EXCL); + di->cleanupfd = open(ZFS_DEV, O_RDWR); VERIFY(di->cleanupfd >= 0); if (get_snapshot_names(di, fromsnap, tosnap) != 0) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 95c4b3568..48e77178f 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -1413,7 +1413,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, ++holdseq; (void) snprintf(sdd.holdtag, sizeof (sdd.holdtag), ".send-%d-%llu", getpid(), (u_longlong_t)holdseq); - sdd.cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL); + sdd.cleanup_fd = open(ZFS_DEV, O_RDWR); if (sdd.cleanup_fd < 0) { err = errno; goto stderr_out; @@ -2988,7 +2988,7 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags, int cleanup_fd; uint64_t action_handle = 0; - cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL); + cleanup_fd = open(ZFS_DEV, O_RDWR); VERIFY(cleanup_fd >= 0); err = zfs_receive_impl(hdl, tosnap, flags, infd, NULL, NULL, diff --git a/module/zfs/include/sys/zfs_ioctl.h b/module/zfs/include/sys/zfs_ioctl.h index ad41561ad..4a21cc8e0 100644 --- a/module/zfs/include/sys/zfs_ioctl.h +++ b/module/zfs/include/sys/zfs_ioctl.h @@ -312,8 +312,6 @@ typedef struct zfs_creat { nvlist_t *zct_props; } zfs_creat_t; -extern dev_info_t *zfs_dip; - extern int zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr); extern int zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr); @@ -321,28 +319,24 @@ extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr); extern int zfs_busy(void); extern int zfs_unmount_snap(const char *, void *); -/* - * ZFS minor numbers can refer to either a control device instance or - * a zvol. Depending on the value of zss_type, zss_data points to either - * a zvol_state_t or a zfs_onexit_t. - */ -enum zfs_soft_state_type { - ZSST_ZVOL, - ZSST_CTLDEV +enum zfsdev_state_type { + ZST_ONEXIT, + ZST_ZEVENT, + ZST_ALL, }; -typedef struct zfs_soft_state { - enum zfs_soft_state_type zss_type; - void *zss_data; -} zfs_soft_state_t; +typedef struct zfsdev_state { + list_node_t zs_next; /* next zfsdev_state_t link */ + struct file *zs_file; /* associated file struct */ + minor_t zs_minor; /* made up minor number */ + void *zs_onexit; /* onexit data */ + void *zs_zevent; /* zevent data */ +} zfsdev_state_t; -extern void *zfsdev_get_soft_state(minor_t minor, - enum zfs_soft_state_type which); +extern void *zfsdev_get_state(minor_t minor, enum zfsdev_state_type which); +extern minor_t zfsdev_getminor(struct file *filp); extern minor_t zfsdev_minor_alloc(void); -extern void *zfsdev_state; -extern kmutex_t zfsdev_state_lock; - #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 2302c0f3c..99287e443 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -65,20 +65,21 @@ #include <sys/dsl_scan.h> #include <sharefs/share.h> #include <sys/dmu_objset.h> +#include <sys/fm/util.h> + +#include <linux/miscdevice.h> #include "zfs_namecheck.h" #include "zfs_prop.h" #include "zfs_deleg.h" #include "zfs_comutil.h" -extern struct modlfs zfs_modlfs; +kmutex_t zfsdev_state_lock; +list_t zfsdev_state_list; extern void zfs_init(void); extern void zfs_fini(void); -ldi_ident_t zfs_li = NULL; -dev_info_t *zfs_dip; - typedef int zfs_ioc_func_t(zfs_cmd_t *); typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); @@ -591,6 +592,7 @@ zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) return (error); } +#ifdef HAVE_ZPL static int zfs_secpolicy_deleg_share(zfs_cmd_t *zc, cred_t *cr) { @@ -614,10 +616,12 @@ zfs_secpolicy_deleg_share(zfs_cmd_t *zc, cred_t *cr) return (dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_SHARE, cr)); } +#endif /* HAVE_ZPL */ int zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) { +#ifdef HAVE_ZPL if (!INGLOBALZONE(curproc)) return (EPERM); @@ -626,11 +630,15 @@ zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) } else { return (zfs_secpolicy_deleg_share(zc, cr)); } +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } int zfs_secpolicy_smb_acl(zfs_cmd_t *zc, cred_t *cr) { +#ifdef HAVE_ZPL if (!INGLOBALZONE(curproc)) return (EPERM); @@ -639,6 +647,9 @@ zfs_secpolicy_smb_acl(zfs_cmd_t *zc, cred_t *cr) } else { return (zfs_secpolicy_deleg_share(zc, cr)); } +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } static int @@ -839,6 +850,7 @@ zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) return (error); } +#ifdef HAVE_ZPL static int zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) { @@ -850,6 +862,7 @@ zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) } return (error); } +#endif /* HAVE_ZPL */ /* * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires @@ -1093,6 +1106,7 @@ put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) return (error); } +#ifdef HAVE_ZPL static int getzfsvfs(const char *dsname, zfsvfs_t **zfvp) { @@ -1118,6 +1132,7 @@ getzfsvfs(const char *dsname, zfsvfs_t **zfvp) dmu_objset_rele(os, FTAG); return (error); } +#endif /* * Find a zfsvfs_t for a mounted filesystem, or create our own, in which @@ -1126,6 +1141,7 @@ getzfsvfs(const char *dsname, zfsvfs_t **zfvp) static int zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer) { +#ifdef HAVE_ZPL int error = 0; if (getzfsvfs(name, zfvp) != 0) @@ -1144,11 +1160,15 @@ zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer) } } return (error); +#else + return ENOTSUP; +#endif } static void zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag) { +#ifdef HAVE_ZPL rrw_exit(&zfsvfs->z_teardown_lock, tag); if (zfsvfs->z_vfs) { @@ -1157,6 +1177,7 @@ zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag) dmu_objset_disown(zfsvfs->z_os, zfsvfs); zfsvfs_free(zfsvfs); } +#endif } static int @@ -2063,6 +2084,7 @@ top: static int zfs_prop_set_userquota(const char *dsname, nvpair_t *pair) { +#ifdef HAVE_ZPL const char *propname = nvpair_name(pair); uint64_t *valary; unsigned int vallen; @@ -2103,6 +2125,9 @@ zfs_prop_set_userquota(const char *dsname, nvpair_t *pair) } return (err); +#else + return ENOTSUP; +#endif } /* @@ -2164,7 +2189,9 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source, if ((err = zfsvfs_hold(dsname, FTAG, &zfsvfs, B_TRUE)) != 0) break; +#ifdef HAVE_ZPL err = zfs_set_version(zfsvfs, intval); +#endif zfsvfs_rele(zfsvfs, FTAG); if (err == 0 && intval >= ZPL_VERSION_USERSPACE) { @@ -2696,6 +2723,7 @@ zfs_ioc_get_fsacl(zfs_cmd_t *zc) return (error); } +#ifdef HAVE_ZPL /* * Search the vfs list for a specified resource. Returns a pointer to it * or NULL if no suitable entry is found. The caller of this routine @@ -2720,6 +2748,7 @@ zfs_get_vfs(const char *resource) vfs_list_unlock(); return (vfs_found); } +#endif /* HAVE_ZPL */ /* ARGSUSED */ static void @@ -3074,6 +3103,7 @@ out: int zfs_unmount_snap(const char *name, void *arg) { +#ifdef HAVE_ZPL vfs_t *vfsp = NULL; if (arg) { @@ -3100,6 +3130,7 @@ zfs_unmount_snap(const char *name, void *arg) if ((err = dounmount(vfsp, flag, kcred)) != 0) return (err); } +#endif /* HAVE_ZPL */ return (0); } @@ -3159,6 +3190,7 @@ zfs_ioc_destroy(zfs_cmd_t *zc) static int zfs_ioc_rollback(zfs_cmd_t *zc) { +#ifdef HAVE_ZPL dsl_dataset_t *ds, *clone; int error; zfsvfs_t *zfsvfs; @@ -3232,6 +3264,9 @@ out: if (ds) dsl_dataset_rele(ds, FTAG); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -3675,6 +3710,7 @@ zfs_ioc_recv(zfs_cmd_t *zc) &zc->zc_action_handle); if (error == 0) { +#ifdef HAVE_ZPL zfsvfs_t *zfsvfs = NULL; if (getzfsvfs(tofs, &zfsvfs) == 0) { @@ -3694,6 +3730,9 @@ zfs_ioc_recv(zfs_cmd_t *zc) } else { error = dmu_recv_end(&drc); } +#else + error = dmu_recv_end(&drc); +#endif /* HAVE_ZPL */ } zc->zc_cookie = off - fp->f_offset; @@ -4017,6 +4056,7 @@ zfs_ioc_promote(zfs_cmd_t *zc) static int zfs_ioc_userspace_one(zfs_cmd_t *zc) { +#ifdef HAVE_ZPL zfsvfs_t *zfsvfs; int error; @@ -4032,6 +4072,9 @@ zfs_ioc_userspace_one(zfs_cmd_t *zc) zfsvfs_rele(zfsvfs, FTAG); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -4048,6 +4091,7 @@ zfs_ioc_userspace_one(zfs_cmd_t *zc) static int zfs_ioc_userspace_many(zfs_cmd_t *zc) { +#ifdef HAVE_ZPL zfsvfs_t *zfsvfs; int bufsize = zc->zc_nvlist_dst_size; @@ -4072,6 +4116,9 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc) zfsvfs_rele(zfsvfs, FTAG); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -4084,6 +4131,7 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc) static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc) { +#ifdef HAVE_ZPL objset_t *os; int error = 0; zfsvfs_t *zfsvfs; @@ -4113,6 +4161,9 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc) } return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -4122,6 +4173,7 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc) * the first file system is shared. * Neither sharefs, nfs or smbsrv are unloadable modules. */ +#ifdef HAVE_ZPL int (*znfsexport_fs)(void *arg); int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); int (*zsmbexport_fs)(void *arg, boolean_t add_share); @@ -4153,10 +4205,12 @@ zfs_init_sharefs() } return (0); } +#endif /* HAVE_ZPL */ static int zfs_ioc_share(zfs_cmd_t *zc) { +#ifdef HAVE_ZPL int error; int opcode; @@ -4246,7 +4300,9 @@ zfs_ioc_share(zfs_cmd_t *zc) zc->zc_share.z_sharemax); return (error); - +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } ace_t full_access[] = { @@ -4363,6 +4419,7 @@ zfs_ioc_diff(zfs_cmd_t *zc) /* * Remove all ACL files in shares dir */ +#ifdef HAVE_ZPL static int zfs_smb_acl_purge(znode_t *dzp) { @@ -4381,10 +4438,12 @@ zfs_smb_acl_purge(znode_t *dzp) zap_cursor_fini(&zc); return (error); } +#endif /* HAVE ZPL */ static int zfs_ioc_smb_acl(zfs_cmd_t *zc) { +#ifdef HAVE_ZPL vnode_t *vp; znode_t *dzp; vnode_t *resourcevp = NULL; @@ -4507,6 +4566,9 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc) ZFS_EXIT(zfsvfs); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -4842,13 +4904,56 @@ pool_status_check(const char *name, zfs_ioc_namecheck_t type, return (error); } +static void * +zfsdev_get_state_impl(minor_t minor, enum zfsdev_state_type which) +{ + zfsdev_state_t *zs; + + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); + + for (zs = list_head(&zfsdev_state_list); zs != NULL; + zs = list_next(&zfsdev_state_list, zs)) { + if (zs->zs_minor == minor) { + switch (which) { + case ZST_ONEXIT: return (zs->zs_onexit); + case ZST_ZEVENT: return (zs->zs_zevent); + case ZST_ALL: return (zs); + } + } + } + + return NULL; +} + +void * +zfsdev_get_state(minor_t minor, enum zfsdev_state_type which) +{ + void *ptr; + + mutex_enter(&zfsdev_state_lock); + ptr = zfsdev_get_state_impl(minor, which); + mutex_exit(&zfsdev_state_lock); + + return ptr; +} + +minor_t +zfsdev_getminor(struct file *filp) +{ + ASSERT(filp != NULL); + ASSERT(filp->private_data != NULL); + + return (((zfsdev_state_t *)filp->private_data)->zs_minor); +} + /* - * Find a free minor number. + * Find a free minor number. The zfsdev_state_list is expected to + * be short since it is only a list of currently open file handles. */ minor_t zfsdev_minor_alloc(void) { - static minor_t last_minor; + static minor_t last_minor = 0; minor_t m; ASSERT(MUTEX_HELD(&zfsdev_state_lock)); @@ -4856,7 +4961,7 @@ zfsdev_minor_alloc(void) for (m = last_minor + 1; m != last_minor; m++) { if (m > ZFSDEV_MAX_MINOR) m = 1; - if (ddi_get_soft_state(zfsdev_state, m) == NULL) { + if (zfsdev_get_state_impl(m, ZST_ALL) == NULL) { last_minor = m; return (m); } @@ -4866,107 +4971,85 @@ zfsdev_minor_alloc(void) } static int -zfs_ctldev_init(dev_t *devp) +zfsdev_state_init(struct file *filp) { + zfsdev_state_t *zs; minor_t minor; - zfs_soft_state_t *zs; ASSERT(MUTEX_HELD(&zfsdev_state_lock)); - ASSERT(getminor(*devp) == 0); - minor = zfsdev_minor_alloc(); - if (minor == 0) - return (ENXIO); + minor = zfsdev_minor_alloc(); + if (minor == 0) + return (ENXIO); + + zs = kmem_zalloc( sizeof(zfsdev_state_t), KM_SLEEP); + if (zs == NULL) + return (ENOMEM); - if (ddi_soft_state_zalloc(zfsdev_state, minor) != DDI_SUCCESS) - return (EAGAIN); + zs->zs_file = filp; + zs->zs_minor = minor; + filp->private_data = zs; - *devp = makedevice(getemajor(*devp), minor); + zfs_onexit_init((zfs_onexit_t **)&zs->zs_onexit); + zfs_zevent_init((zfs_zevent_t **)&zs->zs_zevent); - zs = ddi_get_soft_state(zfsdev_state, minor); - zs->zss_type = ZSST_CTLDEV; - zfs_onexit_init((zfs_onexit_t **)&zs->zss_data); + list_insert_tail(&zfsdev_state_list, zs); return (0); } -static void -zfs_ctldev_destroy(zfs_onexit_t *zo, minor_t minor) +static int +zfsdev_state_destroy(struct file *filp) { - ASSERT(MUTEX_HELD(&zfsdev_state_lock)); + zfsdev_state_t *zs; - zfs_onexit_destroy(zo); - ddi_soft_state_free(zfsdev_state, minor); -} + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); + ASSERT(filp->private_data != NULL); -void * -zfsdev_get_soft_state(minor_t minor, enum zfs_soft_state_type which) -{ - zfs_soft_state_t *zp; + zs = filp->private_data; + zfs_onexit_destroy(zs->zs_onexit); + zfs_zevent_destroy(zs->zs_zevent); - zp = ddi_get_soft_state(zfsdev_state, minor); - if (zp == NULL || zp->zss_type != which) - return (NULL); + list_remove(&zfsdev_state_list, zs); + kmem_free(zs, sizeof(zfsdev_state_t)); - return (zp->zss_data); + return 0; } static int -zfsdev_open(dev_t *devp, int flag, int otyp, cred_t *cr) +zfsdev_open(struct inode *ino, struct file *filp) { - int error = 0; - - if (getminor(*devp) != 0) - return (zvol_open(devp, flag, otyp, cr)); + int error; - /* This is the control device. Allocate a new minor if requested. */ - if (flag & FEXCL) { - mutex_enter(&zfsdev_state_lock); - error = zfs_ctldev_init(devp); - mutex_exit(&zfsdev_state_lock); - } + mutex_enter(&zfsdev_state_lock); + error = zfsdev_state_init(filp); + mutex_exit(&zfsdev_state_lock); - return (error); + return (-error); } static int -zfsdev_close(dev_t dev, int flag, int otyp, cred_t *cr) +zfsdev_release(struct inode *ino, struct file *filp) { - zfs_onexit_t *zo; - minor_t minor = getminor(dev); - - if (minor == 0) - return (0); + int error; mutex_enter(&zfsdev_state_lock); - zo = zfsdev_get_soft_state(minor, ZSST_CTLDEV); - if (zo == NULL) { - mutex_exit(&zfsdev_state_lock); - return (zvol_close(dev, flag, otyp, cr)); - } - zfs_ctldev_destroy(zo, minor); + error = zfsdev_state_destroy(filp); mutex_exit(&zfsdev_state_lock); - return (0); + return (-error); } -static int -zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) +static long +zfsdev_ioctl(struct file *filp, unsigned cmd, unsigned long arg) { zfs_cmd_t *zc; uint_t vec; - int error, rc; - minor_t minor = getminor(dev); - - if (minor != 0 && - zfsdev_get_soft_state(minor, ZSST_CTLDEV) == NULL) - return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); + int error, rc, flag = 0; vec = cmd - ZFS_IOC; - ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); - if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) - return (EINVAL); + return (-EINVAL); zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); @@ -4975,7 +5058,7 @@ zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) error = EFAULT; if ((error == 0) && !(flag & FKIOCTL)) - error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); + error = zfs_ioc_vec[vec].zvec_secpolicy(zc, NULL); /* * Ensure that all pool/dataset names are valid before we pass down to @@ -5018,121 +5101,74 @@ zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) } kmem_free(zc, sizeof (zfs_cmd_t)); - return (error); + return (-error); } -static int -zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) +#ifdef CONFIG_COMPAT +static long +zfsdev_compat_ioctl(struct file *filp, unsigned cmd, unsigned long arg) { - if (cmd != DDI_ATTACH) - return (DDI_FAILURE); - - if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, - DDI_PSEUDO, 0) == DDI_FAILURE) - return (DDI_FAILURE); - - zfs_dip = dip; + return zfsdev_ioctl(filp, cmd, arg); +} +#else +#define zfs_compat_ioctl NULL +#endif - ddi_report_dev(dip); +static const struct file_operations zfsdev_fops = { + .open = zfsdev_open, + .release = zfsdev_release, + .unlocked_ioctl = zfsdev_ioctl, + .compat_ioctl = zfsdev_compat_ioctl, + .owner = THIS_MODULE, +}; - return (DDI_SUCCESS); -} +static struct miscdevice zfs_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = ZFS_DRIVER, + .fops = &zfsdev_fops, +}; static int -zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) +zfs_attach(void) { - if (spa_busy() || zfs_busy() || zvol_busy()) - return (DDI_FAILURE); - - if (cmd != DDI_DETACH) - return (DDI_FAILURE); + int error; - zfs_dip = NULL; + mutex_init(&zfsdev_state_lock, NULL, MUTEX_DEFAULT, NULL); + list_create(&zfsdev_state_list, sizeof (zfsdev_state_t), + offsetof(zfsdev_state_t, zs_next)); - ddi_prop_remove_all(dip); - ddi_remove_minor_node(dip, NULL); + error = misc_register(&zfs_misc); + if (error) { + printk(KERN_INFO "ZFS: misc_register() failed %d\n", error); + return (error); + } - return (DDI_SUCCESS); + return (0); } -/*ARGSUSED*/ -static int -zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) +static void +zfs_detach(void) { - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - *result = zfs_dip; - return (DDI_SUCCESS); + int error; - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)0; - return (DDI_SUCCESS); - } + error = misc_deregister(&zfs_misc); + if (error) + printk(KERN_INFO "ZFS: misc_deregister() failed %d\n", error); - return (DDI_FAILURE); + mutex_destroy(&zfsdev_state_lock); + list_destroy(&zfsdev_state_list); } -/* - * OK, so this is a little weird. - * - * /dev/zfs is the control node, i.e. minor 0. - * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. - * - * /dev/zfs has basically nothing to do except serve up ioctls, - * so most of the standard driver entry points are in zvol.c. - */ -static struct cb_ops zfs_cb_ops = { - zfsdev_open, /* open */ - zfsdev_close, /* close */ - zvol_strategy, /* strategy */ - nodev, /* print */ - zvol_dump, /* dump */ - zvol_read, /* read */ - zvol_write, /* write */ - zfsdev_ioctl, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, /* prop_op */ - NULL, /* streamtab */ - D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ - CB_REV, /* version */ - nodev, /* async read */ - nodev, /* async write */ -}; - -static struct dev_ops zfs_dev_ops = { - DEVO_REV, /* version */ - 0, /* refcnt */ - zfs_info, /* info */ - nulldev, /* identify */ - nulldev, /* probe */ - zfs_attach, /* attach */ - zfs_detach, /* detach */ - nodev, /* reset */ - &zfs_cb_ops, /* driver operations */ - NULL, /* no bus operations */ - NULL, /* power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - -static struct modldrv zfs_modldrv = { - &mod_driverops, - "ZFS storage pool", - &zfs_dev_ops -}; - -static struct modlinkage modlinkage = { - MODREV_1, - (void *)&zfs_modlfs, - (void *)&zfs_modldrv, - NULL -}; - - +#ifdef HAVE_ZPL uint_t zfs_fsyncer_key; extern uint_t rrw_tsd_key; +#endif + +#ifdef DEBUG +#define ZFS_DEBUG_STR " (DEBUG mode)" +#else +#define ZFS_DEBUG_STR "" +#endif int _init(void) @@ -5141,39 +5177,44 @@ _init(void) spa_init(FREAD | FWRITE); zfs_init(); - zvol_init(); - if ((error = mod_install(&modlinkage)) != 0) { - zvol_fini(); - zfs_fini(); - spa_fini(); - return (error); - } + if ((error = zvol_init()) != 0) + goto out1; + + if ((error = zfs_attach()) != 0) + goto out2; +#ifdef HAVE_ZPL tsd_create(&zfs_fsyncer_key, NULL); tsd_create(&rrw_tsd_key, NULL); - error = ldi_ident_from_mod(&modlinkage, &zfs_li); - ASSERT(error == 0); mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); +#endif /* HAVE_ZPL */ + + printk(KERN_NOTICE "ZFS: Loaded ZFS Filesystem v%s%s\n", + ZFS_META_VERSION, ZFS_DEBUG_STR); return (0); + +out2: + (void) zvol_fini(); +out1: + zfs_fini(); + spa_fini(); + printk(KERN_NOTICE "ZFS: Failed to Load ZFS Filesystem v%s%s" + ", rc = %d\n", ZFS_META_VERSION, ZFS_DEBUG_STR, error); + + return (error); } int _fini(void) { - int error; - - if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) - return (EBUSY); - - if ((error = mod_remove(&modlinkage)) != 0) - return (error); - + zfs_detach(); zvol_fini(); zfs_fini(); spa_fini(); +#ifdef HAVE_ZPL if (zfs_nfsshare_inited) (void) ddi_modclose(nfs_mod); if (zfs_smbshare_inited) @@ -5181,16 +5222,21 @@ _fini(void) if (zfs_nfsshare_inited || zfs_smbshare_inited) (void) ddi_modclose(sharefs_mod); - tsd_destroy(&zfs_fsyncer_key); - ldi_ident_release(zfs_li); - zfs_li = NULL; mutex_destroy(&zfs_share_lock); + tsd_destroy(&zfs_fsyncer_key); +#endif /* HAVE_ZPL */ - return (error); -} + printk(KERN_NOTICE "ZFS: Unloaded ZFS Filesystem v%s%s\n", + ZFS_META_VERSION, ZFS_DEBUG_STR); -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); + return (0); } + +#ifdef HAVE_SPL +spl_module_init(_init); +spl_module_exit(_fini); + +MODULE_DESCRIPTION("ZFS"); +MODULE_AUTHOR(ZFS_META_AUTHOR); +MODULE_LICENSE(ZFS_META_LICENSE); +#endif /* HAVE_SPL */ diff --git a/module/zfs/zfs_onexit.c b/module/zfs/zfs_onexit.c index 9706de2b4..2f60b5e4d 100644 --- a/module/zfs/zfs_onexit.c +++ b/module/zfs/zfs_onexit.c @@ -42,9 +42,10 @@ * * These cleanup callbacks are intended to allow for the accumulation * of kernel state across multiple ioctls. User processes participate - * by opening ZFS_DEV with O_EXCL. This causes the ZFS driver to do a - * clone-open, generating a unique minor number. The process then passes - * along that file descriptor to each ioctl that might have a cleanup operation. + * simply by opening ZFS_DEV. This causes the ZFS driver to do create + * some private data for the file descriptor and generating a unique + * minor number. The process then passes along that file descriptor to + * each ioctl that might have a cleanup operation. * * Consumers of the onexit routines should call zfs_onexit_fd_hold() early * on to validate the given fd and add a reference to its file table entry. @@ -106,7 +107,7 @@ zfs_onexit_destroy(zfs_onexit_t *zo) static int zfs_onexit_minor_to_state(minor_t minor, zfs_onexit_t **zo) { - *zo = zfsdev_get_soft_state(minor, ZSST_CTLDEV); + *zo = zfsdev_get_state(minor, ZST_ONEXIT); if (*zo == NULL) return (EBADF); @@ -129,7 +130,7 @@ zfs_onexit_fd_hold(int fd, minor_t *minorp) if (fp == NULL) return (EBADF); - *minorp = getminor(fp->f_vnode->v_rdev); + *minorp = zfsdev_getminor(fp->f_file); return (zfs_onexit_minor_to_state(*minorp, &zo)); } diff --git a/scripts/common.sh b/scripts/common.sh new file mode 100644 index 000000000..66097570d --- /dev/null +++ b/scripts/common.sh @@ -0,0 +1,443 @@ +#!/bin/bash +# +# Common support functions for testing scripts. If a .script-config +# files is available it will be sourced so in-tree kernel modules and +# utilities will be used. If no .script-config can be found then the +# installed kernel modules and utilities will be used. + +basedir="$(dirname $0)" + +SCRIPT_CONFIG=.script-config +if [ -f "${basedir}/../${SCRIPT_CONFIG}" ]; then +. "${basedir}/../${SCRIPT_CONFIG}" +else +MODULES=(zlib_deflate spl splat zavl znvpair zunicode zcommon zfs) +fi + +PROG="<define PROG>" +CLEANUP= +VERBOSE= +VERBOSE_FLAG= +FORCE= +FORCE_FLAG= +DUMP_LOG= +ERROR= +RAID0S=() +RAID10S=() +RAIDZS=() +RAIDZ2S=() +TESTS_RUN=${TESTS_RUN:-'*'} +TESTS_SKIP=${TESTS_SKIP:-} + +prefix=/usr/local +exec_prefix=${prefix} +libexecdir=${exec_prefix}/libexec +pkglibexecdir=${libexecdir}/zfs +bindir=${exec_prefix}/bin +sbindir=${exec_prefix}/sbin + +ETCDIR=${ETCDIR:-/etc} +DEVDIR=${DEVDIR:-/dev/disk/zpool} +ZPOOLDIR=${ZPOOLDIR:-${pkglibexecdir}/zpool-config} +ZPIOSDIR=${ZPIOSDIR:-${pkglibexecdir}/zpios-test} +ZPIOSPROFILEDIR=${ZPIOSPROFILEDIR:-${pkglibexecdir}/zpios-profile} + +ZDB=${ZDB:-${sbindir}/zdb} +ZFS=${ZFS:-${sbindir}/zfs} +ZINJECT=${ZINJECT:-${sbindir}/zinject} +ZPOOL=${ZPOOL:-${sbindir}/zpool} +ZPOOL_ID=${ZPOOL_ID:-${bindir}/zpool_id} +ZTEST=${ZTEST:-${sbindir}/ztest} +ZPIOS=${ZPIOS:-${sbindir}/zpios} + +COMMON_SH=${COMMON_SH:-${pkglibexecdir}/common.sh} +ZFS_SH=${ZFS_SH:-${pkglibexecdir}/zfs.sh} +ZPOOL_CREATE_SH=${ZPOOL_CREATE_SH:-${pkglibexecdir}/zpool-create.sh} +ZPIOS_SH=${ZPIOS_SH:-${pkglibexecdir}/zpios.sh} +ZPIOS_SURVEY_SH=${ZPIOS_SURVEY_SH:-${pkglibexecdir}/zpios-survey.sh} + +LDMOD=${LDMOD:-/sbin/modprobe} +LSMOD=${LSMOD:-/sbin/lsmod} +RMMOD=${RMMOD:-/sbin/rmmod} +INFOMOD=${INFOMOD:-/sbin/modinfo} +LOSETUP=${LOSETUP:-/sbin/losetup} +SYSCTL=${SYSCTL:-/sbin/sysctl} +UDEVADM=${UDEVADM:-/sbin/udevadm} +AWK=${AWK:-/usr/bin/awk} + +COLOR_BLACK="\033[0;30m" +COLOR_DK_GRAY="\033[1;30m" +COLOR_BLUE="\033[0;34m" +COLOR_LT_BLUE="\033[1;34m" +COLOR_GREEN="\033[0;32m" +COLOR_LT_GREEN="\033[1;32m" +COLOR_CYAN="\033[0;36m" +COLOR_LT_CYAN="\033[1;36m" +COLOR_RED="\033[0;31m" +COLOR_LT_RED="\033[1;31m" +COLOR_PURPLE="\033[0;35m" +COLOR_LT_PURPLE="\033[1;35m" +COLOR_BROWN="\033[0;33m" +COLOR_YELLOW="\033[1;33m" +COLOR_LT_GRAY="\033[0;37m" +COLOR_WHITE="\033[1;37m" +COLOR_RESET="\033[0m" + +die() { + echo -e "${PROG}: $1" >&2 + exit 1 +} + +msg() { + if [ ${VERBOSE} ]; then + echo "$@" + fi +} + +pass() { + echo -e "${COLOR_GREEN}Pass${COLOR_RESET}" +} + +fail() { + echo -e "${COLOR_RED}Fail${COLOR_RESET} ($1)" + exit $1 +} + +skip() { + echo -e "${COLOR_BROWN}Skip${COLOR_RESET}" +} + +spl_dump_log() { + ${SYSCTL} -w kernel.spl.debug.dump=1 &>/dev/null + local NAME=`dmesg | tail -n 1 | cut -f5 -d' '` + ${SPLBUILD}/cmd/spl ${NAME} >${NAME}.log + echo + echo "Dumped debug log: ${NAME}.log" + tail -n1 ${NAME}.log + echo + return 0 +} + +check_modules() { + local LOADED_MODULES=() + local MISSING_MODULES=() + + for MOD in ${MODULES[*]}; do + local NAME=`basename $MOD .ko` + + if ${LSMOD} | egrep -q "^${NAME}"; then + LOADED_MODULES=(${NAME} ${LOADED_MODULES[*]}) + fi + + if [ ${INFOMOD} ${MOD} 2>/dev/null ]; then + MISSING_MODULES=("\t${MOD}\n" ${MISSING_MODULES[*]}) + fi + done + + if [ ${#LOADED_MODULES[*]} -gt 0 ]; then + ERROR="Unload these modules with '${PROG} -u':\n" + ERROR="${ERROR}${LOADED_MODULES[*]}" + return 1 + fi + + if [ ${#MISSING_MODULES[*]} -gt 0 ]; then + ERROR="The following modules can not be found," + ERROR="${ERROR} ensure your source trees are built:\n" + ERROR="${ERROR}${MISSING_MODULES[*]}" + return 1 + fi + + return 0 +} + +load_module() { + local NAME=`basename $1 .ko` + + if [ ${VERBOSE} ]; then + echo "Loading ${NAME} ($@)" + fi + + ${LDMOD} $* || ERROR="Failed to load $1" return 1 + + return 0 +} + +load_modules() { + mkdir -p /etc/zfs + + for MOD in ${MODULES[*]}; do + local NAME=`basename ${MOD} .ko` + local VALUE= + + for OPT in "$@"; do + OPT_NAME=`echo ${OPT} | cut -f1 -d'='` + + if [ ${NAME} = "${OPT_NAME}" ]; then + VALUE=`echo ${OPT} | cut -f2- -d'='` + fi + done + + load_module ${MOD} ${VALUE} || return 1 + done + + if [ ${VERBOSE} ]; then + echo "Successfully loaded ZFS module stack" + fi + + return 0 +} + +unload_module() { + local NAME=`basename $1 .ko` + + if [ ${VERBOSE} ]; then + echo "Unloading ${NAME} ($@)" + fi + + ${RMMOD} ${NAME} || ERROR="Failed to unload ${NAME}" return 1 + + return 0 +} + +unload_modules() { + local MODULES_REVERSE=( $(echo ${MODULES[@]} | + ${AWK} '{for (i=NF;i>=1;i--) printf $i" "} END{print ""}') ) + + for MOD in ${MODULES_REVERSE[*]}; do + local NAME=`basename ${MOD} .ko` + local USE_COUNT=`${LSMOD} | + egrep "^${NAME} "| ${AWK} '{print $3}'` + + if [ "${USE_COUNT}" = 0 ] ; then + + if [ "${DUMP_LOG}" -a ${NAME} = "spl" ]; then + spl_dump_log + fi + + unload_module ${MOD} || return 1 + fi + done + + if [ ${VERBOSE} ]; then + echo "Successfully unloaded ZFS module stack" + fi + + return 0 +} + +unused_loop_device() { + for DEVICE in `ls -1 /dev/loop*`; do + ${LOSETUP} ${DEVICE} &>/dev/null + if [ $? -ne 0 ]; then + echo ${DEVICE} + return + fi + done + + die "Error: Unable to find unused loopback device" +} + +# +# This can be slightly dangerous because the loop devices we are +# cleanup up may not be ours. However, if the devices are currently +# in use we will not be able to remove them, and we only remove +# devices which include 'zpool' in the name. So any damage we might +# do should be limited to other zfs related testing. +# +cleanup_loop_devices() { + local TMP_FILE=`mktemp` + + ${LOSETUP} -a | tr -d '()' >${TMP_FILE} + ${AWK} -F":" -v losetup="$LOSETUP" \ + '/zpool/ { system("losetup -d "$1) }' ${TMP_FILE} + ${AWK} -F" " '/zpool/ { system("rm -f "$3) }' ${TMP_FILE} + + rm -f ${TMP_FILE} +} + +# +# The following udev helper functions assume that the provided +# udev rules file will create a /dev/disk/zpool/<CHANNEL><RANK> +# disk mapping. In this mapping each CHANNEL is represented by +# the letters a-z, and the RANK is represented by the numbers +# 1-n. A CHANNEL should identify a group of RANKS which are all +# attached to a single controller, each RANK represents a disk. +# This provides a simply mechanism to locate a specific drive +# given a known hardware configuration. +# +udev_setup() { + local SRC_PATH=$1 + + # When running in tree manually contruct symlinks in tree to + # the proper devices. Symlinks are installed for all entires + # in the config file regardless of if that device actually + # exists. When installed as a package udev can be relied on for + # this and it will only create links for devices which exist. + if [ ${INTREE} ]; then + PWD=`pwd` + mkdir -p ${DEVDIR}/ + cd ${DEVDIR}/ + ${AWK} '!/^#/ && /./ { system( \ + "ln -f -s /dev/disk/by-path/"$2" "$1";" \ + "ln -f -s /dev/disk/by-path/"$2"-part1 "$1"p1;" \ + "ln -f -s /dev/disk/by-path/"$2"-part9 "$1"p9;" \ + ) }' $SRC_PATH + cd ${PWD} + else + DST_FILE=`basename ${SRC_PATH} | cut -f1-2 -d'.'` + DST_PATH=/etc/zfs/${DST_FILE} + + if [ -e ${DST_PATH} ]; then + die "Error: Config ${DST_PATH} already exists" + fi + + cp ${SRC_PATH} ${DST_PATH} + + if [ -f ${UDEVADM} ]; then + ${UDEVADM} trigger + ${UDEVADM} settle + else + /sbin/udevtrigger + /sbin/udevsettle + fi + fi + + return 0 +} + +udev_cleanup() { + local SRC_PATH=$1 + + if [ ${INTREE} ]; then + PWD=`pwd` + cd ${DEVDIR}/ + ${AWK} '!/^#/ && /./ { system( \ + "rm -f "$1" "$1"p1 "$1"p9") }' $SRC_PATH + cd ${PWD} + fi + + return 0 +} + +udev_cr2d() { + local CHANNEL=`echo "obase=16; $1+96" | bc` + local RANK=$2 + + printf "\x${CHANNEL}${RANK}" +} + +udev_raid0_setup() { + local RANKS=$1 + local CHANNELS=$2 + local IDX=0 + + RAID0S=() + for RANK in `seq 1 ${RANKS}`; do + for CHANNEL in `seq 1 ${CHANNELS}`; do + DISK=`udev_cr2d ${CHANNEL} ${RANK}` + RAID0S[${IDX}]="${DEVDIR}/${DISK}" + let IDX=IDX+1 + done + done + + return 0 +} + +udev_raid10_setup() { + local RANKS=$1 + local CHANNELS=$2 + local IDX=0 + + RAID10S=() + for RANK in `seq 1 ${RANKS}`; do + for CHANNEL1 in `seq 1 2 ${CHANNELS}`; do + let CHANNEL2=CHANNEL1+1 + DISK1=`udev_cr2d ${CHANNEL1} ${RANK}` + DISK2=`udev_cr2d ${CHANNEL2} ${RANK}` + GROUP="${DEVDIR}/${DISK1} ${DEVDIR}/${DISK2}" + RAID10S[${IDX}]="mirror ${GROUP}" + let IDX=IDX+1 + done + done + + return 0 +} + +udev_raidz_setup() { + local RANKS=$1 + local CHANNELS=$2 + + RAIDZS=() + for RANK in `seq 1 ${RANKS}`; do + RAIDZ=("raidz") + + for CHANNEL in `seq 1 ${CHANNELS}`; do + DISK=`udev_cr2d ${CHANNEL} ${RANK}` + RAIDZ[${CHANNEL}]="${DEVDIR}/${DISK}" + done + + RAIDZS[${RANK}]="${RAIDZ[*]}" + done + + return 0 +} + +udev_raidz2_setup() { + local RANKS=$1 + local CHANNELS=$2 + + RAIDZ2S=() + for RANK in `seq 1 ${RANKS}`; do + RAIDZ2=("raidz2") + + for CHANNEL in `seq 1 ${CHANNELS}`; do + DISK=`udev_cr2d ${CHANNEL} ${RANK}` + RAIDZ2[${CHANNEL}]="${DEVDIR}/${DISK}" + done + + RAIDZ2S[${RANK}]="${RAIDZ2[*]}" + done + + return 0 +} + +run_one_test() { + local TEST_NUM=$1 + local TEST_NAME=$2 + + printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}" + test_${TEST_NUM} +} + +skip_one_test() { + local TEST_NUM=$1 + local TEST_NAME=$2 + + printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}" + skip +} + +run_test() { + local TEST_NUM=$1 + local TEST_NAME=$2 + + for i in ${TESTS_SKIP[@]}; do + if [[ $i == ${TEST_NUM} ]] ; then + skip_one_test ${TEST_NUM} "${TEST_NAME}" + return 0 + fi + done + + if [ "${TESTS_RUN[0]}" = "*" ]; then + run_one_test ${TEST_NUM} "${TEST_NAME}" + else + for i in ${TESTS_RUN[@]}; do + if [[ $i == ${TEST_NUM} ]] ; then + run_one_test ${TEST_NUM} "${TEST_NAME}" + return 0 + fi + done + + skip_one_test ${TEST_NUM} "${TEST_NAME}" + fi +} diff --git a/scripts/common.sh.in b/scripts/common.sh.in index 00418696c..0a8399f18 100644 --- a/scripts/common.sh.in +++ b/scripts/common.sh.in @@ -26,6 +26,8 @@ RAID0S=() RAID10S=() RAIDZS=() RAIDZ2S=() +TESTS_RUN=${TESTS_RUN:-'*'} +TESTS_SKIP=${TESTS_SKIP:-} prefix=@prefix@ exec_prefix=@exec_prefix@ @@ -58,6 +60,24 @@ SYSCTL=${SYSCTL:-/sbin/sysctl} UDEVADM=${UDEVADM:-/sbin/udevadm} AWK=${AWK:-/usr/bin/awk} +COLOR_BLACK="\033[0;30m" +COLOR_DK_GRAY="\033[1;30m" +COLOR_BLUE="\033[0;34m" +COLOR_LT_BLUE="\033[1;34m" +COLOR_GREEN="\033[0;32m" +COLOR_LT_GREEN="\033[1;32m" +COLOR_CYAN="\033[0;36m" +COLOR_LT_CYAN="\033[1;36m" +COLOR_RED="\033[0;31m" +COLOR_LT_RED="\033[1;31m" +COLOR_PURPLE="\033[0;35m" +COLOR_LT_PURPLE="\033[1;35m" +COLOR_BROWN="\033[0;33m" +COLOR_YELLOW="\033[1;33m" +COLOR_LT_GRAY="\033[0;37m" +COLOR_WHITE="\033[1;37m" +COLOR_RESET="\033[0m" + die() { echo -e "${PROG}: $1" >&2 exit 1 @@ -70,14 +90,18 @@ msg() { } pass() { - echo "PASS" + echo -e "${COLOR_GREEN}Pass${COLOR_RESET}" } fail() { - echo "FAIL ($1)" + echo -e "${COLOR_RED}Fail${COLOR_RESET} ($1)" exit $1 } +skip() { + echo -e "${COLOR_BROWN}Skip${COLOR_RESET}" +} + spl_dump_log() { ${SYSCTL} -w kernel.spl.debug.dump=1 &>/dev/null local NAME=`dmesg | tail -n 1 | cut -f5 -d' '` @@ -371,3 +395,44 @@ udev_raidz2_setup() { return 0 } + +run_one_test() { + local TEST_NUM=$1 + local TEST_NAME=$2 + + printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}" + test_${TEST_NUM} +} + +skip_one_test() { + local TEST_NUM=$1 + local TEST_NAME=$2 + + printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}" + skip +} + +run_test() { + local TEST_NUM=$1 + local TEST_NAME=$2 + + for i in ${TESTS_SKIP[@]}; do + if [[ $i == ${TEST_NUM} ]] ; then + skip_one_test ${TEST_NUM} "${TEST_NAME}" + return 0 + fi + done + + if [ "${TESTS_RUN[0]}" = "*" ]; then + run_one_test ${TEST_NUM} "${TEST_NAME}" + else + for i in ${TESTS_RUN[@]}; do + if [[ $i == ${TEST_NUM} ]] ; then + run_one_test ${TEST_NUM} "${TEST_NAME}" + return 0 + fi + done + + skip_one_test ${TEST_NUM} "${TEST_NAME}" + fi +} diff --git a/scripts/zconfig.sh b/scripts/zconfig.sh index 98f00fa0e..c2e5d9754 100755 --- a/scripts/zconfig.sh +++ b/scripts/zconfig.sh @@ -29,7 +29,7 @@ OPTIONS: EOF } -while getopts 'hvc?' OPTION; do +while getopts 'hvct:s:?' OPTION; do case $OPTION in h) usage @@ -41,6 +41,12 @@ while getopts 'hvc?' OPTION; do c) CLEANUP=1 ;; + t) + TESTS_RUN=($OPTARG) + ;; + s) + TESTS_SKIP=($OPTARG) + ;; ?) usage exit @@ -75,14 +81,12 @@ EOF } # Validate persistent zpool.cache configuration. -zconfig_test1() { +test_1() { local POOL_NAME=test1 local TMP_FILE1=`mktemp` local TMP_FILE2=`mktemp` local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX` - echo -n "test 1 - persistent zpool.cache: " - # Create a pool save its status for comparison. ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1 ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 || fail 2 @@ -101,17 +105,15 @@ zconfig_test1() { pass } -zconfig_test1 +run_test 1 "persistent zpool.cache" # Validate ZFS disk scanning and import w/out zpool.cache configuration. -zconfig_test2() { +test_2() { local POOL_NAME=test2 local TMP_FILE1=`mktemp` local TMP_FILE2=`mktemp` local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX` - echo -n "test 2 - scan disks for pools to import: " - # Create a pool save its status for comparison. ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1 ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 || fail 2 @@ -135,7 +137,7 @@ zconfig_test2() { pass } -zconfig_test2 +run_test 2 "scan disks for pools to import" zconfig_zvol_device_stat() { local EXPECT=$1 @@ -175,7 +177,7 @@ zconfig_zvol_device_stat() { # zpool import/export device check # (1 volume, 2 partitions, 1 snapshot, 1 clone) -zconfig_test3() { +test_3() { local POOL_NAME=tank local ZVOL_NAME=volume local SNAP_NAME=snap @@ -185,8 +187,6 @@ zconfig_test3() { local FULL_CLONE_NAME=${POOL_NAME}/${CLONE_NAME} local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX` - echo -n "test 3 - zpool import/export device: " - # Create a pool, volume, partition, snapshot, and clone. ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1 ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 || fail 2 @@ -225,10 +225,10 @@ zconfig_test3() { pass } -zconfig_test3 +run_test 3 "zpool import/export device" # zpool insmod/rmmod device check (1 volume, 1 snapshot, 1 clone) -zconfig_test4() { +test_4() { POOL_NAME=tank ZVOL_NAME=volume SNAP_NAME=snap @@ -238,8 +238,6 @@ zconfig_test4() { FULL_CLONE_NAME=${POOL_NAME}/${CLONE_NAME} TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX` - echo -n "test 4 - zpool insmod/rmmod device: " - # Create a pool, volume, snapshot, and clone ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1 ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 || fail 2 @@ -278,18 +276,16 @@ zconfig_test4() { pass } -zconfig_test4 +run_test 4 "zpool insmod/rmmod device" # ZVOL volume sanity check -zconfig_test5() { +test_5() { local POOL_NAME=tank local ZVOL_NAME=fish local FULL_NAME=${POOL_NAME}/${ZVOL_NAME} local SRC_DIR=/bin/ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX` - echo -n "test 5 - zvol+ext3 volume: " - # Create a pool and volume. ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1 ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 || fail 2 @@ -323,10 +319,10 @@ zconfig_test5() { pass } -zconfig_test5 +run_test 5 "zvol+ext3 volume" # ZVOL snapshot sanity check -zconfig_test6() { +test_6() { local POOL_NAME=tank local ZVOL_NAME=fish local SNAP_NAME=pristine @@ -335,8 +331,6 @@ zconfig_test6() { local SRC_DIR=/bin/ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX` - echo -n "test 6 - zvol+ext2 snapshot: " - # Create a pool and volume. ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1 ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 || fail 2 @@ -382,10 +376,10 @@ zconfig_test6() { pass } -zconfig_test6 +run_test 6 "zvol+ext2 snapshot" # ZVOL clone sanity check -zconfig_test7() { +test_7() { local POOL_NAME=tank local ZVOL_NAME=fish local SNAP_NAME=pristine @@ -396,8 +390,6 @@ zconfig_test7() { local SRC_DIR=/bin/ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX` - echo -n "test 7 - zvol+ext2 clone: " - # Create a pool and volume. ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1 ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 || fail 2 @@ -464,7 +456,7 @@ zconfig_test7() { pass } -zconfig_test7 +run_test 7 "zvol+ext2 clone" # Send/Receive sanity check test_8() { |