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) { |
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 |