diff --git a/module/zfs/include/sys/zfs_ioctl.h b/module/zfs/include/sys/zfs_ioctl.h index 59992993df..f5f61a4b1c 100644 --- a/module/zfs/include/sys/zfs_ioctl.h +++ b/module/zfs/include/sys/zfs_ioctl.h @@ -123,6 +123,9 @@ typedef struct zinject_record { #define ZINJECT_FLUSH_ARC 0x2 #define ZINJECT_UNLOAD_SPA 0x4 +#define ZEVENT_NONBLOCK 0x1 +#define ZEVENT_SIZE 1024 + typedef struct zfs_share { uint64_t z_exportdata; uint64_t z_sharedata; @@ -187,6 +190,9 @@ typedef struct zfs_creat { extern dev_info_t *zfs_dip; +extern int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp); +extern int put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl); + 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); diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 5f9234319d..fb5532d613 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -63,20 +63,18 @@ #include #include #include +#include + +#include #include "zfs_namecheck.h" #include "zfs_prop.h" #include "zfs_deleg.h" -extern struct modlfs zfs_modlfs; - 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_ioc_func_t(struct file *, zfs_cmd_t *); typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); typedef enum { @@ -101,11 +99,12 @@ static const char *userquota_perms[] = { ZFS_DELEG_PERM_GROUPQUOTA, }; -static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc); -static void clear_props(char *dataset, nvlist_t *props, nvlist_t *newprops); +static int zfs_ioc_userspace_upgrade(struct file *filp, zfs_cmd_t *zc); +static void clear_props(struct file *filp, char *dataset, + nvlist_t *props, nvlist_t *newprops); static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *, boolean_t *); -int zfs_set_prop_nvlist(const char *, nvlist_t *); +int zfs_set_prop_nvlist(struct file *filp, const char *, nvlist_t *); /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ void @@ -403,6 +402,7 @@ zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) ZFS_DELEG_PERM_SEND, cr)); } +#ifdef HAVE_ZPL static int zfs_secpolicy_deleg_share(zfs_cmd_t *zc, cred_t *cr) { @@ -426,10 +426,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); @@ -438,11 +440,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); @@ -451,6 +457,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 @@ -645,6 +654,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) { @@ -656,6 +666,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 @@ -780,7 +791,7 @@ zfs_secpolicy_release(zfs_cmd_t *zc, cred_t *cr) /* * Returns the nvlist as specified by the user in the zfs_cmd_t. */ -static int +int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp) { char *packed; @@ -812,7 +823,7 @@ get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp) return (0); } -static int +int put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) { char *packed = NULL; @@ -836,6 +847,7 @@ put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) return (error); } +#ifdef HAVE_ZPL static int getzfsvfs(const char *dsname, zfsvfs_t **zvp) { @@ -898,9 +910,10 @@ zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag) zfsvfs_free(zfsvfs); } } +#endif /* HAVE_ZPL */ static int -zfs_ioc_pool_create(zfs_cmd_t *zc) +zfs_ioc_pool_create(struct file *filp, zfs_cmd_t *zc) { int error; nvlist_t *config, *props = NULL; @@ -954,7 +967,7 @@ zfs_ioc_pool_create(zfs_cmd_t *zc) * Set the remaining root properties */ if (!error && - (error = zfs_set_prop_nvlist(zc->zc_name, rootprops)) != 0) + (error = zfs_set_prop_nvlist(filp, zc->zc_name, rootprops)) != 0) (void) spa_destroy(zc->zc_name); if (buf != NULL) @@ -970,7 +983,7 @@ pool_props_bad: } static int -zfs_ioc_pool_destroy(zfs_cmd_t *zc) +zfs_ioc_pool_destroy(struct file *filp, zfs_cmd_t *zc) { int error; zfs_log_history(zc); @@ -979,7 +992,7 @@ zfs_ioc_pool_destroy(zfs_cmd_t *zc) } static int -zfs_ioc_pool_import(zfs_cmd_t *zc) +zfs_ioc_pool_import(struct file *filp, zfs_cmd_t *zc) { int error; nvlist_t *config, *props = NULL; @@ -1014,7 +1027,7 @@ zfs_ioc_pool_import(zfs_cmd_t *zc) } static int -zfs_ioc_pool_export(zfs_cmd_t *zc) +zfs_ioc_pool_export(struct file *filp, zfs_cmd_t *zc) { int error; boolean_t force = (boolean_t)zc->zc_cookie; @@ -1026,7 +1039,7 @@ zfs_ioc_pool_export(zfs_cmd_t *zc) } static int -zfs_ioc_pool_configs(zfs_cmd_t *zc) +zfs_ioc_pool_configs(struct file *filp, zfs_cmd_t *zc) { nvlist_t *configs; int error; @@ -1042,7 +1055,7 @@ zfs_ioc_pool_configs(zfs_cmd_t *zc) } static int -zfs_ioc_pool_stats(zfs_cmd_t *zc) +zfs_ioc_pool_stats(struct file *filp, zfs_cmd_t *zc) { nvlist_t *config; int error; @@ -1073,7 +1086,7 @@ zfs_ioc_pool_stats(zfs_cmd_t *zc) * user land knows which devices are available and overall pool health. */ static int -zfs_ioc_pool_tryimport(zfs_cmd_t *zc) +zfs_ioc_pool_tryimport(struct file *filp, zfs_cmd_t *zc) { nvlist_t *tryconfig, *config; int error; @@ -1096,7 +1109,7 @@ zfs_ioc_pool_tryimport(zfs_cmd_t *zc) } static int -zfs_ioc_pool_scrub(zfs_cmd_t *zc) +zfs_ioc_pool_scrub(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -1112,7 +1125,7 @@ zfs_ioc_pool_scrub(zfs_cmd_t *zc) } static int -zfs_ioc_pool_freeze(zfs_cmd_t *zc) +zfs_ioc_pool_freeze(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -1126,7 +1139,7 @@ zfs_ioc_pool_freeze(zfs_cmd_t *zc) } static int -zfs_ioc_pool_upgrade(zfs_cmd_t *zc) +zfs_ioc_pool_upgrade(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -1146,7 +1159,7 @@ zfs_ioc_pool_upgrade(zfs_cmd_t *zc) } static int -zfs_ioc_pool_get_history(zfs_cmd_t *zc) +zfs_ioc_pool_get_history(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; char *hist_buf; @@ -1178,7 +1191,7 @@ zfs_ioc_pool_get_history(zfs_cmd_t *zc) } static int -zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) +zfs_ioc_dsobj_to_dsname(struct file *filp, zfs_cmd_t *zc) { int error; @@ -1189,7 +1202,7 @@ zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) } static int -zfs_ioc_obj_to_path(zfs_cmd_t *zc) +zfs_ioc_obj_to_path(struct file *filp, zfs_cmd_t *zc) { objset_t *osp; int error; @@ -1205,7 +1218,7 @@ zfs_ioc_obj_to_path(zfs_cmd_t *zc) } static int -zfs_ioc_vdev_add(zfs_cmd_t *zc) +zfs_ioc_vdev_add(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -1248,7 +1261,7 @@ zfs_ioc_vdev_add(zfs_cmd_t *zc) } static int -zfs_ioc_vdev_remove(zfs_cmd_t *zc) +zfs_ioc_vdev_remove(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -1262,7 +1275,7 @@ zfs_ioc_vdev_remove(zfs_cmd_t *zc) } static int -zfs_ioc_vdev_set_state(zfs_cmd_t *zc) +zfs_ioc_vdev_set_state(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -1296,7 +1309,7 @@ zfs_ioc_vdev_set_state(zfs_cmd_t *zc) } static int -zfs_ioc_vdev_attach(zfs_cmd_t *zc) +zfs_ioc_vdev_attach(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int replacing = zc->zc_cookie; @@ -1317,7 +1330,7 @@ zfs_ioc_vdev_attach(zfs_cmd_t *zc) } static int -zfs_ioc_vdev_detach(zfs_cmd_t *zc) +zfs_ioc_vdev_detach(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -1332,7 +1345,7 @@ zfs_ioc_vdev_detach(zfs_cmd_t *zc) } static int -zfs_ioc_vdev_setpath(zfs_cmd_t *zc) +zfs_ioc_vdev_setpath(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; char *path = zc->zc_value; @@ -1349,7 +1362,7 @@ zfs_ioc_vdev_setpath(zfs_cmd_t *zc) } static int -zfs_ioc_vdev_setfru(zfs_cmd_t *zc) +zfs_ioc_vdev_setfru(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; char *fru = zc->zc_value; @@ -1376,7 +1389,7 @@ zfs_ioc_vdev_setfru(zfs_cmd_t *zc) * zc_nvlist_dst_size size of property nvlist */ static int -zfs_ioc_objset_stats(zfs_cmd_t *zc) +zfs_ioc_objset_stats(struct file *filp, zfs_cmd_t *zc) { objset_t *os = NULL; int error; @@ -1435,7 +1448,7 @@ nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) * zc_nvlist_dst_size size of zpl property nvlist */ static int -zfs_ioc_objset_zplprops(zfs_cmd_t *zc) +zfs_ioc_objset_zplprops(struct file *filp, zfs_cmd_t *zc) { objset_t *os; int err; @@ -1501,7 +1514,7 @@ dataset_name_hidden(const char *name) * zc_nvlist_dst_size size of property nvlist */ static int -zfs_ioc_dataset_list_next(zfs_cmd_t *zc) +zfs_ioc_dataset_list_next(struct file *filp, zfs_cmd_t *zc) { objset_t *os; int error; @@ -1541,7 +1554,7 @@ zfs_ioc_dataset_list_next(zfs_cmd_t *zc) dmu_objset_close(os); if (error == 0) - error = zfs_ioc_objset_stats(zc); /* fill in the stats */ + error = zfs_ioc_objset_stats(filp, zc); /* fill in the stats */ return (error); } @@ -1559,7 +1572,7 @@ zfs_ioc_dataset_list_next(zfs_cmd_t *zc) * zc_nvlist_dst_size size of property nvlist */ static int -zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) +zfs_ioc_snapshot_list_next(struct file *filp, zfs_cmd_t *zc) { objset_t *os; int error; @@ -1587,7 +1600,7 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); dmu_objset_close(os); if (error == 0) - error = zfs_ioc_objset_stats(zc); /* fill in the stats */ + error = zfs_ioc_objset_stats(filp, zc); /* fill in the stats */ else if (error == ENOENT) error = ESRCH; @@ -1598,7 +1611,7 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) } int -zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) +zfs_set_prop_nvlist(struct file *filp, const char *name, nvlist_t *nvl) { nvpair_t *elem; int error = 0; @@ -1713,6 +1726,7 @@ zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) if (prop == ZPROP_INVAL) { if (zfs_prop_userquota(propname)) { +#ifdef HAVE_ZPL uint64_t *valary; unsigned int vallen; const char *domain; @@ -1741,6 +1755,10 @@ zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) continue; else goto out; +#else + error = ENOTSUP; + goto out; +#endif } else if (zfs_prop_user(propname)) { VERIFY(nvpair_value_string(elem, &strval) == 0); error = dsl_prop_set(name, propname, 1, @@ -1781,8 +1799,7 @@ zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) case ZFS_PROP_VOLSIZE: if ((error = nvpair_value_uint64(elem, &intval)) != 0 || - (error = zvol_set_volsize(name, - ddi_driver_major(zfs_dip), intval)) != 0) + (error = zvol_set_volsize(name, intval)) != 0) goto out; break; @@ -1794,6 +1811,7 @@ zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) case ZFS_PROP_VERSION: { +#ifdef HAVE_ZPL zfsvfs_t *zfsvfs; if ((error = nvpair_value_uint64(elem, &intval)) != 0) @@ -1807,11 +1825,15 @@ zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) if (error == 0 && intval >= ZPL_VERSION_USERSPACE) { zfs_cmd_t zc = { 0 }; (void) strcpy(zc.zc_name, name); - (void) zfs_ioc_userspace_upgrade(&zc); + (void) zfs_ioc_userspace_upgrade(filp, &zc); } if (error) goto out; break; +#else + error = ENOTSUP; + goto out; +#endif /* HAVE_ZPL */ } default: @@ -1902,7 +1924,7 @@ zfs_check_userprops(char *fsname, nvlist_t *nvl) * outputs: none */ static int -zfs_ioc_set_prop(zfs_cmd_t *zc) +zfs_ioc_set_prop(struct file *filp, zfs_cmd_t *zc) { nvlist_t *nvl; int error; @@ -1918,7 +1940,7 @@ zfs_ioc_set_prop(zfs_cmd_t *zc) if (dmu_objset_open(zc->zc_name, DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { if (dsl_prop_get_all(os, &origprops, TRUE) == 0) { - clear_props(zc->zc_name, origprops, nvl); + clear_props(filp, zc->zc_name, origprops, nvl); nvlist_free(origprops); } dmu_objset_close(os); @@ -1926,7 +1948,7 @@ zfs_ioc_set_prop(zfs_cmd_t *zc) } - error = zfs_set_prop_nvlist(zc->zc_name, nvl); + error = zfs_set_prop_nvlist(filp, zc->zc_name, nvl); nvlist_free(nvl); return (error); @@ -1940,14 +1962,14 @@ zfs_ioc_set_prop(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_inherit_prop(zfs_cmd_t *zc) +zfs_ioc_inherit_prop(struct file *filp, zfs_cmd_t *zc) { /* the property name has been validated by zfs_secpolicy_inherit() */ return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); } static int -zfs_ioc_pool_set_props(zfs_cmd_t *zc) +zfs_ioc_pool_set_props(struct file *filp, zfs_cmd_t *zc) { nvlist_t *props; spa_t *spa; @@ -1990,7 +2012,7 @@ zfs_ioc_pool_set_props(zfs_cmd_t *zc) } static int -zfs_ioc_pool_get_props(zfs_cmd_t *zc) +zfs_ioc_pool_get_props(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -2021,8 +2043,9 @@ zfs_ioc_pool_get_props(zfs_cmd_t *zc) } static int -zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) +zfs_ioc_iscsi_perm_check(struct file *filp, zfs_cmd_t *zc) { +#ifdef HAVE_ZPL nvlist_t *nvp; int error; uint32_t uid; @@ -2065,6 +2088,9 @@ zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); crfree(usercred); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -2076,7 +2102,7 @@ zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_set_fsacl(zfs_cmd_t *zc) +zfs_ioc_set_fsacl(struct file *filp, zfs_cmd_t *zc) { int error; nvlist_t *fsaclnv = NULL; @@ -2125,7 +2151,7 @@ zfs_ioc_set_fsacl(zfs_cmd_t *zc) * zc_nvlist_src{_size} nvlist of delegated permissions */ static int -zfs_ioc_get_fsacl(zfs_cmd_t *zc) +zfs_ioc_get_fsacl(struct file *filp, zfs_cmd_t *zc) { nvlist_t *nvp; int error; @@ -2145,9 +2171,9 @@ zfs_ioc_get_fsacl(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_create_minor(zfs_cmd_t *zc) +zfs_ioc_create_minor(struct file *filp, zfs_cmd_t *zc) { - return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); + return (zvol_create_minor(zc->zc_name)); } /* @@ -2157,11 +2183,12 @@ zfs_ioc_create_minor(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_remove_minor(zfs_cmd_t *zc) +zfs_ioc_remove_minor(struct file *filp, zfs_cmd_t *zc) { return (zvol_remove_minor(zc->zc_name)); } +#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 @@ -2186,6 +2213,7 @@ zfs_get_vfs(const char *resource) vfs_list_unlock(); return (vfs_found); } +#endif /* HAVE_ZPL */ /* ARGSUSED */ static void @@ -2358,7 +2386,7 @@ zfs_fill_zplprops_root(uint64_t spa_vers, nvlist_t *createprops, * outputs: none */ static int -zfs_ioc_create(zfs_cmd_t *zc) +zfs_ioc_create(struct file *filp, zfs_cmd_t *zc) { objset_t *clone; int error = 0; @@ -2483,7 +2511,7 @@ zfs_ioc_create(zfs_cmd_t *zc) * It would be nice to do this atomically. */ if (error == 0) { - if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) + if ((error = zfs_set_prop_nvlist(filp, zc->zc_name, nvprops)) != 0) (void) dmu_objset_destroy(zc->zc_name, B_FALSE); } nvlist_free(nvprops); @@ -2500,7 +2528,7 @@ zfs_ioc_create(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_snapshot(zfs_cmd_t *zc) +zfs_ioc_snapshot(struct file *filp, zfs_cmd_t *zc) { nvlist_t *nvprops = NULL; int error; @@ -2535,6 +2563,7 @@ out: int zfs_unmount_snap(char *name, void *arg) { +#ifdef HAVE_ZPL vfs_t *vfsp = NULL; if (arg) { @@ -2566,6 +2595,7 @@ zfs_unmount_snap(char *name, void *arg) if ((err = dounmount(vfsp, flag, kcred)) != 0) return (err); } +#endif /* HAVE_ZPL */ return (0); } @@ -2578,7 +2608,7 @@ zfs_unmount_snap(char *name, void *arg) * outputs: none */ static int -zfs_ioc_destroy_snaps(zfs_cmd_t *zc) +zfs_ioc_destroy_snaps(struct file *filp, zfs_cmd_t *zc) { int err; @@ -2601,7 +2631,7 @@ zfs_ioc_destroy_snaps(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_destroy(zfs_cmd_t *zc) +zfs_ioc_destroy(struct file *filp, zfs_cmd_t *zc) { if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { int err = zfs_unmount_snap(zc->zc_name, NULL); @@ -2619,8 +2649,9 @@ zfs_ioc_destroy(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_rollback(zfs_cmd_t *zc) +zfs_ioc_rollback(struct file *filp, zfs_cmd_t *zc) { +#ifdef HAVE_ZPL objset_t *os; int error; zfsvfs_t *zfsvfs = NULL; @@ -2654,6 +2685,9 @@ zfs_ioc_rollback(zfs_cmd_t *zc) /* Note, the dmu_objset_rollback() releases the objset for us. */ return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -2665,7 +2699,7 @@ zfs_ioc_rollback(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_rename(zfs_cmd_t *zc) +zfs_ioc_rename(struct file *filp, zfs_cmd_t *zc) { boolean_t recursive = zc->zc_cookie & 1; @@ -2689,7 +2723,8 @@ zfs_ioc_rename(zfs_cmd_t *zc) } static void -clear_props(char *dataset, nvlist_t *props, nvlist_t *newprops) +clear_props(struct file *filp, char *dataset, nvlist_t *props, + nvlist_t *newprops) { zfs_cmd_t *zc; nvpair_t *prop; @@ -2705,7 +2740,7 @@ clear_props(char *dataset, nvlist_t *props, nvlist_t *newprops) continue; (void) strcpy(zc->zc_value, nvpair_name(prop)); if (zfs_secpolicy_inherit(zc, CRED()) == 0) - (void) zfs_ioc_inherit_prop(zc); + (void) zfs_ioc_inherit_prop(filp, zc); } kmem_free(zc, sizeof (zfs_cmd_t)); } @@ -2724,10 +2759,12 @@ clear_props(char *dataset, nvlist_t *props, nvlist_t *newprops) * zc_cookie number of bytes read */ static int -zfs_ioc_recv(zfs_cmd_t *zc) +zfs_ioc_recv(struct file *filp, zfs_cmd_t *zc) { file_t *fp; +#ifdef HAVE_ZPL objset_t *os; +#endif /* HAVE_ZPL */ dmu_recv_cookie_t drc; boolean_t force = (boolean_t)zc->zc_guid; int error, fd; @@ -2760,6 +2797,7 @@ zfs_ioc_recv(zfs_cmd_t *zc) return (EBADF); } +#ifdef HAVE_ZPL if (props && dmu_objset_open(tofs, DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { /* @@ -2770,6 +2808,7 @@ zfs_ioc_recv(zfs_cmd_t *zc) dmu_objset_close(os); } +#endif /* HAVE_ZPL */ if (zc->zc_string[0]) { error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, @@ -2790,17 +2829,18 @@ zfs_ioc_recv(zfs_cmd_t *zc) * so that the properties are applied to the new data. */ if (props) { - clear_props(tofs, origprops, props); + clear_props(filp, tofs, origprops, props); /* * XXX - Note, this is all-or-nothing; should be best-effort. */ - (void) zfs_set_prop_nvlist(tofs, props); + (void) zfs_set_prop_nvlist(filp, tofs, props); } off = fp->f_offset; error = dmu_recv_stream(&drc, fp->f_vnode, &off); if (error == 0) { +#ifdef HAVE_ZPL zfsvfs_t *zfsvfs = NULL; if (getzfsvfs(tofs, &zfsvfs) == 0) { @@ -2827,6 +2867,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; @@ -2837,8 +2880,8 @@ zfs_ioc_recv(zfs_cmd_t *zc) * On error, restore the original props. */ if (error && props) { - clear_props(tofs, props, NULL); - (void) zfs_set_prop_nvlist(tofs, origprops); + clear_props(filp, tofs, props, NULL); + (void) zfs_set_prop_nvlist(filp, tofs, origprops); } out: nvlist_free(props); @@ -2857,7 +2900,7 @@ out: * outputs: none */ static int -zfs_ioc_send(zfs_cmd_t *zc) +zfs_ioc_send(struct file *filp, zfs_cmd_t *zc) { objset_t *fromsnap = NULL; objset_t *tosnap; @@ -2910,7 +2953,7 @@ zfs_ioc_send(zfs_cmd_t *zc) } static int -zfs_ioc_inject_fault(zfs_cmd_t *zc) +zfs_ioc_inject_fault(struct file *filp, zfs_cmd_t *zc) { int id, error; @@ -2924,13 +2967,13 @@ zfs_ioc_inject_fault(zfs_cmd_t *zc) } static int -zfs_ioc_clear_fault(zfs_cmd_t *zc) +zfs_ioc_clear_fault(struct file *filp, zfs_cmd_t *zc) { return (zio_clear_fault((int)zc->zc_guid)); } static int -zfs_ioc_inject_list_next(zfs_cmd_t *zc) +zfs_ioc_inject_list_next(struct file *filp, zfs_cmd_t *zc) { int id = (int)zc->zc_guid; int error; @@ -2944,7 +2987,7 @@ zfs_ioc_inject_list_next(zfs_cmd_t *zc) } static int -zfs_ioc_error_log(zfs_cmd_t *zc) +zfs_ioc_error_log(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; int error; @@ -2966,7 +3009,7 @@ zfs_ioc_error_log(zfs_cmd_t *zc) } static int -zfs_ioc_clear(zfs_cmd_t *zc) +zfs_ioc_clear(struct file *filp, zfs_cmd_t *zc) { spa_t *spa; vdev_t *vd; @@ -3026,7 +3069,7 @@ zfs_ioc_clear(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_promote(zfs_cmd_t *zc) +zfs_ioc_promote(struct file *filp, zfs_cmd_t *zc) { char *cp; @@ -3055,8 +3098,9 @@ zfs_ioc_promote(zfs_cmd_t *zc) * zc_cookie property value */ static int -zfs_ioc_userspace_one(zfs_cmd_t *zc) +zfs_ioc_userspace_one(struct file *filp, zfs_cmd_t *zc) { +#ifdef HAVE_ZPL zfsvfs_t *zfsvfs; int error; @@ -3072,6 +3116,9 @@ zfs_ioc_userspace_one(zfs_cmd_t *zc) zfsvfs_rele(zfsvfs, FTAG); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -3086,8 +3133,9 @@ zfs_ioc_userspace_one(zfs_cmd_t *zc) * zc_cookie zap cursor */ static int -zfs_ioc_userspace_many(zfs_cmd_t *zc) +zfs_ioc_userspace_many(struct file *filp, zfs_cmd_t *zc) { +#ifdef HAVE_ZPL zfsvfs_t *zfsvfs; int error; @@ -3110,6 +3158,9 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc) zfsvfs_rele(zfsvfs, FTAG); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -3120,8 +3171,9 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc) * none */ static int -zfs_ioc_userspace_upgrade(zfs_cmd_t *zc) +zfs_ioc_userspace_upgrade(struct file *filp, zfs_cmd_t *zc) { +#ifdef HAVE_ZPL objset_t *os; int error; zfsvfs_t *zfsvfs; @@ -3154,6 +3206,9 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc) } return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -3163,6 +3218,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); @@ -3194,10 +3250,12 @@ zfs_init_sharefs() } return (0); } +#endif /* HAVE_ZPL */ static int -zfs_ioc_share(zfs_cmd_t *zc) +zfs_ioc_share(struct file *filp, zfs_cmd_t *zc) { +#ifdef HAVE_ZPL int error; int opcode; @@ -3287,7 +3345,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[] = { @@ -3297,6 +3357,7 @@ ace_t full_access[] = { /* * Remove all ACL files in shares dir */ +#ifdef HAVE_ZPL static int zfs_smb_acl_purge(znode_t *dzp) { @@ -3315,10 +3376,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) +zfs_ioc_smb_acl(struct file *filp, zfs_cmd_t *zc) { +#ifdef HAVE_ZPL vnode_t *vp; znode_t *dzp; vnode_t *resourcevp = NULL; @@ -3440,6 +3503,9 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc) ZFS_EXIT(zfsvfs); return (error); +#else + return (ENOTSUP); +#endif /* HAVE_ZPL */ } /* @@ -3452,7 +3518,7 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_hold(zfs_cmd_t *zc) +zfs_ioc_hold(struct file *filp, zfs_cmd_t *zc) { boolean_t recursive = zc->zc_cookie; @@ -3473,7 +3539,7 @@ zfs_ioc_hold(zfs_cmd_t *zc) * outputs: none */ static int -zfs_ioc_release(zfs_cmd_t *zc) +zfs_ioc_release(struct file *filp, zfs_cmd_t *zc) { boolean_t recursive = zc->zc_cookie; @@ -3492,7 +3558,7 @@ zfs_ioc_release(zfs_cmd_t *zc) * zc_nvlist_src{_size} nvlist of snapshot holds */ static int -zfs_ioc_get_holds(zfs_cmd_t *zc) +zfs_ioc_get_holds(struct file *filp, zfs_cmd_t *zc) { nvlist_t *nvp; int error; @@ -3505,6 +3571,51 @@ zfs_ioc_get_holds(zfs_cmd_t *zc) return (error); } +/* + * inputs: + * zc_guid flags (ZEVENT_NONBLOCK) + * + * outputs: + * zc_nvlist_dst next nvlist event + * zc_cookie dropped events since last get + */ +static int +zfs_ioc_events_next(struct file *filp, zfs_cmd_t *zc) +{ + zfs_private_data_t *zpd = filp->private_data; + int error; + + do { + error = fm_zevent_next(zpd, zc); + if (zc->zc_guid & ZEVENT_NONBLOCK) + break; + + if ((error == 0) || (error != ENOENT)) + break; + + error = fm_zevent_wait(zpd); + if (error) + break; + } while (1); + + return (error); +} + +/* + * outputs: + * zc_cookie cleared events count + */ +static int +zfs_ioc_events_clear(struct file *filp, zfs_cmd_t *zc) +{ + int count; + + fm_zevent_drain_all(&count); + zc->zc_cookie = count; + + return 0; +} + /* * pool create, destroy, and export don't log the history as part of * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export @@ -3612,7 +3723,11 @@ static zfs_ioc_vec_t zfs_ioc_vec[] = { { zfs_ioc_release, zfs_secpolicy_release, DATASET_NAME, B_TRUE, B_TRUE }, { zfs_ioc_get_holds, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_TRUE } + B_TRUE }, + { zfs_ioc_events_next, zfs_secpolicy_config, NO_NAME, B_FALSE, + B_FALSE }, + { zfs_ioc_events_clear, zfs_secpolicy_config, NO_NAME, B_FALSE, + B_FALSE }, }; int @@ -3633,27 +3748,48 @@ pool_status_check(const char *name, zfs_ioc_namecheck_t type) } static int -zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) +zfs_open(struct inode *ino, struct file *filp) +{ + zfs_private_data_t *zpd; + + zpd = kmem_zalloc(sizeof(zfs_private_data_t), KM_SLEEP); + if (zpd == NULL) + return -ENOMEM; + + fm_zevent_init(zpd); + filp->private_data = zpd; + + return 0; +} + +static int +zfs_release(struct inode *ino, struct file *filp) +{ + zfs_private_data_t *zpd = filp->private_data; + + fm_zevent_fini(zpd); + kmem_free(zpd, sizeof(zfs_private_data_t)); + + return 0; +} + +static long +zfs_ioctl(struct file *filp, unsigned cmd, unsigned long arg) { zfs_cmd_t *zc; uint_t vec; - int error, rc; - - if (getminor(dev) != 0) - 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 = vmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); error = ddi_copyin((void *)arg, zc, sizeof (zfs_cmd_t), flag); if (error == 0) - 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 @@ -3685,7 +3821,7 @@ zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) } if (error == 0) - error = zfs_ioc_vec[vec].zvec_func(zc); + error = zfs_ioc_vec[vec].zvec_func(filp, zc); rc = ddi_copyout(zc, (void *)arg, sizeof (zfs_cmd_t), flag); if (error == 0) { @@ -3698,118 +3834,58 @@ zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) return (-error); } -static int -zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) +#ifdef CONFIG_COMPAT +static long +zfs_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; - - ddi_report_dev(dip); - - return (DDI_SUCCESS); + return zfs_ioctl(filp, cmd, arg); } +#else +#define zfs_compat_ioctl NULL +#endif + +static const struct file_operations zfs_fops = { + .open = zfs_open, + .release = zfs_release, + .unlocked_ioctl = zfs_ioctl, + .compat_ioctl = zfs_compat_ioctl, + .owner = THIS_MODULE, +}; + +static struct miscdevice zfs_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = ZFS_DRIVER, + .fops = &zfs_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); + int error; - if (cmd != DDI_DETACH) - return (DDI_FAILURE); - - zfs_dip = NULL; - - ddi_prop_remove_all(dip); - ddi_remove_minor_node(dip, NULL); - - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -static int -zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - *result = zfs_dip; - return (DDI_SUCCESS); - - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)0; - return (DDI_SUCCESS); + error = misc_register(&zfs_misc); + if (error) { + printk(KERN_INFO "ZFS: misc_register() failed %d\n", error); + return (error); } - return (DDI_FAILURE); + return (0); } -/* - * 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 = { - zvol_open, /* open */ - zvol_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 -}; +static void +zfs_detach(void) +{ + int error; + error = misc_deregister(&zfs_misc); + if (error) + printk(KERN_INFO "ZFS: misc_deregister() failed %d\n", error); +} +#ifdef HAVE_ZPL uint_t zfs_fsyncer_key; extern uint_t rrw_tsd_key; +#endif int _init(void) @@ -3818,21 +3894,28 @@ _init(void) spa_init(FREAD | FWRITE); zfs_init(); - zvol_init(); - if ((error = mod_install(&modlinkage)) != 0) { - zvol_fini(); + if ((error = zvol_init()) != 0) { zfs_fini(); spa_fini(); return (error); } + if ((error = zfs_attach()) != 0) { + (void)zvol_fini(); + zfs_fini(); + spa_fini(); + return (error); + } + +#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_INFO "ZFS: Loaded ZFS Filesystem v%s\n", ZFS_META_VERSION); return (0); } @@ -3840,17 +3923,11 @@ _init(void) 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) @@ -3858,16 +3935,18 @@ _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); + return (0); } -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} +#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 */