From c5905b2cb754423d31cdb8adc625639aa7f8acc6 Mon Sep 17 00:00:00 2001 From: Andrew Walker Date: Fri, 6 Mar 2026 13:05:58 -0600 Subject: [PATCH] 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 Reviewed-by: Brian Behlendorf Reviewed-by: Ameer Hamza Signed-off-by: Andrew Walker Closes #18288 --- include/libzfs_core.h | 2 +- lib/libzfs/libzfs_sendrecv.c | 17 ++--------------- lib/libzfs_core/libzfs_core.abi | 8 ++++++++ lib/libzfs_core/libzfs_core.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/include/libzfs_core.h b/include/libzfs_core.h index 231beaa69..deb810230 100644 --- a/include/libzfs_core.h +++ b/include/libzfs_core.h @@ -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 *); diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 9d693223e..e2b351293 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -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; diff --git a/lib/libzfs_core/libzfs_core.abi b/lib/libzfs_core/libzfs_core.abi index 1cfd2a81d..5c5d29243 100644 --- a/lib/libzfs_core/libzfs_core.abi +++ b/lib/libzfs_core/libzfs_core.abi @@ -227,6 +227,7 @@ + @@ -3997,6 +3998,13 @@ + + + + + + + diff --git a/lib/libzfs_core/libzfs_core.c b/lib/libzfs_core/libzfs_core.c index 9347aa7c6..c6cd62e76 100644 --- a/lib/libzfs_core/libzfs_core.c +++ b/lib/libzfs_core/libzfs_core.c @@ -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) {