Skip to content

Commit

Permalink
zfs receive fix
Browse files Browse the repository at this point in the history
Signed-off-by: Ameer Hamza <[email protected]>
  • Loading branch information
ixhamza committed Jan 22, 2025
1 parent aaeb7fa commit 63a7d3f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
28 changes: 23 additions & 5 deletions cmd/zfs/zfs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ static int zfs_do_unzone(int argc, char **argv);
static int zfs_do_help(int argc, char **argv);

enum zfs_options {
ZFS_OPTION_JSON_NUMS_AS_INT = 1024
ZFS_OPTION_JSON_NUMS_AS_INT = 1024,
ZFS_OPTION_FORCE_PRESERVE_OLD = 1025
};

/*
Expand Down Expand Up @@ -321,11 +322,11 @@ get_usage(zfs_help_t idx)
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
return (gettext("\treceive [-vMnsFhu] "
return (gettext("\treceive [-vMnshu] [-F [--preserve-old]] "
"[-o <property>=<value>] ... [-x <property>] ...\n"
"\t <filesystem|volume|snapshot>\n"
"\treceive [-vMnsFhu] [-o <property>=<value>] ... "
"[-x <property>] ... \n"
"\treceive [-vMnshu] [-F [--preserve-old]] "
"[-o <property>=<value>] ... [-x <property>] ... \n"
"\t [-d | -e] <filesystem>\n"
"\treceive -A <filesystem|volume>\n"));
case HELP_RENAME:
Expand Down Expand Up @@ -5130,8 +5131,16 @@ zfs_do_receive(int argc, char **argv)
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
nomem();

struct option long_options[] = {
{"force", no_argument, NULL, 'F'},
{"preserve-old", no_argument, NULL,
ZFS_OPTION_FORCE_PRESERVE_OLD},
{0, 0, 0, 0}
};

/* check options */
while ((c = getopt(argc, argv, ":o:x:dehMnuvFsAc")) != -1) {
while ((c = getopt_long(argc, argv, ":o:x:dehMnuvFsAc", long_options,
NULL)) != -1) {
switch (c) {
case 'o':
if (!parseprop(props, optarg)) {
Expand Down Expand Up @@ -5184,6 +5193,9 @@ zfs_do_receive(int argc, char **argv)
case 'F':
flags.force = B_TRUE;
break;
case ZFS_OPTION_FORCE_PRESERVE_OLD:
flags.preserveold = B_TRUE;
break;
case 'A':
abort_resumable = B_TRUE;
break;
Expand Down Expand Up @@ -5219,6 +5231,12 @@ zfs_do_receive(int argc, char **argv)
usage(B_FALSE);
}

if (!flags.force && flags.preserveold) {
(void) fprintf(stderr, gettext("'--preserve-old' only works"
"'-F' option\n"));
usage(B_FALSE);
}

if (abort_resumable) {
if (flags.isprefix || flags.istail || flags.dryrun ||
flags.resumable || flags.nomount) {
Expand Down
3 changes: 3 additions & 0 deletions include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,9 @@ typedef struct recvflags {
/* rollback/destroy filesystems as necessary (eg, -F) */
boolean_t force;

/* preserve deletion of old snapshots, used in conjunction with -F */
boolean_t preserveold;

/* set "canmount=off" on all modified filesystems */
boolean_t canmountoff;

Expand Down
18 changes: 16 additions & 2 deletions lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
Expand Up @@ -3545,6 +3545,7 @@ recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
nvlist_t *stream_nvfs = NULL;
nvpair_t *snapelem, *nextsnapelem;
uint64_t fromguid = 0;
uint64_t stream_guid = 0;
uint64_t originguid = 0;
uint64_t stream_originguid = 0;
uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
Expand All @@ -3570,8 +3571,10 @@ recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
thisguid = fnvpair_value_uint64(snapelem);
stream_nvfs = fsavl_find(stream_avl, thisguid, NULL);

if (stream_nvfs != NULL)
if (stream_nvfs != NULL) {
stream_guid = thisguid;
break;
}
}

/* check for promote */
Expand Down Expand Up @@ -3630,6 +3633,16 @@ recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
if (!flags->force)
continue;

/*
* If we have --preserve-old flag set, check
* current snapshot birth with the one found
* in the stream. Only delete recent snapshots
* but preserve older ones.
*/
if (flags->preserveold && created_before(hdl,
local_avl, thisguid, stream_guid) == -1)
continue;

(void) snprintf(name, sizeof (name), "%s@%s",
fsname, nvpair_name(snapelem));

Expand Down Expand Up @@ -3686,7 +3699,8 @@ recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,

/* check for delete */
if (stream_nvfs == NULL) {
if (!flags->force)
if (!flags->force || nvlist_next_nvpair(snaps,
NULL) == NULL)
continue;

error = recv_destroy(hdl, fsname, strlen(tofs)+1,
Expand Down

0 comments on commit 63a7d3f

Please sign in to comment.