Author: mav
Date: Tue Jan 26 13:20:31 2016
New Revision: 294816
URL: https://svnweb.freebsd.org/changeset/base/294816

Log:
  4986 receiving replication stream fails if any snapshot exceeds refquota
  
  Reviewed by: John Kennedy <[email protected]>
  Reviewed by: Matthew Ahrens <[email protected]>
  Approved by: Gordon Ross <[email protected]>
  Author: Dan McDonald <[email protected]>
  
  illumos/illumos-gate@5878fad70d76d8711f6608c1f80b0447601261c6

Modified:
  vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c

Changes in other areas also in this revision:
Modified:
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c     Tue Jan 26 
13:14:39 2016        (r294815)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c     Tue Jan 26 
13:20:31 2016        (r294816)
@@ -24,6 +24,7 @@
  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
+ * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 
 #include <assert.h>
@@ -58,7 +59,7 @@ extern void zfs_setprop_error(libzfs_han
 
 static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
     recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
-    uint64_t *);
+    uint64_t *, const char *);
 static int guid_to_name(libzfs_handle_t *, const char *,
     uint64_t, boolean_t, char *);
 
@@ -2561,6 +2562,7 @@ zfs_receive_package(libzfs_handle_t *hdl
        nvlist_t *stream_nv = NULL;
        avl_tree_t *stream_avl = NULL;
        char *fromsnap = NULL;
+       char *sendsnap = NULL;
        char *cp;
        char tofs[ZFS_MAXNAMELEN];
        char sendfs[ZFS_MAXNAMELEN];
@@ -2709,8 +2711,16 @@ zfs_receive_package(libzfs_handle_t *hdl
         */
        (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
            ZFS_MAXNAMELEN);
-       if ((cp = strchr(sendfs, '@')) != NULL)
+       if ((cp = strchr(sendfs, '@')) != NULL) {
                *cp = '\0';
+               /*
+                * Find the "sendsnap", the final snapshot in a replication
+                * stream.  zfs_receive_one() handles certain errors
+                * differently, depending on if the contained stream is the
+                * last one or not.
+                */
+               sendsnap = (cp + 1);
+       }
 
        /* Finally, receive each contained stream */
        do {
@@ -2723,7 +2733,7 @@ zfs_receive_package(libzfs_handle_t *hdl
                 */
                error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
                    sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
-                   action_handlep);
+                   action_handlep, sendsnap);
                if (error == ENODATA) {
                        error = 0;
                        break;
@@ -2889,7 +2899,7 @@ zfs_receive_one(libzfs_handle_t *hdl, in
     const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
     dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
     avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
-    uint64_t *action_handlep)
+    uint64_t *action_handlep, const char *finalsnap)
 {
        zfs_cmd_t zc = { 0 };
        time_t begin_time;
@@ -2906,6 +2916,7 @@ zfs_receive_one(libzfs_handle_t *hdl, in
        nvlist_t *snapprops_nvlist = NULL;
        zprop_errflags_t prop_errflags;
        boolean_t recursive;
+       char *snapname = NULL;
 
        begin_time = time(NULL);
 
@@ -2916,7 +2927,6 @@ zfs_receive_one(libzfs_handle_t *hdl, in
            ENOENT);
 
        if (stream_avl != NULL) {
-               char *snapname;
                nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
                    &snapname);
                nvlist_t *props;
@@ -3263,7 +3273,21 @@ zfs_receive_one(libzfs_handle_t *hdl, in
                            ZPROP_N_MORE_ERRORS) == 0) {
                                trunc_prop_errs(intval);
                                break;
-                       } else {
+                       } else if (snapname == NULL || finalsnap == NULL ||
+                           strcmp(finalsnap, snapname) == 0 ||
+                           strcmp(nvpair_name(prop_err),
+                           zfs_prop_to_name(ZFS_PROP_REFQUOTA)) != 0) {
+                               /*
+                                * Skip the special case of, for example,
+                                * "refquota", errors on intermediate
+                                * snapshots leading up to a final one.
+                                * That's why we have all of the checks above.
+                                *
+                                * See zfs_ioctl.c's extract_delay_props() for
+                                * a list of props which can fail on
+                                * intermediate snapshots, but shouldn't
+                                * affect the overall receive.
+                                */
                                (void) snprintf(tbuf, sizeof (tbuf),
                                    dgettext(TEXT_DOMAIN,
                                    "cannot receive %s property on %s"),
@@ -3448,7 +3472,7 @@ static int
 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
     const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
     nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int 
cleanup_fd,
-    uint64_t *action_handlep)
+    uint64_t *action_handlep, const char *finalsnap)
 {
        int err;
        dmu_replay_record_t drr, drr_noswap;
@@ -3544,10 +3568,11 @@ zfs_receive_impl(libzfs_handle_t *hdl, c
                        if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
                                *cp = '\0';
                        sendfs = nonpackage_sendfs;
+                       VERIFY(finalsnap == NULL);
                }
                return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
                    &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
-                   cleanup_fd, action_handlep));
+                   cleanup_fd, action_handlep, finalsnap));
        } else {
                assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
                    DMU_COMPOUNDSTREAM);
@@ -3582,7 +3607,7 @@ zfs_receive(libzfs_handle_t *hdl, const 
        VERIFY(cleanup_fd >= 0);
 
        err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
-           stream_avl, &top_zfs, cleanup_fd, &action_handle);
+           stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL);
 
        VERIFY(0 == close(cleanup_fd));
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to