usr/src/lib/libzfs/common/libzfs_dataset.c
changeset 5713 f9b7933f3770
parent 5592 1b20f93ffca0
child 5717 b163be0bb014
equal deleted inserted replaced
5712:81f1af42bafc 5713:f9b7933f3770
   461 	if (zhp->zfs_mntopts)
   461 	if (zhp->zfs_mntopts)
   462 		free(zhp->zfs_mntopts);
   462 		free(zhp->zfs_mntopts);
   463 	nvlist_free(zhp->zfs_props);
   463 	nvlist_free(zhp->zfs_props);
   464 	nvlist_free(zhp->zfs_user_props);
   464 	nvlist_free(zhp->zfs_user_props);
   465 	free(zhp);
   465 	free(zhp);
       
   466 }
       
   467 
       
   468 int
       
   469 zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
       
   470 {
       
   471 	char *pool_name;
       
   472 	zpool_handle_t *zpool_handle;
       
   473 	char *p;
       
   474 
       
   475 	pool_name = zfs_alloc(zhp->zfs_hdl, MAXPATHLEN);
       
   476 	if (zfs_prop_get(zhp, ZFS_PROP_NAME, pool_name,
       
   477 	    MAXPATHLEN, NULL, NULL, 0, B_FALSE) != 0) {
       
   478 		free(pool_name);
       
   479 		return (-1);
       
   480 	}
       
   481 
       
   482 	if (p = strchr(pool_name, '/'))
       
   483 		*p = '\0';
       
   484 	zpool_handle = zpool_open(zhp->zfs_hdl, pool_name);
       
   485 	free(pool_name);
       
   486 	if (zpool_handle == NULL)
       
   487 		return (-1);
       
   488 
       
   489 	*spa_version = zpool_get_prop_int(zpool_handle,
       
   490 	    ZPOOL_PROP_VERSION, NULL);
       
   491 	zpool_close(zpool_handle);
       
   492 	return (0);
       
   493 }
       
   494 
       
   495 /*
       
   496  * The choice of reservation property depends on the SPA version.
       
   497  */
       
   498 static int
       
   499 zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
       
   500 {
       
   501 	int spa_version;
       
   502 
       
   503 	if (zfs_spa_version(zhp, &spa_version) < 0)
       
   504 		return (-1);
       
   505 
       
   506 	if (spa_version >= SPA_VERSION_REFRESERVATION)
       
   507 		*resv_prop = ZFS_PROP_REFRESERVATION;
       
   508 	else
       
   509 		*resv_prop = ZFS_PROP_RESERVATION;
       
   510 
       
   511 	return (0);
   466 }
   512 }
   467 
   513 
   468 /*
   514 /*
   469  * Given an nvlist of properties to set, validates that they are correct, and
   515  * Given an nvlist of properties to set, validates that they are correct, and
   470  * parses any numeric properties (index, boolean, etc) if they are specified as
   516  * parses any numeric properties (index, boolean, etc) if they are specified as
   834 	    &intval) == 0) {
   880 	    &intval) == 0) {
   835 		uint64_t old_volsize = zfs_prop_get_int(zhp,
   881 		uint64_t old_volsize = zfs_prop_get_int(zhp,
   836 		    ZFS_PROP_VOLSIZE);
   882 		    ZFS_PROP_VOLSIZE);
   837 		uint64_t old_reservation;
   883 		uint64_t old_reservation;
   838 		uint64_t new_reservation;
   884 		uint64_t new_reservation;
   839 		char *pool_name;
       
   840 		zpool_handle_t *zpool_handle;
       
   841 		char *p;
       
   842 		zfs_prop_t resv_prop;
   885 		zfs_prop_t resv_prop;
   843 		uint64_t spa_version;
   886 
   844 
   887 		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
   845 		pool_name = zfs_alloc(zhp->zfs_hdl, MAXPATHLEN);
       
   846 		if (zfs_prop_get(zhp, ZFS_PROP_NAME, pool_name,
       
   847 		    MAXPATHLEN, NULL, NULL, 0, B_FALSE) != 0) {
       
   848 			free(pool_name);
       
   849 			goto error;
   888 			goto error;
   850 		}
       
   851 
       
   852 		if (p = strchr(pool_name, '/'))
       
   853 			*p = '\0';
       
   854 		zpool_handle = zpool_open(hdl, pool_name);
       
   855 		free(pool_name);
       
   856 		if (zpool_handle == NULL)
       
   857 			goto error;
       
   858 
       
   859 		spa_version = zpool_get_prop_int(zpool_handle,
       
   860 		    ZPOOL_PROP_VERSION, NULL);
       
   861 		zpool_close(zpool_handle);
       
   862 		if (spa_version >= SPA_VERSION_REFRESERVATION)
       
   863 			resv_prop = ZFS_PROP_REFRESERVATION;
       
   864 		else
       
   865 			resv_prop = ZFS_PROP_RESERVATION;
       
   866 
       
   867 		old_reservation = zfs_prop_get_int(zhp, resv_prop);
   889 		old_reservation = zfs_prop_get_int(zhp, resv_prop);
   868 
   890 
   869 		if (old_volsize == old_reservation &&
   891 		if (old_volsize == old_reservation &&
   870 		    nvlist_lookup_uint64(ret, zfs_prop_to_name(resv_prop),
   892 		    nvlist_lookup_uint64(ret, zfs_prop_to_name(resv_prop),
   871 		    &new_reservation) != 0) {
   893 		    &new_reservation) != 0) {
   874 				(void) no_memory(hdl);
   896 				(void) no_memory(hdl);
   875 				goto error;
   897 				goto error;
   876 			}
   898 			}
   877 		}
   899 		}
   878 	}
   900 	}
   879 
       
   880 	return (ret);
   901 	return (ret);
   881 
   902 
   882 error:
   903 error:
   883 	nvlist_free(ret);
   904 	nvlist_free(ret);
   884 	return (NULL);
   905 	return (NULL);
  1622 
  1643 
  1623 	if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
  1644 	if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
  1624 		goto error;
  1645 		goto error;
  1625 
  1646 
  1626 	ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
  1647 	ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
  1627 
       
  1628 	if (ret != 0) {
  1648 	if (ret != 0) {
  1629 		switch (errno) {
  1649 		switch (errno) {
  1630 
  1650 
  1631 		case ENOSPC:
  1651 		case ENOSPC:
  1632 			/*
  1652 			/*
  2282 	(void) get_numeric_property(zhp, prop, NULL, &source, &val);
  2302 	(void) get_numeric_property(zhp, prop, NULL, &source, &val);
  2283 
  2303 
  2284 	return (val);
  2304 	return (val);
  2285 }
  2305 }
  2286 
  2306 
       
  2307 int
       
  2308 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
       
  2309 {
       
  2310 	char buf[64];
       
  2311 
       
  2312 	zfs_nicenum(val, buf, sizeof (buf));
       
  2313 	return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
       
  2314 }
       
  2315 
  2287 /*
  2316 /*
  2288  * Similar to zfs_prop_get(), but returns the value as an integer.
  2317  * Similar to zfs_prop_get(), but returns the value as an integer.
  2289  */
  2318  */
  2290 int
  2319 int
  2291 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
  2320 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
  3347 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap)
  3376 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap)
  3348 {
  3377 {
  3349 	rollback_data_t cb = { 0 };
  3378 	rollback_data_t cb = { 0 };
  3350 	int err;
  3379 	int err;
  3351 	zfs_cmd_t zc = { 0 };
  3380 	zfs_cmd_t zc = { 0 };
       
  3381 	boolean_t restore_resv = 0;
       
  3382 	uint64_t old_volsize, new_volsize;
       
  3383 	zfs_prop_t resv_prop;
  3352 
  3384 
  3353 	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
  3385 	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
  3354 	    zhp->zfs_type == ZFS_TYPE_VOLUME);
  3386 	    zhp->zfs_type == ZFS_TYPE_VOLUME);
  3355 
  3387 
  3356 	/*
  3388 	/*
  3366 	/*
  3398 	/*
  3367 	 * Now that we have verified that the snapshot is the latest,
  3399 	 * Now that we have verified that the snapshot is the latest,
  3368 	 * rollback to the given snapshot.
  3400 	 * rollback to the given snapshot.
  3369 	 */
  3401 	 */
  3370 
  3402 
  3371 	if (zhp->zfs_type == ZFS_TYPE_VOLUME &&
  3403 	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
  3372 	    zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0)
  3404 		if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0)
  3373 		return (-1);
  3405 			return (-1);
       
  3406 		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
       
  3407 			return (-1);
       
  3408 		old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
       
  3409 		restore_resv =
       
  3410 		    (old_volsize == zfs_prop_get_int(zhp, resv_prop));
       
  3411 	}
  3374 
  3412 
  3375 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
  3413 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
  3376 
  3414 
  3377 	if (ZFS_IS_VOLUME(zhp))
  3415 	if (ZFS_IS_VOLUME(zhp))
  3378 		zc.zc_objset_type = DMU_OST_ZVOL;
  3416 		zc.zc_objset_type = DMU_OST_ZVOL;
  3383 	 * We rely on zfs_iter_children() to verify that there are no
  3421 	 * We rely on zfs_iter_children() to verify that there are no
  3384 	 * newer snapshots for the given dataset.  Therefore, we can
  3422 	 * newer snapshots for the given dataset.  Therefore, we can
  3385 	 * simply pass the name on to the ioctl() call.  There is still
  3423 	 * simply pass the name on to the ioctl() call.  There is still
  3386 	 * an unlikely race condition where the user has taken a
  3424 	 * an unlikely race condition where the user has taken a
  3387 	 * snapshot since we verified that this was the most recent.
  3425 	 * snapshot since we verified that this was the most recent.
       
  3426 	 *
  3388 	 */
  3427 	 */
  3389 	if ((err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_ROLLBACK, &zc)) != 0) {
  3428 	if ((err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_ROLLBACK, &zc)) != 0) {
  3390 		(void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
  3429 		(void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
  3391 		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
  3430 		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
  3392 		    zhp->zfs_name);
  3431 		    zhp->zfs_name);
  3393 	} else if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
  3432 	} else if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
       
  3433 
       
  3434 	/*
       
  3435 	 * For volumes, if the pre-rollback volsize matched the pre-
       
  3436 	 * rollback reservation and the volsize has changed then set
       
  3437 	 * the reservation property to the post-rollback volsize.
       
  3438 	 * Make a new handle since the rollback closed the dataset.
       
  3439 	 */
       
  3440 		zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name);
       
  3441 		if (!zhp)
       
  3442 			return (err);
       
  3443 
       
  3444 		if (restore_resv) {
       
  3445 			new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
       
  3446 			if (old_volsize != new_volsize)
       
  3447 				zfs_prop_set_int(zhp, resv_prop, new_volsize);
       
  3448 		}
  3394 		err = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
  3449 		err = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
  3395 	}
  3450 		zfs_close(zhp);
  3396 
  3451 	}
  3397 	return (err);
  3452 	return (err);
  3398 }
  3453 }
  3399 
  3454 
  3400 /*
  3455 /*
  3401  * Iterate over all dependents for a given dataset.  This includes both
  3456  * Iterate over all dependents for a given dataset.  This includes both