Print this page
2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Dan McDonald <danmcd@nexenta.com>
   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);