1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Portions Copyright 2011 Martin Matuska 25 * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. 26 * Portions Copyright 2012 Pawel Jakub Dawidek <pawel@dawidek.net> 27 * Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved. 28 * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 29 * Copyright (c) 2014, Joyent, Inc. All rights reserved. 30 * Copyright (c) 2011, 2018 by Delphix. All rights reserved. 31 * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. 32 * Copyright (c) 2013 Steven Hartland. All rights reserved. 33 * Copyright (c) 2014 Integros [integros.com] 34 * Copyright 2016 Toomas Soome <tsoome@me.com> 35 * Copyright (c) 2016 Actifio, Inc. All rights reserved. 36 * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved. 37 * Copyright 2017 RackTop Systems. 38 * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. 39 * Copyright (c) 2019 Datto Inc. 40 */ 41 42#include <sys/types.h> 43#include <sys/param.h> 44#include <sys/errno.h> 45#include <sys/uio.h> 46#include <sys/file.h> 47#include <sys/kmem.h> 48#include <sys/stat.h> 49#include <sys/zfs_ioctl.h> 50#include <sys/zfs_vfsops.h> 51#include <sys/zap.h> 52#include <sys/spa.h> 53#include <sys/nvpair.h> 54#include <sys/fs/zfs.h> 55#include <sys/zfs_ctldir.h> 56#include <sys/zfs_dir.h> 57#include <sys/zfs_onexit.h> 58#include <sys/zvol.h> 59#include <sys/fm/util.h> 60#include <sys/dsl_crypt.h> 61 62#include <sys/zfs_ioctl_impl.h> 63 64#include <sys/zfs_sysfs.h> 65#include <linux/miscdevice.h> 66#include <linux/slab.h> 67 68boolean_t 69zfs_vfs_held(zfsvfs_t *zfsvfs) 70{ 71 return (zfsvfs->z_sb != NULL); 72} 73 74int 75zfs_vfs_ref(zfsvfs_t **zfvp) 76{ 77 if (*zfvp == NULL || (*zfvp)->z_sb == NULL || 78 !atomic_inc_not_zero(&((*zfvp)->z_sb->s_active))) { 79 return (SET_ERROR(ESRCH)); 80 } 81 return (0); 82} 83 84void 85zfs_vfs_rele(zfsvfs_t *zfsvfs) 86{ 87 deactivate_super(zfsvfs->z_sb); 88} 89 90static int 91zfsdev_state_init(struct file *filp) 92{ 93 zfsdev_state_t *zs, *zsprev = NULL; 94 minor_t minor; 95 boolean_t newzs = B_FALSE; 96 97 ASSERT(MUTEX_HELD(&zfsdev_state_lock)); 98 99 minor = zfsdev_minor_alloc(); 100 if (minor == 0) 101 return (SET_ERROR(ENXIO)); 102 103 for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) { 104 if (zs->zs_minor == -1) 105 break; 106 zsprev = zs; 107 } 108 109 if (!zs) { 110 zs = kmem_zalloc(sizeof (zfsdev_state_t), KM_SLEEP); 111 newzs = B_TRUE; 112 } 113 114 filp->private_data = zs; 115 116 zfs_onexit_init((zfs_onexit_t **)&zs->zs_onexit); 117 zfs_zevent_init((zfs_zevent_t **)&zs->zs_zevent); 118 119 /* 120 * In order to provide for lock-free concurrent read access 121 * to the minor list in zfsdev_get_state_impl(), new entries 122 * must be completely written before linking them into the 123 * list whereas existing entries are already linked; the last 124 * operation must be updating zs_minor (from -1 to the new 125 * value). 126 */ 127 if (newzs) { 128 zs->zs_minor = minor; 129 smp_wmb(); 130 zsprev->zs_next = zs; 131 } else { 132 smp_wmb(); 133 zs->zs_minor = minor; 134 } 135 136 return (0); 137} 138 139static int 140zfsdev_state_destroy(struct file *filp) 141{ 142 zfsdev_state_t *zs; 143 144 ASSERT(MUTEX_HELD(&zfsdev_state_lock)); 145 ASSERT(filp->private_data != NULL); 146 147 zs = filp->private_data; 148 zs->zs_minor = -1; 149 zfs_onexit_destroy(zs->zs_onexit); 150 zfs_zevent_destroy(zs->zs_zevent); 151 zs->zs_onexit = NULL; 152 zs->zs_zevent = NULL; 153 154 return (0); 155} 156 157static int 158zfsdev_open(struct inode *ino, struct file *filp) 159{ 160 int error; 161 162 mutex_enter(&zfsdev_state_lock); 163 error = zfsdev_state_init(filp); 164 mutex_exit(&zfsdev_state_lock); 165 166 return (-error); 167} 168 169static int 170zfsdev_release(struct inode *ino, struct file *filp) 171{ 172 int error; 173 174 mutex_enter(&zfsdev_state_lock); 175 error = zfsdev_state_destroy(filp); 176 mutex_exit(&zfsdev_state_lock); 177 178 return (-error); 179} 180 181static long 182zfsdev_ioctl(struct file *filp, unsigned cmd, unsigned long arg) 183{ 184 uint_t vecnum; 185 zfs_cmd_t *zc; 186 int error, rc; 187 188 vecnum = cmd - ZFS_IOC_FIRST; 189 190 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 191 192 if (ddi_copyin((void *)(uintptr_t)arg, zc, sizeof (zfs_cmd_t), 0)) { 193 error = -SET_ERROR(EFAULT); 194 goto out; 195 } 196 error = -zfsdev_ioctl_common(vecnum, zc, 0); 197 rc = ddi_copyout(zc, (void *)(uintptr_t)arg, sizeof (zfs_cmd_t), 0); 198 if (error == 0 && rc != 0) 199 error = -SET_ERROR(EFAULT); 200out: 201 kmem_free(zc, sizeof (zfs_cmd_t)); 202 return (error); 203 204} 205 206uint64_t 207zfs_max_nvlist_src_size_os(void) 208{ 209 if (zfs_max_nvlist_src_size != 0) 210 return (zfs_max_nvlist_src_size); 211 212 return (MIN(ptob(zfs_totalram_pages) / 4, 128 * 1024 * 1024)); 213} 214 215/* Update the VFS's cache of mountpoint properties */ 216void 217zfs_ioctl_update_mount_cache(const char *dsname) 218{ 219} 220 221void 222zfs_ioctl_init_os(void) 223{ 224} 225 226#ifdef CONFIG_COMPAT 227static long 228zfsdev_compat_ioctl(struct file *filp, unsigned cmd, unsigned long arg) 229{ 230 return (zfsdev_ioctl(filp, cmd, arg)); 231} 232#else 233#define zfsdev_compat_ioctl NULL 234#endif 235 236static const struct file_operations zfsdev_fops = { 237 .open = zfsdev_open, 238 .release = zfsdev_release, 239 .unlocked_ioctl = zfsdev_ioctl, 240 .compat_ioctl = zfsdev_compat_ioctl, 241 .owner = THIS_MODULE, 242}; 243 244static struct miscdevice zfs_misc = { 245 .minor = ZFS_DEVICE_MINOR, 246 .name = ZFS_DRIVER, 247 .fops = &zfsdev_fops, 248}; 249 250MODULE_ALIAS_MISCDEV(ZFS_DEVICE_MINOR); 251MODULE_ALIAS("devname:zfs"); 252 253int 254zfsdev_attach(void) 255{ 256 int error; 257 258 error = misc_register(&zfs_misc); 259 if (error == -EBUSY) { 260 /* 261 * Fallback to dynamic minor allocation in the event of a 262 * collision with a reserved minor in linux/miscdevice.h. 263 * In this case the kernel modules must be manually loaded. 264 */ 265 printk(KERN_INFO "ZFS: misc_register() with static minor %d " 266 "failed %d, retrying with MISC_DYNAMIC_MINOR\n", 267 ZFS_DEVICE_MINOR, error); 268 269 zfs_misc.minor = MISC_DYNAMIC_MINOR; 270 error = misc_register(&zfs_misc); 271 } 272 273 if (error) 274 printk(KERN_INFO "ZFS: misc_register() failed %d\n", error); 275 276 return (error); 277} 278 279void 280zfsdev_detach(void) 281{ 282 misc_deregister(&zfs_misc); 283} 284 285#ifdef ZFS_DEBUG 286#define ZFS_DEBUG_STR " (DEBUG mode)" 287#else 288#define ZFS_DEBUG_STR "" 289#endif 290 291static int __init 292openzfs_init(void) 293{ 294 int error; 295 296 if ((error = zfs_kmod_init()) != 0) { 297 printk(KERN_NOTICE "ZFS: Failed to Load ZFS Filesystem v%s-%s%s" 298 ", rc = %d\n", ZFS_META_VERSION, ZFS_META_RELEASE, 299 ZFS_DEBUG_STR, error); 300 301 return (-error); 302 } 303 304 zfs_sysfs_init(); 305 306 printk(KERN_NOTICE "ZFS: Loaded module v%s-%s%s, " 307 "ZFS pool version %s, ZFS filesystem version %s\n", 308 ZFS_META_VERSION, ZFS_META_RELEASE, ZFS_DEBUG_STR, 309 SPA_VERSION_STRING, ZPL_VERSION_STRING); 310#ifndef CONFIG_FS_POSIX_ACL 311 printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n"); 312#endif /* CONFIG_FS_POSIX_ACL */ 313 314 return (0); 315} 316 317static void __exit 318openzfs_fini(void) 319{ 320 zfs_sysfs_fini(); 321 zfs_kmod_fini(); 322 323 printk(KERN_NOTICE "ZFS: Unloaded module v%s-%s%s\n", 324 ZFS_META_VERSION, ZFS_META_RELEASE, ZFS_DEBUG_STR); 325} 326 327#if defined(_KERNEL) 328module_init(openzfs_init); 329module_exit(openzfs_fini); 330#endif 331 332ZFS_MODULE_DESCRIPTION("ZFS"); 333ZFS_MODULE_AUTHOR(ZFS_META_AUTHOR); 334ZFS_MODULE_LICENSE(ZFS_META_LICENSE); 335ZFS_MODULE_VERSION(ZFS_META_VERSION "-" ZFS_META_RELEASE); 336