]> granicus.if.org Git - zfs/commitdiff
Retire send space estimation via ZFS_IOC_SEND
authorLOLi <loli10K@users.noreply.github.com>
Thu, 31 Aug 2017 16:00:35 +0000 (18:00 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 31 Aug 2017 16:00:35 +0000 (09:00 -0700)
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 <tcaputi@datto.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #6029

lib/libzfs/libzfs_sendrecv.c
lib/libzfs_core/libzfs_core.c
module/zfs/zfs_ioctl.c

index 3146b4e617c6fd1a310efdb3375e30ffe7916707..fddcd9c02fc855bad18b3bffcf6506d39ea046bc 100644 (file)
@@ -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;
        }
 
index 8c3272da6d84de35aa81726f8d29e52178c39151..cc663f9dd45c403d18bb4140a091a94b7197cd0b 100644 (file)
@@ -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)
index b51b3b79c40ec8325cb6d90dbc4e6e7c9c0e8d28..f6291ce59a62b1ab74df46f84c9a960f92736ec3 100644 (file)
@@ -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: {