From 1f043c8be1bf575bae1088f150cf17b35184ad12 Mon Sep 17 00:00:00 2001 From: Matthew Ahrens Date: Mon, 20 Apr 2020 10:12:48 -0700 Subject: [PATCH] Fix zfs send progress reporting The progress of a send is supposed to be reported by `zfs send -v`, but it is not. This works by creating a new user thread (with pthread_create()) which does ZFS_IOC_SEND_PROGRESS ioctls to check how much progress has been made. This IOCTL finds the specified send (since there may be multiple concurrent sends in the system). The IOCTL also checks that the specified send was started by the current process. On Linux, different threads of the same process are represented as different `struct task_struct`s (and, confusingly, have different PID's). To check if if two threads are in the same process, we need to check if they have the same `struct task_struct:group_leader`. We used to to this correctly, but it was inadvertently changed by 30af21b02569 (Redacted Send) to simply check if the current `struct task_struct` is the one that started the send. This commit changes the code back to checking if the send was started by a `struct task_struct` with the same `group_leader` as the calling thread. Reviewed-by: Ryan Moeller Reviewed-by: Chris Wedgwood Reviewed-by: Paul Dagnelie Reviewed-by: Brian Behlendorf Signed-off-by: Matthew Ahrens Closes #10215 Closes #10216 --- include/os/freebsd/spl/sys/proc.h | 7 +++++++ include/os/linux/spl/sys/proc.h | 7 +++++++ module/zfs/zfs_ioctl.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/os/freebsd/spl/sys/proc.h b/include/os/freebsd/spl/sys/proc.h index fca833018ea0..07201dd6a095 100644 --- a/include/os/freebsd/spl/sys/proc.h +++ b/include/os/freebsd/spl/sys/proc.h @@ -117,4 +117,11 @@ do_thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg, int uread(proc_t *, void *, size_t, uintptr_t); int uwrite(proc_t *, void *, size_t, uintptr_t); + +static inline boolean_t +zfs_proc_is_caller(proc_t *p) +{ + return (p == curproc); +} + #endif /* _OPENSOLARIS_SYS_PROC_H_ */ diff --git a/include/os/linux/spl/sys/proc.h b/include/os/linux/spl/sys/proc.h index 28768392077c..fefce515eb24 100644 --- a/include/os/linux/spl/sys/proc.h +++ b/include/os/linux/spl/sys/proc.h @@ -26,10 +26,17 @@ #define _SPL_PROC_H #include +#include extern struct proc_dir_entry *proc_spl_kstat; int spl_proc_init(void); void spl_proc_fini(void); +static inline boolean_t +zfs_proc_is_caller(struct task_struct *t) +{ + return (t->group_leader == current->group_leader); +} + #endif /* SPL_PROC_H */ diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index fb9435341db1..5c53eb637794 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -5468,7 +5468,7 @@ zfs_ioc_send_progress(zfs_cmd_t *zc) for (dsp = list_head(&ds->ds_sendstreams); dsp != NULL; dsp = list_next(&ds->ds_sendstreams, dsp)) { if (dsp->dss_outfd == zc->zc_cookie && - dsp->dss_proc == curproc) + zfs_proc_is_caller(dsp->dss_proc)) break; }