1 /* 2 * Copyright (c) 2020 iXsystems, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/types.h> 29 #include <sys/errno.h> 30 #include <sys/nvpair.h> 31 #include <sys/spa_impl.h> 32 #include <sys/vdev_os.h> 33 #include <sys/zfs_vfsops.h> 34 #include <sys/zone.h> 35 #include <vm/vm_pageout.h> 36 37 #include <sys/zfs_ioctl_impl.h> 38 39 int 40 zfs_vfs_ref(zfsvfs_t **zfvp) 41 { 42 int error = 0; 43 44 if (*zfvp == NULL) 45 return (SET_ERROR(ESRCH)); 46 47 error = vfs_busy((*zfvp)->z_vfs, 0); 48 if (error != 0) { 49 *zfvp = NULL; 50 error = SET_ERROR(ESRCH); 51 } 52 return (error); 53 } 54 55 boolean_t 56 zfs_vfs_held(zfsvfs_t *zfsvfs) 57 { 58 return (zfsvfs->z_vfs != NULL); 59 } 60 61 void 62 zfs_vfs_rele(zfsvfs_t *zfsvfs) 63 { 64 vfs_unbusy(zfsvfs->z_vfs); 65 } 66 67 static const zfs_ioc_key_t zfs_keys_nextboot[] = { 68 {"command", DATA_TYPE_STRING, 0}, 69 { ZPOOL_CONFIG_POOL_GUID, DATA_TYPE_UINT64, 0}, 70 { ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64, 0} 71 }; 72 73 static int 74 zfs_ioc_jail(zfs_cmd_t *zc) 75 { 76 77 return (zone_dataset_attach(curthread->td_ucred, zc->zc_name, 78 (int)zc->zc_zoneid)); 79 } 80 81 static int 82 zfs_ioc_unjail(zfs_cmd_t *zc) 83 { 84 85 return (zone_dataset_detach(curthread->td_ucred, zc->zc_name, 86 (int)zc->zc_zoneid)); 87 } 88 89 static int 90 zfs_ioc_nextboot(const char *unused, nvlist_t *innvl, nvlist_t *outnvl) 91 { 92 char name[MAXNAMELEN]; 93 spa_t *spa; 94 vdev_t *vd; 95 const char *command; 96 uint64_t pool_guid; 97 uint64_t vdev_guid; 98 int error; 99 100 if (nvlist_lookup_uint64(innvl, 101 ZPOOL_CONFIG_POOL_GUID, &pool_guid) != 0) 102 return (EINVAL); 103 if (nvlist_lookup_uint64(innvl, 104 ZPOOL_CONFIG_GUID, &vdev_guid) != 0) 105 return (EINVAL); 106 if (nvlist_lookup_string(innvl, 107 "command", &command) != 0) 108 return (EINVAL); 109 110 mutex_enter(&spa_namespace_lock); 111 spa = spa_by_guid(pool_guid, vdev_guid); 112 if (spa != NULL) 113 strcpy(name, spa_name(spa)); 114 mutex_exit(&spa_namespace_lock); 115 if (spa == NULL) 116 return (ENOENT); 117 118 if ((error = spa_open(name, &spa, FTAG)) != 0) 119 return (error); 120 spa_vdev_state_enter(spa, SCL_ALL); 121 vd = spa_lookup_by_guid(spa, vdev_guid, B_TRUE); 122 if (vd == NULL) { 123 (void) spa_vdev_state_exit(spa, NULL, ENXIO); 124 spa_close(spa, FTAG); 125 return (ENODEV); 126 } 127 error = vdev_label_write_pad2(vd, command, strlen(command)); 128 (void) spa_vdev_state_exit(spa, NULL, 0); 129 txg_wait_synced(spa->spa_dsl_pool, 0); 130 spa_close(spa, FTAG); 131 return (error); 132 } 133 134 /* Update the VFS's cache of mountpoint properties */ 135 void 136 zfs_ioctl_update_mount_cache(const char *dsname) 137 { 138 zfsvfs_t *zfsvfs; 139 140 if (getzfsvfs(dsname, &zfsvfs) == 0) { 141 struct mount *mp = zfsvfs->z_vfs; 142 VFS_STATFS(mp, &mp->mnt_stat); 143 zfs_vfs_rele(zfsvfs); 144 } 145 /* 146 * Ignore errors; we can't do anything useful if either getzfsvfs or 147 * VFS_STATFS fails. 148 */ 149 } 150 151 uint64_t 152 zfs_max_nvlist_src_size_os(void) 153 { 154 if (zfs_max_nvlist_src_size != 0) 155 return (zfs_max_nvlist_src_size); 156 157 return (ptob(vm_page_max_user_wired) / 4); 158 } 159 160 void 161 zfs_ioctl_init_os(void) 162 { 163 zfs_ioctl_register_dataset_nolog(ZFS_IOC_JAIL, zfs_ioc_jail, 164 zfs_secpolicy_config, POOL_CHECK_NONE); 165 zfs_ioctl_register_dataset_nolog(ZFS_IOC_UNJAIL, zfs_ioc_unjail, 166 zfs_secpolicy_config, POOL_CHECK_NONE); 167 zfs_ioctl_register("fbsd_nextboot", ZFS_IOC_NEXTBOOT, 168 zfs_ioc_nextboot, zfs_secpolicy_config, NO_NAME, 169 POOL_CHECK_NONE, B_FALSE, B_FALSE, zfs_keys_nextboot, 3); 170 171 } 172