From cf7684bc8d57ace26d086027e8059c725fd9ff92 Mon Sep 17 00:00:00 2001 From: LOLi Date: Thu, 31 Aug 2017 18:00:35 +0200 Subject: [PATCH] Retire send space estimation via ZFS_IOC_SEND Add a small wrapper around libzfs_core`lzc_send_space() to libzfs so that every legacy ZFS_IOC_SEND consumer, along with their userland counterpart estimate_ioctl(), can leverage ZFS_IOC_SEND_SPACE to request send space estimation. The legacy functionality in zfs_ioc_send() is left untouched for compatibility purposes. Reviewed by: Thomas Caputi Reviewed-by: Brian Behlendorf Signed-off-by: loli10K Closes #6029 --- lib/libzfs/libzfs_sendrecv.c | 55 ++++++++++++++++++----------------- lib/libzfs_core/libzfs_core.c | 2 ++ module/zfs/zfs_ioctl.c | 5 ++++ 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 3146b4e61..fddcd9c02 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -1013,39 +1013,32 @@ typedef struct send_dump_data { } send_dump_data_t; static int -estimate_ioctl(zfs_handle_t *zhp, uint64_t fromsnap_obj, - boolean_t fromorigin, enum lzc_send_flags flags, uint64_t *sizep) +zfs_send_space(zfs_handle_t *zhp, const char *snapname, const char *from, + enum lzc_send_flags flags, uint64_t *spacep) { - zfs_cmd_t zc = {"\0"}; libzfs_handle_t *hdl = zhp->zfs_hdl; + int error; - assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); - assert(fromsnap_obj == 0 || !fromorigin); + assert(snapname != NULL); + error = lzc_send_space(snapname, from, flags, spacep); - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - zc.zc_obj = fromorigin; - zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID); - zc.zc_fromobj = fromsnap_obj; - zc.zc_guid = 1; /* estimate flag */ - zc.zc_flags = flags; - - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) { + if (error != 0) { char errbuf[1024]; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "warning: cannot estimate space for '%s'"), zhp->zfs_name); + "warning: cannot estimate space for '%s'"), snapname); - switch (errno) { + switch (error) { case EXDEV: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "not an earlier snapshot from the same fs")); return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); case ENOENT: - if (zfs_dataset_exists(hdl, zc.zc_name, + if (zfs_dataset_exists(hdl, snapname, ZFS_TYPE_SNAPSHOT)) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "incremental source (@%s) does not exist"), - zc.zc_value); + "incremental source (%s) does not exist"), + snapname); } return (zfs_error(hdl, EZFS_NOENT, errbuf)); @@ -1060,16 +1053,15 @@ estimate_ioctl(zfs_handle_t *zhp, uint64_t fromsnap_obj, case ERANGE: case EFAULT: case EROFS: - zfs_error_aux(hdl, strerror(errno)); + case EINVAL: + zfs_error_aux(hdl, strerror(error)); return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); default: - return (zfs_standard_error(hdl, errno, errbuf)); + return (zfs_standard_error(hdl, error, errbuf)); } } - *sizep = zc.zc_objset_type; - return (0); } @@ -1355,12 +1347,21 @@ dump_snapshot(zfs_handle_t *zhp, void *arg) if (sdd->verbose) { uint64_t size = 0; - (void) estimate_ioctl(zhp, sdd->prevsnap_obj, - fromorigin, flags, &size); + char fromds[ZFS_MAX_DATASET_NAME_LEN]; - send_print_verbose(fout, zhp->zfs_name, - sdd->prevsnap[0] ? sdd->prevsnap : NULL, - size, sdd->parsable); + if (sdd->prevsnap[0] != '\0') { + (void) strlcpy(fromds, zhp->zfs_name, sizeof (fromds)); + *(strchr(fromds, '@') + 1) = '\0'; + (void) strlcat(fromds, sdd->prevsnap, sizeof (fromds)); + } + if (zfs_send_space(zhp, zhp->zfs_name, + sdd->prevsnap[0] ? fromds : NULL, flags, &size) != 0) { + size = 0; /* cannot estimate send space */ + } else { + send_print_verbose(fout, zhp->zfs_name, + sdd->prevsnap[0] ? sdd->prevsnap : NULL, + size, sdd->parsable); + } sdd->size += size; } diff --git a/lib/libzfs_core/libzfs_core.c b/lib/libzfs_core/libzfs_core.c index 8c3272da6..cc663f9dd 100644 --- a/lib/libzfs_core/libzfs_core.c +++ b/lib/libzfs_core/libzfs_core.c @@ -590,6 +590,8 @@ lzc_send_space(const char *snapname, const char *from, fnvlist_add_boolean(args, "embedok"); if (flags & LZC_SEND_FLAG_COMPRESS) fnvlist_add_boolean(args, "compressok"); + if (flags & LZC_SEND_FLAG_RAW) + fnvlist_add_boolean(args, "rawok"); err = lzc_ioctl(ZFS_IOC_SEND_SPACE, snapname, args, &result); nvlist_free(args); if (err == 0) diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index b51b3b79c..f6291ce59 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -4758,6 +4758,9 @@ zfs_ioc_recv_new(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl) * * outputs: * zc_objset_type estimated size, if zc_guid is set + * + * NOTE: This is no longer the preferred interface, any new functionality + * should be added to zfs_ioc_send_new() instead. */ static int zfs_ioc_send(zfs_cmd_t *zc) @@ -5876,6 +5879,8 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl) * presence indicates DRR_WRITE_EMBEDDED records are permitted * (optional) "compressok" -> (value ignored) * presence indicates compressed DRR_WRITE records are permitted + * (optional) "rawok" -> (value ignored) + * presence indicates raw encrypted records should be used. * } * * outnvl: { -- 2.40.0