MFV r308222: 6051 lzc_receive: allow the caller to read the begin record
illumos/illumos-gate@620f322510
620f322510
https://www.illumos.org/issues/6051
Currently lzc_receive() requires that its snapname argument is a snapshot name
(contains '@').
zfs receive allows to specify just a dataset name and would try to deduce the
snapshot name from the stream.
I propose to allow lzc_receive() to do the same.
That seems to be quite easy to implement, it requires only a small amount of
logic, it does not require any additional system calls or any additional data
from the stream.
The benefit is that the new behavior would allow to keep the snapshot names the
same between the sender and receiver at zero cost, without a need to pass the
names out of band.
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Author: Andriy Gapon <avg@icyb.net.ua>
MFC after: 2 weeks
This commit is contained in:
commit
d5315b02cd
@ -596,8 +596,9 @@ recv_read(int fd, void *buf, int ilen)
|
||||
}
|
||||
|
||||
static int
|
||||
lzc_receive_impl(const char *snapname, nvlist_t *props, const char *origin,
|
||||
boolean_t force, boolean_t resumable, int fd)
|
||||
recv_impl(const char *snapname, nvlist_t *props, const char *origin,
|
||||
boolean_t force, boolean_t resumable, int fd,
|
||||
const dmu_replay_record_t *begin_record)
|
||||
{
|
||||
/*
|
||||
* The receive ioctl is still legacy, so we need to construct our own
|
||||
@ -642,9 +643,14 @@ lzc_receive_impl(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, &zc.zc_begin_record, sizeof (zc.zc_begin_record));
|
||||
if (error != 0)
|
||||
goto out;
|
||||
if (begin_record == NULL) {
|
||||
error = recv_read(fd, &zc.zc_begin_record,
|
||||
sizeof (zc.zc_begin_record));
|
||||
if (error != 0)
|
||||
goto out;
|
||||
} else {
|
||||
zc.zc_begin_record = *begin_record;
|
||||
}
|
||||
|
||||
/* zc_cookie is fd to read from */
|
||||
zc.zc_cookie = fd;
|
||||
@ -685,7 +691,7 @@ int
|
||||
lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
|
||||
boolean_t force, int fd)
|
||||
{
|
||||
return (lzc_receive_impl(snapname, props, origin, force, B_FALSE, fd));
|
||||
return (recv_impl(snapname, props, origin, force, B_FALSE, fd, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -698,7 +704,29 @@ int
|
||||
lzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin,
|
||||
boolean_t force, int fd)
|
||||
{
|
||||
return (lzc_receive_impl(snapname, props, origin, force, B_TRUE, fd));
|
||||
return (recv_impl(snapname, props, origin, force, B_TRUE, 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.
|
||||
*
|
||||
* The 'resumable' parameter allows to obtain the same behavior as with
|
||||
* lzc_receive_resumable.
|
||||
*/
|
||||
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, resumable, fd,
|
||||
begin_record));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -68,10 +68,15 @@ enum lzc_send_flags {
|
||||
int lzc_send(const char *, const char *, int, enum lzc_send_flags);
|
||||
int lzc_send_resume(const char *, const char *, int,
|
||||
enum lzc_send_flags, uint64_t, uint64_t);
|
||||
int lzc_send_space(const char *, const char *, uint64_t *);
|
||||
|
||||
struct dmu_replay_record;
|
||||
|
||||
int lzc_receive(const char *, nvlist_t *, const char *, boolean_t, int);
|
||||
int lzc_receive_resumable(const char *, nvlist_t *, const char *,
|
||||
boolean_t, int);
|
||||
int lzc_send_space(const char *, const char *, uint64_t *);
|
||||
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 *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user