Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lzc_receive_with_header: allow caller to access information in begin header #14

Open
wants to merge 2 commits into
base: libzfs_core-wip
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion include/libzfs_core.h
Original file line number Diff line number Diff line change
@@ -66,10 +66,15 @@ enum lzc_send_flags {
};

int lzc_send(const char *, const char *, int, enum lzc_send_flags);
int lzc_receive(const char *, nvlist_t *, const char *, boolean_t, int);
int lzc_send_space(const char *, const char *, uint64_t *);
int lzc_send_progress(const char *, int, uint64_t *);

struct dmu_replay_record;

int lzc_receive(const char *, nvlist_t *, const char *, boolean_t, int);
int lzc_receive_with_header(const char *, nvlist_t *, const char *, boolean_t,
boolean_t, int, const struct dmu_replay_record *);

boolean_t lzc_exists(const char *);

int lzc_rollback(const char *, char *, int);
89 changes: 54 additions & 35 deletions lib/libzfs_core/libzfs_core.c
Original file line number Diff line number Diff line change
@@ -594,22 +594,9 @@ recv_read(int fd, void *buf, int ilen)
return (0);
}

/*
* The simplest receive case: receive from the specified fd, creating the
* specified snapshot. Apply the specified properties a "received" properties
* (which can be overridden by locally-set properties). If the stream is a
* clone, its origin snapshot must be specified by 'origin'. The 'force'
* flag will cause the target filesystem to be rolled back or destroyed if
* necessary to receive.
*
* Return 0 on success or an errno on failure.
*
* Note: this interface does not work on dedup'd streams
* (those with DMU_BACKUP_FEATURE_DEDUP).
*/
int
lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, int fd)
static int
recv_impl(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, int fd, const dmu_replay_record_t *begin_record)
{
/*
* The receive ioctl is still legacy, so we need to construct our own
@@ -627,8 +614,9 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
/* zc_name is name of containing filesystem */
(void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name));
atp = strchr(zc.zc_name, '@');
if (atp != NULL)
*atp = '\0';
if (atp == NULL)
return (EINVAL);
*atp = '\0';

/* if the fs does not exist, try its parent. */
if (!lzc_exists(zc.zc_name)) {
@@ -639,6 +627,9 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,

}

/* zc_value is full name of the snapshot to create */
(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));

if (props != NULL) {
/* zc_nvlist_src is props to set */
packed = fnvlist_pack(props, &size);
@@ -651,23 +642,13 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
(void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string));

/* zc_begin_record is non-byteswapped BEGIN record */
error = recv_read(fd, &drr, sizeof (drr));
if (error != 0)
goto out;
zc.zc_begin_record = drr.drr_u.drr_begin;

/* zc_value is full name of the snapshot to create */
(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));

/* if snapshot name is not provided try to take it from the stream */
atp = strchr(zc.zc_value, '@');
if (atp == NULL) {
atp = strchr(zc.zc_begin_record.drr_toname, '@');
if (atp == NULL)
return (EINVAL);
if (strlen(zc.zc_value) + strlen(atp) >= sizeof (zc.zc_value))
return (ENAMETOOLONG);
strcat(zc.zc_value, atp);
if (begin_record == NULL) {
error = recv_read(fd, &drr, sizeof (drr));
if (error != 0)
goto out;
zc.zc_begin_record = drr.drr_u.drr_begin;
} else {
zc.zc_begin_record = begin_record->drr_u.drr_begin;
}

/* zc_cookie is fd to read from */
@@ -690,6 +671,44 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
return (error);
}

/*
* The simplest receive case: receive from the specified fd, creating the
* specified snapshot. Apply the specified properties as "received" properties
* (which can be overridden by locally-set properties). If the stream is a
* clone, its origin snapshot must be specified by 'origin'. The 'force'
* flag will cause the target filesystem to be rolled back or destroyed if
* necessary to receive.
*
* Return 0 on success or an errno on failure.
*
* Note: this interface does not work on dedup'd streams
* (those with DMU_BACKUP_FEATURE_DEDUP).
*/
int
lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, int fd)
{
return (recv_impl(snapname, props, origin, force, fd, NULL));
}

/*
* Like lzc_receive, but allows the caller to read the begin record and then to
* pass it in. That could be useful if the caller wants to derive, for example,
* the snapname or the origin parameters based on the information contained in
* the begin record.
* The begin record must be in its original form as read from the stream,
* in other words, it should not be byteswapped.
*/
int
lzc_receive_with_header(const char *snapname, nvlist_t *props,
const char *origin, boolean_t force, boolean_t resumable, int fd,
const dmu_replay_record_t *begin_record)
{
if (begin_record == NULL)
return (EINVAL);
return (recv_impl(snapname, props, origin, force, fd, begin_record));
}

/*
* Roll back this filesystem or volume to its most recent snapshot.
* If snapnamebuf is not NULL, it will be filled in with the name