mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
libzfs, libzfs_core: send: always write to pipe
By introducing lzc_send_wrapper() and routing all ZFS_IOC_SEND* users through it, we fix a Linux 5.10-introduced bug (see comment) This is all /transparent/ to the users API, ABI, and usage-wise, and disabled on FreeBSD and if the output is already a pipe, and transparently nestable (i.e. zfs_send_one() is wrapped, but so is lzc_send_redacted() it calls to ‒ this wouldn't be strictly necessary if ZFS_IOC_SEND_PROGRESS wasn't strictly denominational w.r.t. the descriptor the send is happening on) Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Paul Dagnelie <pcd@delphix.com> Co-authored-by: Rich Ercolani <rincebrain@gmail.com> Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> Closes #11445 Closes #13133
This commit is contained in:
@@ -1682,8 +1682,8 @@ lzc_flags_from_resume_nvl(nvlist_t *resume_nvl)
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
nvlist_t *resume_nvl)
|
||||
zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
|
||||
int outfd, nvlist_t *resume_nvl)
|
||||
{
|
||||
char errbuf[1024];
|
||||
char *toname;
|
||||
@@ -1893,6 +1893,32 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
return (error);
|
||||
}
|
||||
|
||||
struct zfs_send_resume_impl {
|
||||
libzfs_handle_t *hdl;
|
||||
sendflags_t *flags;
|
||||
nvlist_t *resume_nvl;
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_send_resume_impl_cb(int outfd, void *arg)
|
||||
{
|
||||
struct zfs_send_resume_impl *zsri = arg;
|
||||
return (zfs_send_resume_impl_cb_impl(zsri->hdl, zsri->flags, outfd,
|
||||
zsri->resume_nvl));
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
nvlist_t *resume_nvl)
|
||||
{
|
||||
struct zfs_send_resume_impl zsri = {
|
||||
.hdl = hdl,
|
||||
.flags = flags,
|
||||
.resume_nvl = resume_nvl,
|
||||
};
|
||||
return (lzc_send_wrapper(zfs_send_resume_impl_cb, outfd, &zsri));
|
||||
}
|
||||
|
||||
int
|
||||
zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
const char *resume_token)
|
||||
@@ -2170,9 +2196,11 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd,
|
||||
* if "replicate" is set. If "doall" is set, dump all the intermediate
|
||||
* snapshots. The DMU_COMPOUNDSTREAM header is used in the "doall"
|
||||
* case too. If "props" is set, send properties.
|
||||
*
|
||||
* Pre-wrapped (cf. lzc_send_wrapper()).
|
||||
*/
|
||||
int
|
||||
zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||
static int
|
||||
zfs_send_cb_impl(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||
sendflags_t *flags, int outfd, snapfilter_cb_t filter_func,
|
||||
void *cb_arg, nvlist_t **debugnvp)
|
||||
{
|
||||
@@ -2374,6 +2402,42 @@ err_out:
|
||||
return (err);
|
||||
}
|
||||
|
||||
struct zfs_send {
|
||||
zfs_handle_t *zhp;
|
||||
const char *fromsnap;
|
||||
const char *tosnap;
|
||||
sendflags_t *flags;
|
||||
snapfilter_cb_t *filter_func;
|
||||
void *cb_arg;
|
||||
nvlist_t **debugnvp;
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_send_cb(int outfd, void *arg)
|
||||
{
|
||||
struct zfs_send *zs = arg;
|
||||
return (zfs_send_cb_impl(zs->zhp, zs->fromsnap, zs->tosnap, zs->flags,
|
||||
outfd, zs->filter_func, zs->cb_arg, zs->debugnvp));
|
||||
}
|
||||
|
||||
int
|
||||
zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||
sendflags_t *flags, int outfd, snapfilter_cb_t filter_func,
|
||||
void *cb_arg, nvlist_t **debugnvp)
|
||||
{
|
||||
struct zfs_send arg = {
|
||||
.zhp = zhp,
|
||||
.fromsnap = fromsnap,
|
||||
.tosnap = tosnap,
|
||||
.flags = flags,
|
||||
.filter_func = filter_func,
|
||||
.cb_arg = cb_arg,
|
||||
.debugnvp = debugnvp,
|
||||
};
|
||||
return (lzc_send_wrapper(zfs_send_cb, outfd, &arg));
|
||||
}
|
||||
|
||||
|
||||
static zfs_handle_t *
|
||||
name_to_dir_handle(libzfs_handle_t *hdl, const char *snapname)
|
||||
{
|
||||
@@ -2450,10 +2514,12 @@ snapshot_is_before(zfs_handle_t *earlier, zfs_handle_t *later)
|
||||
* The "zhp" argument is the handle of the dataset to send (typically a
|
||||
* snapshot). The "from" argument is the full name of the snapshot or
|
||||
* bookmark that is the incremental source.
|
||||
*
|
||||
* Pre-wrapped (cf. lzc_send_wrapper()).
|
||||
*/
|
||||
int
|
||||
zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
const char *redactbook)
|
||||
static int
|
||||
zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
|
||||
sendflags_t *flags, const char *redactbook)
|
||||
{
|
||||
int err;
|
||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||
@@ -2642,6 +2708,34 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
return (err != 0);
|
||||
}
|
||||
|
||||
struct zfs_send_one {
|
||||
zfs_handle_t *zhp;
|
||||
const char *from;
|
||||
sendflags_t *flags;
|
||||
const char *redactbook;
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_send_one_cb(int fd, void *arg)
|
||||
{
|
||||
struct zfs_send_one *zso = arg;
|
||||
return (zfs_send_one_cb_impl(zso->zhp, zso->from, fd, zso->flags,
|
||||
zso->redactbook));
|
||||
}
|
||||
|
||||
int
|
||||
zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
const char *redactbook)
|
||||
{
|
||||
struct zfs_send_one zso = {
|
||||
.zhp = zhp,
|
||||
.from = from,
|
||||
.flags = flags,
|
||||
.redactbook = redactbook,
|
||||
};
|
||||
return (lzc_send_wrapper(zfs_send_one_cb, fd, &zso));
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines specific to "zfs recv"
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user