26
26
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
27
27
* All rights reserved
28
28
* Copyright (c) 2013 Steven Hartland. All rights reserved.
29
+ * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
29
30
*/
30
31
31
32
#include <assert.h>
@@ -66,7 +67,7 @@ extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
66
67
67
68
static int zfs_receive_impl (libzfs_handle_t * , const char * , const char * ,
68
69
recvflags_t * , int , const char * , nvlist_t * , avl_tree_t * , char * * , int ,
69
- uint64_t * );
70
+ uint64_t * , const char * );
70
71
static int guid_to_name (libzfs_handle_t * , const char * ,
71
72
uint64_t , boolean_t , char * );
72
73
@@ -2621,6 +2622,7 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2621
2622
nvlist_t * stream_nv = NULL ;
2622
2623
avl_tree_t * stream_avl = NULL ;
2623
2624
char * fromsnap = NULL ;
2625
+ char * sendsnap = NULL ;
2624
2626
char * cp ;
2625
2627
char tofs [ZFS_MAXNAMELEN ];
2626
2628
char sendfs [ZFS_MAXNAMELEN ];
@@ -2769,8 +2771,16 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2769
2771
*/
2770
2772
(void ) strlcpy (sendfs , drr -> drr_u .drr_begin .drr_toname ,
2771
2773
ZFS_MAXNAMELEN );
2772
- if ((cp = strchr (sendfs , '@' )) != NULL )
2774
+ if ((cp = strchr (sendfs , '@' )) != NULL ) {
2773
2775
* cp = '\0' ;
2776
+ /*
2777
+ * Find the "sendsnap", the final snapshot in a replication
2778
+ * stream. zfs_receive_one() handles certain errors
2779
+ * differently, depending on if the contained stream is the
2780
+ * last one or not.
2781
+ */
2782
+ sendsnap = (cp + 1 );
2783
+ }
2774
2784
2775
2785
/* Finally, receive each contained stream */
2776
2786
do {
@@ -2783,7 +2793,7 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2783
2793
*/
2784
2794
error = zfs_receive_impl (hdl , destname , NULL , flags , fd ,
2785
2795
sendfs , stream_nv , stream_avl , top_zfs , cleanup_fd ,
2786
- action_handlep );
2796
+ action_handlep , sendsnap );
2787
2797
if (error == ENODATA ) {
2788
2798
error = 0 ;
2789
2799
break ;
@@ -2948,7 +2958,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2948
2958
const char * originsnap , recvflags_t * flags , dmu_replay_record_t * drr ,
2949
2959
dmu_replay_record_t * drr_noswap , const char * sendfs , nvlist_t * stream_nv ,
2950
2960
avl_tree_t * stream_avl , char * * top_zfs , int cleanup_fd ,
2951
- uint64_t * action_handlep )
2961
+ uint64_t * action_handlep , const char * finalsnap )
2952
2962
{
2953
2963
zfs_cmd_t zc = {"\0" };
2954
2964
time_t begin_time ;
@@ -2965,6 +2975,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2965
2975
nvlist_t * snapprops_nvlist = NULL ;
2966
2976
zprop_errflags_t prop_errflags ;
2967
2977
boolean_t recursive ;
2978
+ char * snapname = NULL ;
2968
2979
2969
2980
begin_time = time (NULL );
2970
2981
@@ -2975,7 +2986,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2975
2986
ENOENT );
2976
2987
2977
2988
if (stream_avl != NULL ) {
2978
- char * snapname ;
2979
2989
nvlist_t * fs = fsavl_find (stream_avl , drrb -> drr_toguid ,
2980
2990
& snapname );
2981
2991
nvlist_t * props ;
@@ -3316,7 +3326,21 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
3316
3326
ZPROP_N_MORE_ERRORS ) == 0 ) {
3317
3327
trunc_prop_errs (intval );
3318
3328
break ;
3319
- } else {
3329
+ } else if (snapname == NULL || finalsnap == NULL ||
3330
+ strcmp (finalsnap , snapname ) == 0 ||
3331
+ strcmp (nvpair_name (prop_err ),
3332
+ zfs_prop_to_name (ZFS_PROP_REFQUOTA )) != 0 ) {
3333
+ /*
3334
+ * Skip the special case of, for example,
3335
+ * "refquota", errors on intermediate
3336
+ * snapshots leading up to a final one.
3337
+ * That's why we have all of the checks above.
3338
+ *
3339
+ * See zfs_ioctl.c's extract_delay_props() for
3340
+ * a list of props which can fail on
3341
+ * intermediate snapshots, but shouldn't
3342
+ * affect the overall receive.
3343
+ */
3320
3344
(void ) snprintf (tbuf , sizeof (tbuf ),
3321
3345
dgettext (TEXT_DOMAIN ,
3322
3346
"cannot receive %s property on %s" ),
@@ -3501,7 +3525,7 @@ static int
3501
3525
zfs_receive_impl (libzfs_handle_t * hdl , const char * tosnap ,
3502
3526
const char * originsnap , recvflags_t * flags , int infd , const char * sendfs ,
3503
3527
nvlist_t * stream_nv , avl_tree_t * stream_avl , char * * top_zfs , int cleanup_fd ,
3504
- uint64_t * action_handlep )
3528
+ uint64_t * action_handlep , const char * finalsnap )
3505
3529
{
3506
3530
int err ;
3507
3531
dmu_replay_record_t drr , drr_noswap ;
@@ -3597,10 +3621,11 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
3597
3621
if ((cp = strchr (nonpackage_sendfs , '@' )) != NULL )
3598
3622
* cp = '\0' ;
3599
3623
sendfs = nonpackage_sendfs ;
3624
+ VERIFY (finalsnap == NULL );
3600
3625
}
3601
3626
return (zfs_receive_one (hdl , infd , tosnap , originsnap , flags ,
3602
3627
& drr , & drr_noswap , sendfs , stream_nv , stream_avl , top_zfs ,
3603
- cleanup_fd , action_handlep ));
3628
+ cleanup_fd , action_handlep , finalsnap ));
3604
3629
} else {
3605
3630
assert (DMU_GET_STREAM_HDRTYPE (drrb -> drr_versioninfo ) ==
3606
3631
DMU_COMPOUNDSTREAM );
@@ -3678,7 +3703,7 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
3678
3703
VERIFY (cleanup_fd >= 0 );
3679
3704
3680
3705
err = zfs_receive_impl (hdl , tosnap , originsnap , flags , infd , NULL , NULL ,
3681
- stream_avl , & top_zfs , cleanup_fd , & action_handle );
3706
+ stream_avl , & top_zfs , cleanup_fd , & action_handle , NULL );
3682
3707
3683
3708
VERIFY (0 == close (cleanup_fd ));
3684
3709
0 commit comments