Implement lzc_send_progress

This commit adds an implementation of lzc_send_progress, which
existed in the libzfs_core header, but not in ABI and lacked
an actual implementation. The libzfs_send_progress function
is altered so that it wraps around the lzc operation. This
fills a functional gap in libzfs core.

Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ameer Hamza <ahamza@ixsystems.com>
Signed-off-by: Andrew Walker <andrew.walker@truenas.com>
Closes #18288
This commit is contained in:
Andrew Walker 2026-03-06 13:05:58 -06:00 committed by GitHub
parent c58b8b7dc2
commit c5905b2cb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 44 additions and 16 deletions

View File

@ -125,7 +125,7 @@ _LIBZFS_CORE_H int lzc_send_space(const char *, const char *,
_LIBZFS_CORE_H int lzc_send_space_resume_redacted(const char *, const char *,
enum lzc_send_flags, uint64_t, uint64_t, uint64_t, const char *,
int, uint64_t *);
_LIBZFS_CORE_H uint64_t lzc_send_progress(int);
_LIBZFS_CORE_H int lzc_send_progress(const char *, int, uint64_t *, uint64_t *);
_LIBZFS_CORE_H boolean_t lzc_exists(const char *);

View File

@ -927,21 +927,8 @@ int
zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written,
uint64_t *blocks_visited)
{
zfs_cmd_t zc = {"\0"};
if (bytes_written != NULL)
*bytes_written = 0;
if (blocks_visited != NULL)
*blocks_visited = 0;
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
zc.zc_cookie = fd;
if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0)
return (errno);
if (bytes_written != NULL)
*bytes_written = zc.zc_cookie;
if (blocks_visited != NULL)
*blocks_visited = zc.zc_objset_type;
return (0);
return (lzc_send_progress(zhp->zfs_name, fd, bytes_written,
blocks_visited));
}
static volatile boolean_t send_progress_thread_signal_duetotimer;

View File

@ -227,6 +227,7 @@
<elf-symbol name='lzc_send_redacted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_send_resume' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_send_resume_redacted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_send_progress' 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'/>
@ -3997,6 +3998,13 @@
<parameter type-id='5d6479ae' name='spacep'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='lzc_send_progress' mangled-name='lzc_send_progress' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_send_progress'>
<parameter type-id='80f4b756' name='snapname'/>
<parameter type-id='95e97e5e' name='fd'/>
<parameter type-id='5d6479ae' name='bytes_written'/>
<parameter type-id='5d6479ae' name='blocks_visited'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='lzc_send_space' mangled-name='lzc_send_space' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_send_space'>
<parameter type-id='80f4b756' name='snapname'/>
<parameter type-id='80f4b756' name='from'/>

View File

@ -1016,6 +1016,39 @@ lzc_send_space(const char *snapname, const char *from,
NULL, -1, spacep));
}
/*
* Query the progress of a send stream identified by the snapshot name and
* the file descriptor the stream is being written to.
*
* snapname name of the snapshot being sent
* fd file descriptor of the active send stream
* bytes_written on success, set to the number of bytes sent so far
* blocks_visited on success, set to the number of logical blocks traversed
*
* Returns 0 on success. Returns ENOENT if no send stream matching the
* snapshot name and file descriptor was found in the current process.
*/
int
lzc_send_progress(const char *snapname, int fd, uint64_t *bytes_written,
uint64_t *blocks_visited)
{
zfs_cmd_t zc = {"\0"};
if (bytes_written != NULL)
*bytes_written = 0;
if (blocks_visited != NULL)
*blocks_visited = 0;
(void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name));
zc.zc_cookie = fd;
if (lzc_ioctl_fd(g_fd, ZFS_IOC_SEND_PROGRESS, &zc) != 0)
return (errno);
if (bytes_written != NULL)
*bytes_written = zc.zc_cookie;
if (blocks_visited != NULL)
*blocks_visited = zc.zc_objset_type;
return (0);
}
static int
recv_read(int fd, void *buf, int ilen)
{