diff options
author | Matthew Macy <[email protected]> | 2019-09-27 10:46:28 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-09-27 10:46:28 -0700 |
commit | 7bb0c294688ed121477536d7b4a7031c78a5706a (patch) | |
tree | e3e78a38a6139bcd32c57d4a67ae08fcb5552a1c /module/os | |
parent | 3768db24abe09f964a976945faeb805214817626 (diff) |
OpenZFS restructuring - zfs_ioctl
Refactor the zfs ioctls in to platform dependent and independent bits.
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Sean Eric Fagan <[email protected]>
Signed-off-by: Matthew Macy <[email protected]>
Signed-off-by: Ryan Moeller <[email protected]>
Closes #9301
Diffstat (limited to 'module/os')
-rw-r--r-- | module/os/linux/zfs/Makefile.in | 1 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_ioctl_os.c | 322 |
2 files changed, 323 insertions, 0 deletions
diff --git a/module/os/linux/zfs/Makefile.in b/module/os/linux/zfs/Makefile.in index a4f198907..1a7ea0d69 100644 --- a/module/os/linux/zfs/Makefile.in +++ b/module/os/linux/zfs/Makefile.in @@ -22,6 +22,7 @@ $(MODULE)-objs += ../os/linux/zfs/zfs_acl.o $(MODULE)-objs += ../os/linux/zfs/zfs_ctldir.o $(MODULE)-objs += ../os/linux/zfs/zfs_debug.o $(MODULE)-objs += ../os/linux/zfs/zfs_dir.o +$(MODULE)-objs += ../os/linux/zfs/zfs_ioctl_os.o $(MODULE)-objs += ../os/linux/zfs/zfs_sysfs.o $(MODULE)-objs += ../os/linux/zfs/zfs_vfsops.o $(MODULE)-objs += ../os/linux/zfs/zfs_vnops.o diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c new file mode 100644 index 000000000..9b562cab3 --- /dev/null +++ b/module/os/linux/zfs/zfs_ioctl_os.c @@ -0,0 +1,322 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Portions Copyright 2011 Martin Matuska + * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. + * Portions Copyright 2012 Pawel Jakub Dawidek <[email protected]> + * Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. + * Copyright (c) 2013 Steven Hartland. All rights reserved. + * Copyright (c) 2014 Integros [integros.com] + * Copyright 2016 Toomas Soome <[email protected]> + * Copyright (c) 2016 Actifio, Inc. All rights reserved. + * Copyright (c) 2018, loli10K <[email protected]>. All rights reserved. + * Copyright 2017 RackTop Systems. + * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. + * Copyright (c) 2019 Datto Inc. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/uio.h> +#include <sys/file.h> +#include <sys/kmem.h> +#include <sys/stat.h> +#include <sys/zfs_ioctl.h> +#include <sys/zfs_vfsops.h> +#include <sys/zap.h> +#include <sys/spa.h> +#include <sys/nvpair.h> +#include <sys/fs/zfs.h> +#include <sys/zfs_ctldir.h> +#include <sys/zfs_dir.h> +#include <sys/zfs_onexit.h> +#include <sys/zvol.h> +#include <sys/fm/util.h> +#include <sys/dsl_crypt.h> + +#include <sys/zfs_ioctl_impl.h> + +#include <sys/zfs_sysfs.h> +#include <linux/miscdevice.h> +#include <linux/slab.h> + +int +zfs_vfs_ref(zfsvfs_t **zfvp) +{ + if (*zfvp == NULL || (*zfvp)->z_sb == NULL || + !atomic_inc_not_zero(&((*zfvp)->z_sb->s_active))) { + return (SET_ERROR(ESRCH)); + } + return (0); +} + +static int +zfsdev_state_init(struct file *filp) +{ + zfsdev_state_t *zs, *zsprev = NULL; + minor_t minor; + boolean_t newzs = B_FALSE; + + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); + + minor = zfsdev_minor_alloc(); + if (minor == 0) + return (SET_ERROR(ENXIO)); + + for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) { + if (zs->zs_minor == -1) + break; + zsprev = zs; + } + + if (!zs) { + zs = kmem_zalloc(sizeof (zfsdev_state_t), KM_SLEEP); + newzs = B_TRUE; + } + + zs->zs_file = filp; + filp->private_data = zs; + + zfs_onexit_init((zfs_onexit_t **)&zs->zs_onexit); + zfs_zevent_init((zfs_zevent_t **)&zs->zs_zevent); + + /* + * In order to provide for lock-free concurrent read access + * to the minor list in zfsdev_get_state_impl(), new entries + * must be completely written before linking them into the + * list whereas existing entries are already linked; the last + * operation must be updating zs_minor (from -1 to the new + * value). + */ + if (newzs) { + zs->zs_minor = minor; + smp_wmb(); + zsprev->zs_next = zs; + } else { + smp_wmb(); + zs->zs_minor = minor; + } + + return (0); +} + +static int +zfsdev_state_destroy(struct file *filp) +{ + zfsdev_state_t *zs; + + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); + ASSERT(filp->private_data != NULL); + + zs = filp->private_data; + zs->zs_minor = -1; + zfs_onexit_destroy(zs->zs_onexit); + zfs_zevent_destroy(zs->zs_zevent); + + return (0); +} + +static int +zfsdev_open(struct inode *ino, struct file *filp) +{ + int error; + + mutex_enter(&zfsdev_state_lock); + error = zfsdev_state_init(filp); + mutex_exit(&zfsdev_state_lock); + + return (-error); +} + +static int +zfsdev_release(struct inode *ino, struct file *filp) +{ + int error; + + mutex_enter(&zfsdev_state_lock); + error = zfsdev_state_destroy(filp); + mutex_exit(&zfsdev_state_lock); + + return (-error); +} + +static long +zfsdev_ioctl(struct file *filp, unsigned cmd, unsigned long arg) +{ + uint_t vecnum; + + vecnum = cmd - ZFS_IOC_FIRST; + return (zfsdev_ioctl_common(vecnum, arg)); +} + +int +zfsdev_getminor(struct file *filp, minor_t *minorp) +{ + zfsdev_state_t *zs, *fpd; + + ASSERT(filp != NULL); + ASSERT(!MUTEX_HELD(&zfsdev_state_lock)); + + fpd = filp->private_data; + if (fpd == NULL) + return (SET_ERROR(EBADF)); + + mutex_enter(&zfsdev_state_lock); + + for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) { + + if (zs->zs_minor == -1) + continue; + + if (fpd == zs) { + *minorp = fpd->zs_minor; + mutex_exit(&zfsdev_state_lock); + return (0); + } + } + + mutex_exit(&zfsdev_state_lock); + + return (SET_ERROR(EBADF)); +} + +void +zfs_ioctl_init_os(void) +{ +} + +#ifdef CONFIG_COMPAT +static long +zfsdev_compat_ioctl(struct file *filp, unsigned cmd, unsigned long arg) +{ + return (zfsdev_ioctl(filp, cmd, arg)); +} +#else +#define zfsdev_compat_ioctl NULL +#endif + +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, +}; + +static struct miscdevice zfs_misc = { + .minor = ZFS_DEVICE_MINOR, + .name = ZFS_DRIVER, + .fops = &zfsdev_fops, +}; + +MODULE_ALIAS_MISCDEV(ZFS_DEVICE_MINOR); +MODULE_ALIAS("devname:zfs"); + +int +zfsdev_attach(void) +{ + int error; + + error = misc_register(&zfs_misc); + if (error == -EBUSY) { + /* + * Fallback to dynamic minor allocation in the event of a + * collision with a reserved minor in linux/miscdevice.h. + * In this case the kernel modules must be manually loaded. + */ + printk(KERN_INFO "ZFS: misc_register() with static minor %d " + "failed %d, retrying with MISC_DYNAMIC_MINOR\n", + ZFS_DEVICE_MINOR, error); + + zfs_misc.minor = MISC_DYNAMIC_MINOR; + error = misc_register(&zfs_misc); + } + + if (error) + printk(KERN_INFO "ZFS: misc_register() failed %d\n", error); + + return (error); +} + +void +zfsdev_detach(void) +{ + misc_deregister(&zfs_misc); +} + +#ifdef DEBUG +#define ZFS_DEBUG_STR " (DEBUG mode)" +#else +#define ZFS_DEBUG_STR "" +#endif + +static int __init +_init(void) +{ + int error; + + if ((error = zfs_kmod_init()) != 0) { + printk(KERN_NOTICE "ZFS: Failed to Load ZFS Filesystem v%s-%s%s" + ", rc = %d\n", ZFS_META_VERSION, ZFS_META_RELEASE, + ZFS_DEBUG_STR, error); + + return (-error); + } + + zfs_sysfs_init(); + + printk(KERN_NOTICE "ZFS: Loaded module v%s-%s%s, " + "ZFS pool version %s, ZFS filesystem version %s\n", + ZFS_META_VERSION, ZFS_META_RELEASE, ZFS_DEBUG_STR, + SPA_VERSION_STRING, ZPL_VERSION_STRING); +#ifndef CONFIG_FS_POSIX_ACL + printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n"); +#endif /* CONFIG_FS_POSIX_ACL */ + + return (0); +} + +static void __exit +_fini(void) +{ + zfs_sysfs_fini(); + zfs_kmod_fini(); + + printk(KERN_NOTICE "ZFS: Unloaded module v%s-%s%s\n", + ZFS_META_VERSION, ZFS_META_RELEASE, ZFS_DEBUG_STR); +} + +#if defined(_KERNEL) +module_init(_init); +module_exit(_fini); + +MODULE_DESCRIPTION("ZFS"); +MODULE_AUTHOR(ZFS_META_AUTHOR); +MODULE_LICENSE(ZFS_META_LICENSE); +MODULE_VERSION(ZFS_META_VERSION "-" ZFS_META_RELEASE); +#endif |