mirror_zfs/include/os/freebsd/spl/sys/proc.h
Matthew Ahrens 1f043c8be1
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
30af21b025 (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 <ryan@iXsystems.com>
Reviewed-by: Chris Wedgwood <cw@f00f.org>
Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
Closes #10215 
Closes #10216
2020-04-20 10:12:48 -07:00

128 lines
3.4 KiB
C

/*
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _OPENSOLARIS_SYS_PROC_H_
#define _OPENSOLARIS_SYS_PROC_H_
#include <sys/param.h>
#include <sys/kthread.h>
#include_next <sys/proc.h>
#include <sys/stdint.h>
#include <sys/smp.h>
#include <sys/sched.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/unistd.h>
#include <sys/kmem.h>
#include <sys/malloc.h>
#define CPU curcpu
#define minclsyspri PRIBIO
#define defclsyspri minclsyspri
#define maxclsyspri PVM
#define max_ncpus (mp_maxid + 1)
#define boot_max_ncpus (mp_maxid + 1)
#define TS_RUN 0
#define p0 proc0
#define t_tid td_tid
typedef short pri_t;
typedef struct thread _kthread;
typedef struct thread kthread_t;
typedef struct thread *kthread_id_t;
typedef struct proc proc_t;
extern struct proc *zfsproc;
struct thread_wrap {
void *tw_arg;
void (*tw_proc)(void*);
};
static __inline void
solthread_wrapper(void *arg)
{
struct thread_wrap *tw = arg;
tw->tw_proc(tw->tw_arg);
free(tw, M_SOLARIS);
kthread_exit();
}
static __inline kthread_t *
do_thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg,
size_t len, proc_t *pp, int state, pri_t pri)
{
kthread_t *td = NULL;
int error;
struct thread_wrap *tw;
/*
* Be sure there are no surprises.
*/
ASSERT(stk == NULL);
ASSERT(len == 0);
ASSERT(state == TS_RUN);
tw = malloc(sizeof (*tw), M_SOLARIS, M_WAITOK);
tw->tw_proc = proc;
tw->tw_arg = arg;
error = kproc_kthread_add(solthread_wrapper, tw, &zfsproc, &td,
RFSTOPPED, stksize / PAGE_SIZE, "zfskern", "solthread %p", proc);
if (error == 0) {
thread_lock(td);
sched_prio(td, pri);
sched_add(td, SRQ_BORING);
#if __FreeBSD_version < 1300068
thread_unlock(td);
#endif
} else {
free(tw, M_SOLARIS);
}
return (td);
}
#define thread_create(stk, stksize, proc, arg, len, pp, state, pri) \
do_thread_create(stk, stksize, proc, arg, len, pp, state, pri)
#define thread_exit() kthread_exit()
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_ */