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:
parent
fbbea09db9
commit
3a909fe33e
|
@ -86,6 +86,7 @@ enum lzc_send_flags {
|
|||
LZC_SEND_FLAG_SAVED = 1 << 4,
|
||||
};
|
||||
|
||||
_LIBZFS_CORE_H int lzc_send_wrapper(int (*)(int, void *), int, void *);
|
||||
_LIBZFS_CORE_H int lzc_send(const char *, const char *, int,
|
||||
enum lzc_send_flags);
|
||||
_LIBZFS_CORE_H int lzc_send_resume(const char *, const char *, int,
|
||||
|
|
|
@ -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"
|
||||
*/
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
<dependency name='ld-linux-x86-64.so.2'/>
|
||||
</elf-needed>
|
||||
<elf-function-symbols>
|
||||
<elf-symbol name='_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='_sol_getmntent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='atomic_add_16' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='atomic_add_16_nv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
|
@ -195,6 +193,7 @@
|
|||
<elf-symbol name='lzc_send_resume_redacted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_send_space' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_send_space_resume_redacted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_send_wrapper' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_set_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_set_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_snaprange_space' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
|
@ -215,14 +214,12 @@
|
|||
<elf-symbol name='strlcat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
</elf-function-symbols>
|
||||
<elf-variable-symbols>
|
||||
</elf-variable-symbols>
|
||||
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
|
||||
<type-decl name='variadic parameter type' id='2c1145c5'/>
|
||||
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
|
||||
<parameter type-id='f58c8277' name='val'/>
|
||||
<parameter type-id='c19b74c3' name='val'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<type-decl name='variadic parameter type' id='2c1145c5'/>
|
||||
<function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
|
||||
<parameter type-id='80f4b756' name='file'/>
|
||||
<parameter type-id='80f4b756' name='func'/>
|
||||
|
@ -246,7 +243,6 @@
|
|||
<typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
|
||||
<typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/>
|
||||
<typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
|
||||
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
|
||||
<qualified-type-def type-id='149c6638' volatile='yes' id='5120c5f7'/>
|
||||
<pointer-type-def type-id='5120c5f7' size-in-bits='64' id='93977ae7'/>
|
||||
<qualified-type-def type-id='8f92235e' volatile='yes' id='430e0681'/>
|
||||
|
@ -289,6 +285,11 @@
|
|||
<parameter type-id='64698d33' name='target'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_add_ptr' mangled-name='atomic_add_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_ptr'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='79a0948f' name='bits'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_add_8' mangled-name='atomic_add_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_8'>
|
||||
<parameter type-id='aa323ea4' name='target'/>
|
||||
<parameter type-id='ee31ee44' name='bits'/>
|
||||
|
@ -309,7 +310,7 @@
|
|||
<parameter type-id='bd54fe1a' name='bits'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_add_ptr' mangled-name='atomic_add_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_ptr'>
|
||||
<function-decl name='atomic_sub_ptr' mangled-name='atomic_sub_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='79a0948f' name='bits'/>
|
||||
<return type-id='48b5725f'/>
|
||||
|
@ -334,11 +335,6 @@
|
|||
<parameter type-id='bd54fe1a' name='bits'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_sub_ptr' mangled-name='atomic_sub_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='79a0948f' name='bits'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_or_8' mangled-name='atomic_or_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_8'>
|
||||
<parameter type-id='aa323ea4' name='target'/>
|
||||
<parameter type-id='b96825af' name='bits'/>
|
||||
|
@ -411,6 +407,11 @@
|
|||
<parameter type-id='64698d33' name='target'/>
|
||||
<return type-id='ee1f298e'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_add_ptr_nv' mangled-name='atomic_add_ptr_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_ptr_nv'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='79a0948f' name='bits'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_add_8_nv' mangled-name='atomic_add_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_8_nv'>
|
||||
<parameter type-id='aa323ea4' name='target'/>
|
||||
<parameter type-id='ee31ee44' name='bits'/>
|
||||
|
@ -431,7 +432,7 @@
|
|||
<parameter type-id='bd54fe1a' name='bits'/>
|
||||
<return type-id='ee1f298e'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_add_ptr_nv' mangled-name='atomic_add_ptr_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_ptr_nv'>
|
||||
<function-decl name='atomic_sub_ptr_nv' mangled-name='atomic_sub_ptr_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr_nv'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='79a0948f' name='bits'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
|
@ -456,11 +457,6 @@
|
|||
<parameter type-id='bd54fe1a' name='bits'/>
|
||||
<return type-id='ee1f298e'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_sub_ptr_nv' mangled-name='atomic_sub_ptr_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr_nv'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='79a0948f' name='bits'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_or_8_nv' mangled-name='atomic_or_8_nv' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_8_nv'>
|
||||
<parameter type-id='aa323ea4' name='target'/>
|
||||
<parameter type-id='b96825af' name='bits'/>
|
||||
|
@ -501,6 +497,12 @@
|
|||
<parameter type-id='ee1f298e' name='bits'/>
|
||||
<return type-id='ee1f298e'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_cas_ptr' mangled-name='atomic_cas_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_ptr'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='eaa32e2f' name='exp'/>
|
||||
<parameter type-id='eaa32e2f' name='des'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_cas_8' mangled-name='atomic_cas_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_8'>
|
||||
<parameter type-id='aa323ea4' name='target'/>
|
||||
<parameter type-id='b96825af' name='exp'/>
|
||||
|
@ -525,12 +527,6 @@
|
|||
<parameter type-id='ee1f298e' name='des'/>
|
||||
<return type-id='ee1f298e'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_cas_ptr' mangled-name='atomic_cas_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_cas_ptr'>
|
||||
<parameter type-id='fe09dd29' name='target'/>
|
||||
<parameter type-id='eaa32e2f' name='exp'/>
|
||||
<parameter type-id='eaa32e2f' name='des'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='atomic_swap_8' mangled-name='atomic_swap_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_8'>
|
||||
<parameter type-id='aa323ea4' name='target'/>
|
||||
<parameter type-id='b96825af' name='bits'/>
|
||||
|
@ -718,6 +714,9 @@
|
|||
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
|
||||
<subrange length='20' type-id='7359adad' id='fdca39cf'/>
|
||||
</array-type-def>
|
||||
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
|
||||
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
|
||||
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
|
||||
<class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
|
||||
|
@ -752,18 +751,66 @@
|
|||
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
|
||||
<class-decl name='_IO_marker' size-in-bits='192' is-struct='yes' visibility='default' id='010ae0b9'>
|
||||
<class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='_next' type-id='e4c6fa61' visibility='default'/>
|
||||
<var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='_sbuf' type-id='dca988a5' visibility='default'/>
|
||||
<var-decl name='st_ino' type-id='71288a47' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='_pos' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='st_mode' type-id='e1c52942' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='224'>
|
||||
<var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='288'>
|
||||
<var-decl name='__pad0' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='st_rdev' type-id='35ed8932' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='st_size' type-id='79989e9c' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='st_blocks' type-id='4e711bf1' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='576'>
|
||||
<var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='704'>
|
||||
<var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='832'>
|
||||
<var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='960'>
|
||||
<var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__dev_t' type-id='7359adad' id='35ed8932'/>
|
||||
<typedef-decl name='__uid_t' type-id='f0981eeb' id='cc5fcceb'/>
|
||||
<typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
|
||||
<typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/>
|
||||
<typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
|
||||
<typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
|
||||
<typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
|
||||
<typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
|
||||
<typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
|
||||
<typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
|
||||
<typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
|
||||
<typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
|
||||
<typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
|
||||
<class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
|
||||
|
@ -832,16 +879,16 @@
|
|||
<var-decl name='_offset' type-id='724e4de6' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1216'>
|
||||
<var-decl name='__pad1' type-id='eaa32e2f' visibility='default'/>
|
||||
<var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1280'>
|
||||
<var-decl name='__pad2' type-id='eaa32e2f' visibility='default'/>
|
||||
<var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1344'>
|
||||
<var-decl name='__pad3' type-id='eaa32e2f' visibility='default'/>
|
||||
<var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1408'>
|
||||
<var-decl name='__pad4' type-id='eaa32e2f' visibility='default'/>
|
||||
<var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1472'>
|
||||
<var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
|
||||
|
@ -853,65 +900,6 @@
|
|||
<var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='st_ino' type-id='71288a47' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='st_mode' type-id='e1c52942' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='224'>
|
||||
<var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='288'>
|
||||
<var-decl name='__pad0' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='st_rdev' type-id='35ed8932' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='st_size' type-id='79989e9c' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='st_blocks' type-id='4e711bf1' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='576'>
|
||||
<var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='704'>
|
||||
<var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='832'>
|
||||
<var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='960'>
|
||||
<var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__dev_t' type-id='7359adad' id='35ed8932'/>
|
||||
<typedef-decl name='__uid_t' type-id='f0981eeb' id='cc5fcceb'/>
|
||||
<typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
|
||||
<typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/>
|
||||
<typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
|
||||
<typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
|
||||
<typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
|
||||
<typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
|
||||
<typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
|
||||
<typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
|
||||
<typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
|
||||
<typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
|
||||
<class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/>
|
||||
|
@ -922,11 +910,16 @@
|
|||
</class-decl>
|
||||
<pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
|
||||
<pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
|
||||
<pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
|
||||
<pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
|
||||
<pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
|
||||
<pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
|
||||
<pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
|
||||
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
|
||||
<pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
|
||||
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
|
||||
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
|
||||
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
|
||||
<function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'>
|
||||
<parameter type-id='822cd80b' name='fp'/>
|
||||
<parameter type-id='9d424d31' name='mgetp'/>
|
||||
|
@ -1012,6 +1005,7 @@
|
|||
<type-decl name='unsigned char' size-in-bits='8' id='002ac4a6'/>
|
||||
<type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
|
||||
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
|
||||
<type-decl name='void' id='48b5725f'/>
|
||||
<enum-decl name='lzc_dataset_type' id='bc9887f1'>
|
||||
<underlying-type type-id='9cac1fee'/>
|
||||
<enumerator name='LZC_DATSET_TYPE_ZFS' value='2'/>
|
||||
|
@ -1574,10 +1568,12 @@
|
|||
<pointer-type-def type-id='9623bc03' size-in-bits='64' id='8341348b'/>
|
||||
<qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
|
||||
<pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
|
||||
<pointer-type-def type-id='c70fa2e8' size-in-bits='64' id='2e711a2a'/>
|
||||
<pointer-type-def type-id='8e8d4be3' size-in-bits='64' id='5ce45b60'/>
|
||||
<pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/>
|
||||
<pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/>
|
||||
<pointer-type-def type-id='b96825af' size-in-bits='64' id='ae3e8ca6'/>
|
||||
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
|
||||
<function-decl name='libzfs_core_init' mangled-name='libzfs_core_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_core_init'>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
|
@ -1657,6 +1653,12 @@
|
|||
<parameter type-id='857bb57e' name='holdsp'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzc_send_wrapper' mangled-name='lzc_send_wrapper' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_send_wrapper'>
|
||||
<parameter type-id='2e711a2a' name='func'/>
|
||||
<parameter type-id='95e97e5e' name='orig_fd'/>
|
||||
<parameter type-id='eaa32e2f' name='data'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzc_send' mangled-name='lzc_send' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_send'>
|
||||
<parameter type-id='80f4b756' name='snapname'/>
|
||||
<parameter type-id='80f4b756' name='from'/>
|
||||
|
@ -1919,7 +1921,11 @@
|
|||
<parameter type-id='857bb57e' name='outnvl'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<type-decl name='void' id='48b5725f'/>
|
||||
<function-type size-in-bits='64' id='c70fa2e8'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-type>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='os/linux/libzfs_core_ioctl.c' language='LANG_C99'>
|
||||
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32768' id='d16c6df4'>
|
||||
|
|
|
@ -617,6 +617,84 @@ max_pipe_buffer(int infd)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
struct send_worker_ctx {
|
||||
int from; /* read end of pipe, with send data; closed on exit */
|
||||
int to; /* original arbitrary output fd; mustn't be a pipe */
|
||||
};
|
||||
|
||||
static void *
|
||||
send_worker(void *arg)
|
||||
{
|
||||
struct send_worker_ctx *ctx = arg;
|
||||
unsigned int bufsiz = max_pipe_buffer(ctx->from);
|
||||
ssize_t rd;
|
||||
|
||||
while ((rd = splice(ctx->from, NULL, ctx->to, NULL, bufsiz,
|
||||
SPLICE_F_MOVE | SPLICE_F_MORE)) > 0)
|
||||
;
|
||||
|
||||
int err = (rd == -1) ? errno : 0;
|
||||
close(ctx->from);
|
||||
return ((void *)(uintptr_t)err);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Since Linux 5.10, 4d03e3cc59828c82ee89ea6e27a2f3cdf95aaadf
|
||||
* ("fs: don't allow kernel reads and writes without iter ops"),
|
||||
* ZFS_IOC_SEND* will EINVAL when writing to /dev/null, /dev/zero, &c.
|
||||
*
|
||||
* This wrapper transparently executes func() with a pipe
|
||||
* by spawning a thread to copy from that pipe to the original output
|
||||
* in the background.
|
||||
*
|
||||
* Returns the error from func(), if nonzero,
|
||||
* otherwise the error from the thread.
|
||||
*
|
||||
* No-op if orig_fd is -1, already a pipe, and on not-Linux;
|
||||
* as such, it is safe to wrap/call wrapped functions in a wrapped context.
|
||||
*/
|
||||
int
|
||||
lzc_send_wrapper(int (*func)(int, void *), int orig_fd, void *data)
|
||||
{
|
||||
#if __linux__
|
||||
struct stat sb;
|
||||
if (orig_fd != -1 && fstat(orig_fd, &sb) == -1)
|
||||
return (errno);
|
||||
if (orig_fd == -1 || S_ISFIFO(sb.st_mode))
|
||||
return (func(orig_fd, data));
|
||||
if ((fcntl(orig_fd, F_GETFL) & O_ACCMODE) == O_RDONLY)
|
||||
return (errno = EBADF);
|
||||
|
||||
int rw[2];
|
||||
if (pipe2(rw, O_CLOEXEC) == -1)
|
||||
return (errno);
|
||||
|
||||
int err;
|
||||
pthread_t send_thread;
|
||||
struct send_worker_ctx ctx = {.from = rw[0], .to = orig_fd};
|
||||
if ((err = pthread_create(&send_thread, NULL, send_worker, &ctx))
|
||||
!= 0) {
|
||||
close(rw[0]);
|
||||
close(rw[1]);
|
||||
return (errno = err);
|
||||
}
|
||||
|
||||
err = func(rw[1], data);
|
||||
|
||||
void *send_err;
|
||||
close(rw[1]);
|
||||
pthread_join(send_thread, &send_err);
|
||||
if (err == 0 && send_err != 0)
|
||||
errno = err = (uintptr_t)send_err;
|
||||
|
||||
return (err);
|
||||
#else
|
||||
return (func(orig_fd, data));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a zfs send stream for the specified snapshot and write it to
|
||||
* the specified file descriptor.
|
||||
|
@ -687,9 +765,11 @@ lzc_send_resume(const char *snapname, const char *from, int fd,
|
|||
* redactnv: nvlist of string -> boolean(ignored) containing the names of all
|
||||
* the snapshots that we should redact with respect to.
|
||||
* redactbook: Name of the redaction bookmark to create.
|
||||
*
|
||||
* Pre-wrapped.
|
||||
*/
|
||||
int
|
||||
lzc_send_resume_redacted(const char *snapname, const char *from, int fd,
|
||||
static int
|
||||
lzc_send_resume_redacted_cb_impl(const char *snapname, const char *from, int fd,
|
||||
enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff,
|
||||
const char *redactbook)
|
||||
{
|
||||
|
@ -722,6 +802,40 @@ lzc_send_resume_redacted(const char *snapname, const char *from, int fd,
|
|||
return (err);
|
||||
}
|
||||
|
||||
struct lzc_send_resume_redacted {
|
||||
const char *snapname;
|
||||
const char *from;
|
||||
enum lzc_send_flags flags;
|
||||
uint64_t resumeobj;
|
||||
uint64_t resumeoff;
|
||||
const char *redactbook;
|
||||
};
|
||||
|
||||
static int
|
||||
lzc_send_resume_redacted_cb(int fd, void *arg)
|
||||
{
|
||||
struct lzc_send_resume_redacted *zsrr = arg;
|
||||
return (lzc_send_resume_redacted_cb_impl(zsrr->snapname, zsrr->from,
|
||||
fd, zsrr->flags, zsrr->resumeobj, zsrr->resumeoff,
|
||||
zsrr->redactbook));
|
||||
}
|
||||
|
||||
int
|
||||
lzc_send_resume_redacted(const char *snapname, const char *from, int fd,
|
||||
enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff,
|
||||
const char *redactbook)
|
||||
{
|
||||
struct lzc_send_resume_redacted zsrr = {
|
||||
.snapname = snapname,
|
||||
.from = from,
|
||||
.flags = flags,
|
||||
.resumeobj = resumeobj,
|
||||
.resumeoff = resumeoff,
|
||||
.redactbook = redactbook,
|
||||
};
|
||||
return (lzc_send_wrapper(lzc_send_resume_redacted_cb, fd, &zsrr));
|
||||
}
|
||||
|
||||
/*
|
||||
* "from" can be NULL, a snapshot, or a bookmark.
|
||||
*
|
||||
|
@ -737,9 +851,11 @@ lzc_send_resume_redacted(const char *snapname, const char *from, int fd,
|
|||
* significantly more I/O and be less efficient than a send space estimation on
|
||||
* an equivalent snapshot. This process is also used if redact_snaps is
|
||||
* non-null.
|
||||
*
|
||||
* Pre-wrapped.
|
||||
*/
|
||||
int
|
||||
lzc_send_space_resume_redacted(const char *snapname, const char *from,
|
||||
static int
|
||||
lzc_send_space_resume_redacted_cb_impl(const char *snapname, const char *from,
|
||||
enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff,
|
||||
uint64_t resume_bytes, const char *redactbook, int fd, uint64_t *spacep)
|
||||
{
|
||||
|
@ -776,6 +892,45 @@ lzc_send_space_resume_redacted(const char *snapname, const char *from,
|
|||
return (err);
|
||||
}
|
||||
|
||||
struct lzc_send_space_resume_redacted {
|
||||
const char *snapname;
|
||||
const char *from;
|
||||
enum lzc_send_flags flags;
|
||||
uint64_t resumeobj;
|
||||
uint64_t resumeoff;
|
||||
uint64_t resume_bytes;
|
||||
const char *redactbook;
|
||||
uint64_t *spacep;
|
||||
};
|
||||
|
||||
static int
|
||||
lzc_send_space_resume_redacted_cb(int fd, void *arg)
|
||||
{
|
||||
struct lzc_send_space_resume_redacted *zssrr = arg;
|
||||
return (lzc_send_space_resume_redacted_cb_impl(zssrr->snapname,
|
||||
zssrr->from, zssrr->flags, zssrr->resumeobj, zssrr->resumeoff,
|
||||
zssrr->resume_bytes, zssrr->redactbook, fd, zssrr->spacep));
|
||||
}
|
||||
|
||||
int
|
||||
lzc_send_space_resume_redacted(const char *snapname, const char *from,
|
||||
enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff,
|
||||
uint64_t resume_bytes, const char *redactbook, int fd, uint64_t *spacep)
|
||||
{
|
||||
struct lzc_send_space_resume_redacted zssrr = {
|
||||
.snapname = snapname,
|
||||
.from = from,
|
||||
.flags = flags,
|
||||
.resumeobj = resumeobj,
|
||||
.resumeoff = resumeoff,
|
||||
.resume_bytes = resume_bytes,
|
||||
.redactbook = redactbook,
|
||||
.spacep = spacep,
|
||||
};
|
||||
return (lzc_send_wrapper(lzc_send_space_resume_redacted_cb,
|
||||
fd, &zssrr));
|
||||
}
|
||||
|
||||
int
|
||||
lzc_send_space(const char *snapname, const char *from,
|
||||
enum lzc_send_flags flags, uint64_t *spacep)
|
||||
|
|
Loading…
Reference in New Issue