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 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Portions Copyright 2011 Martin Matuska
24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
27 */
28
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/errno.h>
32 #include <sys/uio.h>
33 #include <sys/buf.h>
34 #include <sys/modctl.h>
35 #include <sys/open.h>
36 #include <sys/file.h>
37 #include <sys/kmem.h>
38 #include <sys/conf.h>
39 #include <sys/cmn_err.h>
40 #include <sys/stat.h>
1117 if (dmu_objset_type(os) != DMU_OST_ZFS) {
1118 dmu_objset_rele(os, FTAG);
1119 return (EINVAL);
1120 }
1121
1122 mutex_enter(&os->os_user_ptr_lock);
1123 *zfvp = dmu_objset_get_user(os);
1124 if (*zfvp) {
1125 VFS_HOLD((*zfvp)->z_vfs);
1126 } else {
1127 error = ESRCH;
1128 }
1129 mutex_exit(&os->os_user_ptr_lock);
1130 dmu_objset_rele(os, FTAG);
1131 return (error);
1132 }
1133
1134 /*
1135 * Find a zfsvfs_t for a mounted filesystem, or create our own, in which
1136 * case its z_vfs will be NULL, and it will be opened as the owner.
1137 */
1138 static int
1139 zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer)
1140 {
1141 int error = 0;
1142
1143 if (getzfsvfs(name, zfvp) != 0)
1144 error = zfsvfs_create(name, zfvp);
1145 if (error == 0) {
1146 rrw_enter(&(*zfvp)->z_teardown_lock, (writer) ? RW_WRITER :
1147 RW_READER, tag);
1148 if ((*zfvp)->z_unmounted) {
1149 /*
1150 * XXX we could probably try again, since the unmounting
1151 * thread should be just about to disassociate the
1152 * objset from the zfsvfs.
1153 */
1154 rrw_exit(&(*zfvp)->z_teardown_lock, tag);
1155 return (EBUSY);
1156 }
1180 nvlist_t *zplprops = NULL;
1181 char *buf;
1182
1183 if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
1184 zc->zc_iflags, &config))
1185 return (error);
1186
1187 if (zc->zc_nvlist_src_size != 0 && (error =
1188 get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
1189 zc->zc_iflags, &props))) {
1190 nvlist_free(config);
1191 return (error);
1192 }
1193
1194 if (props) {
1195 nvlist_t *nvl = NULL;
1196 uint64_t version = SPA_VERSION;
1197
1198 (void) nvlist_lookup_uint64(props,
1199 zpool_prop_to_name(ZPOOL_PROP_VERSION), &version);
1200 if (version < SPA_VERSION_INITIAL || version > SPA_VERSION) {
1201 error = EINVAL;
1202 goto pool_props_bad;
1203 }
1204 (void) nvlist_lookup_nvlist(props, ZPOOL_ROOTFS_PROPS, &nvl);
1205 if (nvl) {
1206 error = nvlist_dup(nvl, &rootprops, KM_SLEEP);
1207 if (error != 0) {
1208 nvlist_free(config);
1209 nvlist_free(props);
1210 return (error);
1211 }
1212 (void) nvlist_remove_all(props, ZPOOL_ROOTFS_PROPS);
1213 }
1214 VERIFY(nvlist_alloc(&zplprops, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1215 error = zfs_fill_zplprops_root(version, rootprops,
1216 zplprops, NULL);
1217 if (error)
1218 goto pool_props_bad;
1219 }
1220
1304 zvol_remove_minors(zc->zc_name);
1305 return (error);
1306 }
1307
1308 static int
1309 zfs_ioc_pool_configs(zfs_cmd_t *zc)
1310 {
1311 nvlist_t *configs;
1312 int error;
1313
1314 if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
1315 return (EEXIST);
1316
1317 error = put_nvlist(zc, configs);
1318
1319 nvlist_free(configs);
1320
1321 return (error);
1322 }
1323
1324 static int
1325 zfs_ioc_pool_stats(zfs_cmd_t *zc)
1326 {
1327 nvlist_t *config;
1328 int error;
1329 int ret = 0;
1330
1331 error = spa_get_stats(zc->zc_name, &config, zc->zc_value,
1332 sizeof (zc->zc_value));
1333
1334 if (config != NULL) {
1335 ret = put_nvlist(zc, config);
1336 nvlist_free(config);
1337
1338 /*
1339 * The config may be present even if 'error' is non-zero.
1340 * In this case we return success, and preserve the real errno
1341 * in 'zc_cookie'.
1342 */
1343 zc->zc_cookie = error;
1405 spa_t *spa;
1406 int error;
1407
1408 error = spa_open(zc->zc_name, &spa, FTAG);
1409 if (error == 0) {
1410 spa_freeze(spa);
1411 spa_close(spa, FTAG);
1412 }
1413 return (error);
1414 }
1415
1416 static int
1417 zfs_ioc_pool_upgrade(zfs_cmd_t *zc)
1418 {
1419 spa_t *spa;
1420 int error;
1421
1422 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
1423 return (error);
1424
1425 if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) {
1426 spa_close(spa, FTAG);
1427 return (EINVAL);
1428 }
1429
1430 spa_upgrade(spa, zc->zc_cookie);
1431 spa_close(spa, FTAG);
1432
1433 return (error);
1434 }
1435
1436 static int
1437 zfs_ioc_pool_get_history(zfs_cmd_t *zc)
1438 {
1439 spa_t *spa;
1440 char *hist_buf;
1441 uint64_t size;
1442 int error;
1443
1444 if ((size = zc->zc_history_len) == 0)
1445 return (EINVAL);
|
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 2011 Nexenta Systems, Inc. All rights reserved.
26 * Copyright (c) 2012 by Delphix. All rights reserved.
27 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
28 */
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/errno.h>
33 #include <sys/uio.h>
34 #include <sys/buf.h>
35 #include <sys/modctl.h>
36 #include <sys/open.h>
37 #include <sys/file.h>
38 #include <sys/kmem.h>
39 #include <sys/conf.h>
40 #include <sys/cmn_err.h>
41 #include <sys/stat.h>
1118 if (dmu_objset_type(os) != DMU_OST_ZFS) {
1119 dmu_objset_rele(os, FTAG);
1120 return (EINVAL);
1121 }
1122
1123 mutex_enter(&os->os_user_ptr_lock);
1124 *zfvp = dmu_objset_get_user(os);
1125 if (*zfvp) {
1126 VFS_HOLD((*zfvp)->z_vfs);
1127 } else {
1128 error = ESRCH;
1129 }
1130 mutex_exit(&os->os_user_ptr_lock);
1131 dmu_objset_rele(os, FTAG);
1132 return (error);
1133 }
1134
1135 /*
1136 * Find a zfsvfs_t for a mounted filesystem, or create our own, in which
1137 * case its z_vfs will be NULL, and it will be opened as the owner.
1138 * If 'writer' is set, the z_teardown_lock will be held for RW_WRITER,
1139 * which prevents all vnode ops from running.
1140 */
1141 static int
1142 zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer)
1143 {
1144 int error = 0;
1145
1146 if (getzfsvfs(name, zfvp) != 0)
1147 error = zfsvfs_create(name, zfvp);
1148 if (error == 0) {
1149 rrw_enter(&(*zfvp)->z_teardown_lock, (writer) ? RW_WRITER :
1150 RW_READER, tag);
1151 if ((*zfvp)->z_unmounted) {
1152 /*
1153 * XXX we could probably try again, since the unmounting
1154 * thread should be just about to disassociate the
1155 * objset from the zfsvfs.
1156 */
1157 rrw_exit(&(*zfvp)->z_teardown_lock, tag);
1158 return (EBUSY);
1159 }
1183 nvlist_t *zplprops = NULL;
1184 char *buf;
1185
1186 if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
1187 zc->zc_iflags, &config))
1188 return (error);
1189
1190 if (zc->zc_nvlist_src_size != 0 && (error =
1191 get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
1192 zc->zc_iflags, &props))) {
1193 nvlist_free(config);
1194 return (error);
1195 }
1196
1197 if (props) {
1198 nvlist_t *nvl = NULL;
1199 uint64_t version = SPA_VERSION;
1200
1201 (void) nvlist_lookup_uint64(props,
1202 zpool_prop_to_name(ZPOOL_PROP_VERSION), &version);
1203 if (!SPA_VERSION_IS_SUPPORTED(version)) {
1204 error = EINVAL;
1205 goto pool_props_bad;
1206 }
1207 (void) nvlist_lookup_nvlist(props, ZPOOL_ROOTFS_PROPS, &nvl);
1208 if (nvl) {
1209 error = nvlist_dup(nvl, &rootprops, KM_SLEEP);
1210 if (error != 0) {
1211 nvlist_free(config);
1212 nvlist_free(props);
1213 return (error);
1214 }
1215 (void) nvlist_remove_all(props, ZPOOL_ROOTFS_PROPS);
1216 }
1217 VERIFY(nvlist_alloc(&zplprops, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1218 error = zfs_fill_zplprops_root(version, rootprops,
1219 zplprops, NULL);
1220 if (error)
1221 goto pool_props_bad;
1222 }
1223
1307 zvol_remove_minors(zc->zc_name);
1308 return (error);
1309 }
1310
1311 static int
1312 zfs_ioc_pool_configs(zfs_cmd_t *zc)
1313 {
1314 nvlist_t *configs;
1315 int error;
1316
1317 if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
1318 return (EEXIST);
1319
1320 error = put_nvlist(zc, configs);
1321
1322 nvlist_free(configs);
1323
1324 return (error);
1325 }
1326
1327 /*
1328 * inputs:
1329 * zc_name name of the pool
1330 *
1331 * outputs:
1332 * zc_cookie real errno
1333 * zc_nvlist_dst config nvlist
1334 * zc_nvlist_dst_size size of config nvlist
1335 */
1336 static int
1337 zfs_ioc_pool_stats(zfs_cmd_t *zc)
1338 {
1339 nvlist_t *config;
1340 int error;
1341 int ret = 0;
1342
1343 error = spa_get_stats(zc->zc_name, &config, zc->zc_value,
1344 sizeof (zc->zc_value));
1345
1346 if (config != NULL) {
1347 ret = put_nvlist(zc, config);
1348 nvlist_free(config);
1349
1350 /*
1351 * The config may be present even if 'error' is non-zero.
1352 * In this case we return success, and preserve the real errno
1353 * in 'zc_cookie'.
1354 */
1355 zc->zc_cookie = error;
1417 spa_t *spa;
1418 int error;
1419
1420 error = spa_open(zc->zc_name, &spa, FTAG);
1421 if (error == 0) {
1422 spa_freeze(spa);
1423 spa_close(spa, FTAG);
1424 }
1425 return (error);
1426 }
1427
1428 static int
1429 zfs_ioc_pool_upgrade(zfs_cmd_t *zc)
1430 {
1431 spa_t *spa;
1432 int error;
1433
1434 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
1435 return (error);
1436
1437 if (zc->zc_cookie < spa_version(spa) ||
1438 !SPA_VERSION_IS_SUPPORTED(zc->zc_cookie)) {
1439 spa_close(spa, FTAG);
1440 return (EINVAL);
1441 }
1442
1443 spa_upgrade(spa, zc->zc_cookie);
1444 spa_close(spa, FTAG);
1445
1446 return (error);
1447 }
1448
1449 static int
1450 zfs_ioc_pool_get_history(zfs_cmd_t *zc)
1451 {
1452 spa_t *spa;
1453 char *hist_buf;
1454 uint64_t size;
1455 int error;
1456
1457 if ((size = zc->zc_history_len) == 0)
1458 return (EINVAL);
|