svn commit: r367777 - in head: lib/libkvm lib/libprocstat sys/compat/cloudabi sys/fs/fuse sys/fs/unionfs sys/kern sys/sys

Conrad Meyer cem at FreeBSD.org
Tue Nov 17 21:14:17 UTC 2020


Author: cem
Date: Tue Nov 17 21:14:13 2020
New Revision: 367777
URL: https://svnweb.freebsd.org/changeset/base/367777

Log:
  Split out cwd/root/jail, cmask state from filedesc table
  
  No functional change intended.
  
  Tracking these structures separately for each proc enables future work to
  correctly emulate clone(2) in linux(4).
  
  __FreeBSD_version is bumped (to 1300130) for consumption by, e.g., lsof.
  
  Reviewed by:	kib
  Discussed with:	markj, mjg
  Differential Revision:	https://reviews.freebsd.org/D27037

Modified:
  head/lib/libkvm/kvm_proc.c
  head/lib/libprocstat/libprocstat.c
  head/sys/compat/cloudabi/cloudabi_file.c
  head/sys/fs/fuse/fuse_internal.c
  head/sys/fs/fuse/fuse_vnops.c
  head/sys/fs/unionfs/union_subr.c
  head/sys/kern/imgact_elf.c
  head/sys/kern/init_main.c
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_exec.c
  head/sys/kern/kern_exit.c
  head/sys/kern/kern_fork.c
  head/sys/kern/kern_proc.c
  head/sys/kern/kern_thread.c
  head/sys/kern/uipc_mqueue.c
  head/sys/kern/uipc_sem.c
  head/sys/kern/uipc_shm.c
  head/sys/kern/uipc_usrreq.c
  head/sys/kern/vfs_syscalls.c
  head/sys/sys/filedesc.h
  head/sys/sys/param.h
  head/sys/sys/proc.h
  head/sys/sys/user.h

Modified: head/lib/libkvm/kvm_proc.c
==============================================================================
--- head/lib/libkvm/kvm_proc.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/lib/libkvm/kvm_proc.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -221,6 +221,7 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc
 		kp->ki_tracep = proc.p_tracevp;
 		kp->ki_textvp = proc.p_textvp;
 		kp->ki_fd = proc.p_fd;
+		kp->ki_pd = proc.p_pd;
 		kp->ki_vmspace = proc.p_vmspace;
 		if (proc.p_sigacts != NULL) {
 			if (KREAD(kd, (u_long)proc.p_sigacts, &sigacts)) {

Modified: head/lib/libprocstat/libprocstat.c
==============================================================================
--- head/lib/libprocstat/libprocstat.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/lib/libprocstat/libprocstat.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -460,6 +460,7 @@ procstat_getfiles_kvm(struct procstat *procstat, struc
 {
 	struct file file;
 	struct filedesc filed;
+	struct pwddesc pathsd;
 	struct fdescenttbl *fdt;
 	struct pwd pwd;
 	unsigned long pwd_addr;
@@ -484,15 +485,20 @@ procstat_getfiles_kvm(struct procstat *procstat, struc
 	kd = procstat->kd;
 	if (kd == NULL)
 		return (NULL);
-	if (kp->ki_fd == NULL)
+	if (kp->ki_fd == NULL || kp->ki_pd == NULL)
 		return (NULL);
 	if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed,
 	    sizeof(filed))) {
 		warnx("can't read filedesc at %p", (void *)kp->ki_fd);
 		return (NULL);
 	}
+	if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pathsd,
+	    sizeof(pathsd))) {
+		warnx("can't read pwddesc at %p", (void *)kp->ki_pd);
+		return (NULL);
+	}
 	haspwd = false;
-	pwd_addr = (unsigned long)(FILEDESC_KVM_LOAD_PWD(&filed));
+	pwd_addr = (unsigned long)(PWDDESC_KVM_LOAD_PWD(&pathsd));
 	if (pwd_addr != 0) {
 		if (!kvm_read_all(kd, pwd_addr, &pwd, sizeof(pwd))) {
 			warnx("can't read fd_pwd at %p", (void *)pwd_addr);
@@ -2086,18 +2092,18 @@ procstat_freegroups(struct procstat *procstat __unused
 static int
 procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp)
 {
-	struct filedesc fd;
+	struct pwddesc pd;
 
 	assert(kd != NULL);
 	assert(kp != NULL);
-	if (kp->ki_fd == NULL)
+	if (kp->ki_pd == NULL)
 		return (-1);
-	if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &fd, sizeof(fd))) {
-		warnx("can't read filedesc at %p for pid %d", kp->ki_fd,
+	if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pd, sizeof(pd))) {
+		warnx("can't read pwddesc at %p for pid %d", kp->ki_pd,
 		    kp->ki_pid);
 		return (-1);
 	}
-	*maskp = fd.fd_cmask;
+	*maskp = pd.pd_cmask;
 	return (0);
 }
 

Modified: head/sys/compat/cloudabi/cloudabi_file.c
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_file.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/compat/cloudabi/cloudabi_file.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -265,7 +265,7 @@ cloudabi_sys_file_open(struct thread *td,
 	}
 	NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, uap->dirfd.fd,
 	    &rights, td);
-	error = vn_open(&nd, &fflags, 0777 & ~td->td_proc->p_fd->fd_cmask, fp);
+	error = vn_open(&nd, &fflags, 0777 & ~td->td_proc->p_pd->pd_cmask, fp);
 	cloudabi_freestr(path);
 	if (error != 0) {
 		/* Custom operations provided. */

Modified: head/sys/fs/fuse/fuse_internal.c
==============================================================================
--- head/sys/fs/fuse/fuse_internal.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/fs/fuse/fuse_internal.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -497,7 +497,7 @@ fuse_internal_mknod(struct vnode *dvp, struct vnode **
 	fmni.rdev = vap->va_rdev;
 	if (fuse_libabi_geq(data, 7, 12)) {
 		insize = sizeof(fmni);
-		fmni.umask = curthread->td_proc->p_fd->fd_cmask;
+		fmni.umask = curthread->td_proc->p_pd->pd_cmask;
 	} else {
 		insize = FUSE_COMPAT_MKNOD_IN_SIZE;
 	}

Modified: head/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- head/sys/fs/fuse/fuse_vnops.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/fs/fuse/fuse_vnops.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -668,7 +668,7 @@ fuse_vnop_create(struct vop_create_args *ap)
 		fci->flags = O_CREAT | flags;
 		if (fuse_libabi_geq(data, 7, 12)) {
 			insize = sizeof(*fci);
-			fci->umask = td->td_proc->p_fd->fd_cmask;
+			fci->umask = td->td_proc->p_pd->pd_cmask;
 		} else {
 			insize = sizeof(struct fuse_open_in);
 		}
@@ -1269,7 +1269,7 @@ fuse_vnop_mkdir(struct vop_mkdir_args *ap)
 		return ENXIO;
 	}
 	fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);
-	fmdi.umask = curthread->td_proc->p_fd->fd_cmask;
+	fmdi.umask = curthread->td_proc->p_pd->pd_cmask;
 
 	return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi,
 	    sizeof(fmdi), VDIR));

Modified: head/sys/fs/unionfs/union_subr.c
==============================================================================
--- head/sys/fs/unionfs/union_subr.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/fs/unionfs/union_subr.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -486,7 +486,7 @@ unionfs_create_uppervattr_core(struct unionfs_mount *u
 		}
 		break;
 	default:		/* UNIONFS_TRADITIONAL */
-		uva->va_mode = 0777 & ~td->td_proc->p_fd->fd_cmask;
+		uva->va_mode = 0777 & ~td->td_proc->p_pd->pd_cmask;
 		uva->va_uid = ump->um_uid;
 		uva->va_gid = ump->um_gid;
 		break;

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/imgact_elf.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -2507,12 +2507,12 @@ note_procstat_umask(void *arg, struct sbuf *sb, size_t
 	int structsize;
 
 	p = (struct proc *)arg;
-	size = sizeof(structsize) + sizeof(p->p_fd->fd_cmask);
+	size = sizeof(structsize) + sizeof(p->p_pd->pd_cmask);
 	if (sb != NULL) {
 		KASSERT(*sizep == size, ("invalid size"));
-		structsize = sizeof(p->p_fd->fd_cmask);
+		structsize = sizeof(p->p_pd->pd_cmask);
 		sbuf_bcat(sb, &structsize, sizeof(structsize));
-		sbuf_bcat(sb, &p->p_fd->fd_cmask, sizeof(p->p_fd->fd_cmask));
+		sbuf_bcat(sb, &p->p_pd->pd_cmask, sizeof(p->p_pd->pd_cmask));
 	}
 	*sizep = size;
 }

Modified: head/sys/kern/init_main.c
==============================================================================
--- head/sys/kern/init_main.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/init_main.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -555,6 +555,7 @@ proc0_init(void *dummy __unused)
 	siginit(&proc0);
 
 	/* Create the file descriptor table. */
+	p->p_pd = pdinit(NULL, false);
 	p->p_fd = fdinit(NULL, false, NULL);
 	p->p_fdtol = NULL;
 

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/kern_descrip.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
 
 static MALLOC_DEFINE(M_FILEDESC, "filedesc", "Open file descriptor table");
 static MALLOC_DEFINE(M_PWD, "pwd", "Descriptor table vnodes");
+static MALLOC_DEFINE(M_PWDDESC, "pwddesc", "Pwd descriptors");
 static MALLOC_DEFINE(M_FILEDESC_TO_LEADER, "filedesc_to_leader",
     "file desc to leader structures");
 static MALLOC_DEFINE(M_SIGIO, "sigio", "sigio structures");
@@ -2029,7 +2030,6 @@ finstall(struct thread *td, struct file *fp, int *fd, 
 
 /*
  * Build a new filedesc structure from another.
- * Copy the current, root, and jail root vnode references.
  *
  * If fdp is not NULL, return with it shared locked.
  */
@@ -2038,7 +2038,6 @@ fdinit(struct filedesc *fdp, bool prepfiles, int *last
 {
 	struct filedesc0 *newfdp0;
 	struct filedesc *newfdp;
-	struct pwd *newpwd;
 
 	if (prepfiles)
 		MPASS(lastfile != NULL);
@@ -2052,20 +2051,14 @@ fdinit(struct filedesc *fdp, bool prepfiles, int *last
 	FILEDESC_LOCK_INIT(newfdp);
 	refcount_init(&newfdp->fd_refcnt, 1);
 	refcount_init(&newfdp->fd_holdcnt, 1);
-	newfdp->fd_cmask = CMASK;
 	newfdp->fd_map = newfdp0->fd_dmap;
 	newfdp->fd_files = (struct fdescenttbl *)&newfdp0->fd_dfiles;
 	newfdp->fd_files->fdt_nfiles = NDFILE;
 
-	if (fdp == NULL) {
-		newpwd = pwd_alloc();
-		smr_serialized_store(&newfdp->fd_pwd, newpwd, true);
+	if (fdp == NULL)
 		return (newfdp);
-	}
 
 	FILEDESC_SLOCK(fdp);
-	newpwd = pwd_hold_filedesc(fdp);
-	smr_serialized_store(&newfdp->fd_pwd, newpwd, true);
 	if (!prepfiles) {
 		FILEDESC_SUNLOCK(fdp);
 		return (newfdp);
@@ -2083,6 +2076,38 @@ fdinit(struct filedesc *fdp, bool prepfiles, int *last
 	return (newfdp);
 }
 
+/*
+ * Build a pwddesc structure from another.
+ * Copy the current, root, and jail root vnode references.
+ *
+ * If pdp is not NULL, return with it shared locked.
+ */
+struct pwddesc *
+pdinit(struct pwddesc *pdp, bool keeplock)
+{
+	struct pwddesc *newpdp;
+	struct pwd *newpwd;
+
+	newpdp = malloc(sizeof(*newpdp), M_PWDDESC, M_WAITOK | M_ZERO);
+
+	PWDDESC_LOCK_INIT(newpdp);
+	refcount_init(&newpdp->pd_refcount, 1);
+	newpdp->pd_cmask = CMASK;
+
+	if (pdp == NULL) {
+		newpwd = pwd_alloc();
+		smr_serialized_store(&newpdp->pd_pwd, newpwd, true);
+		return (newpdp);
+	}
+
+	PWDDESC_XLOCK(pdp);
+	newpwd = pwd_hold_pwddesc(pdp);
+	smr_serialized_store(&newpdp->pd_pwd, newpwd, true);
+	if (!keeplock)
+		PWDDESC_XUNLOCK(pdp);
+	return (newpdp);
+}
+
 static struct filedesc *
 fdhold(struct proc *p)
 {
@@ -2095,6 +2120,18 @@ fdhold(struct proc *p)
 	return (fdp);
 }
 
+static struct pwddesc *
+pdhold(struct proc *p)
+{
+	struct pwddesc *pdp;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	pdp = p->p_pd;
+	if (pdp != NULL)
+		refcount_acquire(&pdp->pd_refcount);
+	return (pdp);
+}
+
 static void
 fddrop(struct filedesc *fdp)
 {
@@ -2108,6 +2145,28 @@ fddrop(struct filedesc *fdp)
 	uma_zfree(filedesc0_zone, fdp);
 }
 
+static void
+pddrop(struct pwddesc *pdp)
+{
+	struct pwd *pwd;
+
+	if (refcount_release_if_not_last(&pdp->pd_refcount))
+		return;
+
+	PWDDESC_XLOCK(pdp);
+	if (refcount_release(&pdp->pd_refcount) == 0) {
+		PWDDESC_XUNLOCK(pdp);
+		return;
+	}
+	pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
+	pwd_set(pdp, NULL);
+	PWDDESC_XUNLOCK(pdp);
+	pwd_drop(pwd);
+
+	PWDDESC_LOCK_DESTROY(pdp);
+	free(pdp, M_PWDDESC);
+}
+
 /*
  * Share a filedesc structure.
  */
@@ -2120,6 +2179,16 @@ fdshare(struct filedesc *fdp)
 }
 
 /*
+ * Share a pwddesc structure.
+ */
+struct pwddesc *
+pdshare(struct pwddesc *pdp)
+{
+	refcount_acquire(&pdp->pd_refcount);
+	return (pdp);
+}
+
+/*
  * Unshare a filedesc structure, if necessary by making a copy
  */
 void
@@ -2136,7 +2205,26 @@ fdunshare(struct thread *td)
 	p->p_fd = tmp;
 }
 
+/*
+ * Unshare a pwddesc structure.
+ */
 void
+pdunshare(struct thread *td)
+{
+	struct pwddesc *pdp;
+	struct proc *p;
+
+	p = td->td_proc;
+	/* Not shared. */
+	if (p->p_pd->pd_refcount == 1)
+		return;
+
+	pdp = pdcopy(p->p_pd);
+	pdescfree(td);
+	p->p_pd = pdp;
+}
+
+void
 fdinstall_remapped(struct thread *td, struct filedesc *fdp)
 {
 
@@ -2176,12 +2264,27 @@ fdcopy(struct filedesc *fdp)
 	}
 	if (newfdp->fd_freefile == -1)
 		newfdp->fd_freefile = i;
-	newfdp->fd_cmask = fdp->fd_cmask;
 	FILEDESC_SUNLOCK(fdp);
 	return (newfdp);
 }
 
 /*
+ * Copy a pwddesc structure.
+ */
+struct pwddesc *
+pdcopy(struct pwddesc *pdp)
+{
+	struct pwddesc *newpdp;
+
+	MPASS(pdp != NULL);
+
+	newpdp = pdinit(pdp, true);
+	newpdp->pd_cmask = pdp->pd_cmask;
+	PWDDESC_XUNLOCK(pdp);
+	return (newpdp);
+}
+
+/*
  * Copies a filedesc structure, while remapping all file descriptors
  * stored inside using a translation table.
  *
@@ -2232,7 +2335,6 @@ fdcopy_remapped(struct filedesc *fdp, const int *fds, 
 		filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true);
 		fdused_init(newfdp, i);
 	}
-	newfdp->fd_cmask = fdp->fd_cmask;
 	FILEDESC_SUNLOCK(fdp);
 	*ret = newfdp;
 	return (0);
@@ -2366,7 +2468,6 @@ fdescfree(struct thread *td)
 {
 	struct proc *p;
 	struct filedesc *fdp;
-	struct pwd *pwd;
 
 	p = td->td_proc;
 	fdp = p->p_fd;
@@ -2387,21 +2488,29 @@ fdescfree(struct thread *td)
 	if (refcount_release(&fdp->fd_refcnt) == 0)
 		return;
 
-	FILEDESC_XLOCK(fdp);
-	pwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
-	pwd_set(fdp, NULL);
-	FILEDESC_XUNLOCK(fdp);
+	fdescfree_fds(td, fdp, 1);
+}
 
-	pwd_drop(pwd);
+void
+pdescfree(struct thread *td)
+{
+	struct proc *p;
+	struct pwddesc *pdp;
 
-	fdescfree_fds(td, fdp, 1);
+	p = td->td_proc;
+	pdp = p->p_pd;
+	MPASS(pdp != NULL);
+
+	PROC_LOCK(p);
+	p->p_pd = NULL;
+	PROC_UNLOCK(p);
+
+	pddrop(pdp);
 }
 
 void
 fdescfree_remapped(struct filedesc *fdp)
 {
-
-	pwd_drop(smr_serialized_load(&fdp->fd_pwd, true));
 	fdescfree_fds(curthread, fdp, 0);
 }
 
@@ -3452,12 +3561,12 @@ pwd_fill(struct pwd *oldpwd, struct pwd *newpwd)
 }
 
 struct pwd *
-pwd_hold_filedesc(struct filedesc *fdp)
+pwd_hold_pwddesc(struct pwddesc *pdp)
 {
 	struct pwd *pwd;
 
-	FILEDESC_LOCK_ASSERT(fdp);
-	pwd = FILEDESC_LOCKED_LOAD_PWD(fdp);
+	PWDDESC_ASSERT_XLOCKED(pdp);
+	pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 	if (pwd != NULL)
 		refcount_acquire(&pwd->pwd_refcount);
 	return (pwd);
@@ -3477,22 +3586,22 @@ pwd_hold_smr(struct pwd *pwd)
 struct pwd *
 pwd_hold(struct thread *td)
 {
-	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct pwd *pwd;
 
-	fdp = td->td_proc->p_fd;
+	pdp = td->td_proc->p_pd;
 
 	vfs_smr_enter();
-	pwd = vfs_smr_entered_load(&fdp->fd_pwd);
+	pwd = vfs_smr_entered_load(&pdp->pd_pwd);
 	if (pwd_hold_smr(pwd)) {
 		vfs_smr_exit();
 		return (pwd);
 	}
 	vfs_smr_exit();
-	FILEDESC_SLOCK(fdp);
-	pwd = pwd_hold_filedesc(fdp);
+	PWDDESC_XLOCK(pdp);
+	pwd = pwd_hold_pwddesc(pdp);
 	MPASS(pwd != NULL);
-	FILEDESC_SUNLOCK(fdp);
+	PWDDESC_XUNLOCK(pdp);
 	return (pwd);
 }
 
@@ -3501,7 +3610,7 @@ pwd_get_smr(void)
 {
 	struct pwd *pwd;
 
-	pwd = vfs_smr_entered_load(&curproc->p_fd->fd_pwd);
+	pwd = vfs_smr_entered_load(&curproc->p_pd->pd_pwd);
 	MPASS(pwd != NULL);
 	return (pwd);
 }
@@ -3541,23 +3650,29 @@ pwd_drop(struct pwd *pwd)
 int
 pwd_chroot(struct thread *td, struct vnode *vp)
 {
+	struct pwddesc *pdp;
 	struct filedesc *fdp;
 	struct pwd *newpwd, *oldpwd;
 	int error;
 
 	fdp = td->td_proc->p_fd;
+	pdp = td->td_proc->p_pd;
 	newpwd = pwd_alloc();
-	FILEDESC_XLOCK(fdp);
-	oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
+	FILEDESC_SLOCK(fdp);
+	PWDDESC_XLOCK(pdp);
+	oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 	if (chroot_allow_open_directories == 0 ||
 	    (chroot_allow_open_directories == 1 &&
 	    oldpwd->pwd_rdir != rootvnode)) {
 		error = chroot_refuse_vdir_fds(fdp);
+		FILEDESC_SUNLOCK(fdp);
 		if (error != 0) {
-			FILEDESC_XUNLOCK(fdp);
+			PWDDESC_XUNLOCK(pdp);
 			pwd_drop(newpwd);
 			return (error);
 		}
+	} else {
+		FILEDESC_SUNLOCK(fdp);
 	}
 
 	vrefact(vp);
@@ -3567,8 +3682,8 @@ pwd_chroot(struct thread *td, struct vnode *vp)
 		newpwd->pwd_jdir = vp;
 	}
 	pwd_fill(oldpwd, newpwd);
-	pwd_set(fdp, newpwd);
-	FILEDESC_XUNLOCK(fdp);
+	pwd_set(pdp, newpwd);
+	PWDDESC_XUNLOCK(pdp);
 	pwd_drop(oldpwd);
 	return (0);
 }
@@ -3576,40 +3691,40 @@ pwd_chroot(struct thread *td, struct vnode *vp)
 void
 pwd_chdir(struct thread *td, struct vnode *vp)
 {
-	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct pwd *newpwd, *oldpwd;
 
 	VNPASS(vp->v_usecount > 0, vp);
 
 	newpwd = pwd_alloc();
-	fdp = td->td_proc->p_fd;
-	FILEDESC_XLOCK(fdp);
-	oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
+	pdp = td->td_proc->p_pd;
+	PWDDESC_XLOCK(pdp);
+	oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 	newpwd->pwd_cdir = vp;
 	pwd_fill(oldpwd, newpwd);
-	pwd_set(fdp, newpwd);
-	FILEDESC_XUNLOCK(fdp);
+	pwd_set(pdp, newpwd);
+	PWDDESC_XUNLOCK(pdp);
 	pwd_drop(oldpwd);
 }
 
 void
 pwd_ensure_dirs(void)
 {
-	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct pwd *oldpwd, *newpwd;
 
-	fdp = curproc->p_fd;
-	FILEDESC_XLOCK(fdp);
-	oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
+	pdp = curproc->p_pd;
+	PWDDESC_XLOCK(pdp);
+	oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 	if (oldpwd->pwd_cdir != NULL && oldpwd->pwd_rdir != NULL) {
-		FILEDESC_XUNLOCK(fdp);
+		PWDDESC_XUNLOCK(pdp);
 		return;
 	}
-	FILEDESC_XUNLOCK(fdp);
+	PWDDESC_XUNLOCK(pdp);
 
 	newpwd = pwd_alloc();
-	FILEDESC_XLOCK(fdp);
-	oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
+	PWDDESC_XLOCK(pdp);
+	oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 	pwd_fill(oldpwd, newpwd);
 	if (newpwd->pwd_cdir == NULL) {
 		vrefact(rootvnode);
@@ -3619,29 +3734,29 @@ pwd_ensure_dirs(void)
 		vrefact(rootvnode);
 		newpwd->pwd_rdir = rootvnode;
 	}
-	pwd_set(fdp, newpwd);
-	FILEDESC_XUNLOCK(fdp);
+	pwd_set(pdp, newpwd);
+	PWDDESC_XUNLOCK(pdp);
 	pwd_drop(oldpwd);
 }
 
 void
 pwd_set_rootvnode(void)
 {
-	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct pwd *oldpwd, *newpwd;
 
-	fdp = curproc->p_fd;
+	pdp = curproc->p_pd;
 
 	newpwd = pwd_alloc();
-	FILEDESC_XLOCK(fdp);
-	oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
+	PWDDESC_XLOCK(pdp);
+	oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 	vrefact(rootvnode);
 	newpwd->pwd_cdir = rootvnode;
 	vrefact(rootvnode);
 	newpwd->pwd_rdir = rootvnode;
 	pwd_fill(oldpwd, newpwd);
-	pwd_set(fdp, newpwd);
-	FILEDESC_XUNLOCK(fdp);
+	pwd_set(pdp, newpwd);
+	PWDDESC_XUNLOCK(pdp);
 	pwd_drop(oldpwd);
 }
 
@@ -3652,7 +3767,7 @@ pwd_set_rootvnode(void)
 void
 mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
 {
-	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct pwd *newpwd, *oldpwd;
 	struct prison *pr;
 	struct proc *p;
@@ -3665,18 +3780,18 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newd
 	sx_slock(&allproc_lock);
 	FOREACH_PROC_IN_SYSTEM(p) {
 		PROC_LOCK(p);
-		fdp = fdhold(p);
+		pdp = pdhold(p);
 		PROC_UNLOCK(p);
-		if (fdp == NULL)
+		if (pdp == NULL)
 			continue;
-		FILEDESC_XLOCK(fdp);
-		oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
+		PWDDESC_XLOCK(pdp);
+		oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 		if (oldpwd == NULL ||
 		    (oldpwd->pwd_cdir != olddp &&
 		    oldpwd->pwd_rdir != olddp &&
 		    oldpwd->pwd_jdir != olddp)) {
-			FILEDESC_XUNLOCK(fdp);
-			fddrop(fdp);
+			PWDDESC_XUNLOCK(pdp);
+			pddrop(pdp);
 			continue;
 		}
 		if (oldpwd->pwd_cdir == olddp) {
@@ -3692,10 +3807,10 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newd
 			newpwd->pwd_jdir = newdp;
 		}
 		pwd_fill(oldpwd, newpwd);
-		pwd_set(fdp, newpwd);
-		FILEDESC_XUNLOCK(fdp);
+		pwd_set(pdp, newpwd);
+		PWDDESC_XUNLOCK(pdp);
 		pwd_drop(oldpwd);
-		fddrop(fdp);
+		pddrop(pdp);
 		newpwd = pwd_alloc();
 	}
 	sx_sunlock(&allproc_lock);
@@ -3968,6 +4083,7 @@ export_vnode_to_kinfo(struct vnode *vp, int fd, int ff
 
 struct export_fd_buf {
 	struct filedesc		*fdp;
+	struct pwddesc	*pdp;
 	struct sbuf 		*sb;
 	ssize_t			remainder;
 	struct kinfo_file	kif;
@@ -4015,12 +4131,12 @@ export_vnode_to_sb(struct vnode *vp, int fd, int fflag
 
 	if (efbuf->remainder == 0)
 		return (0);
-	if (efbuf->fdp != NULL)
-		FILEDESC_SUNLOCK(efbuf->fdp);
+	if (efbuf->pdp != NULL)
+		PWDDESC_XUNLOCK(efbuf->pdp);
 	export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif, efbuf->flags);
 	error = export_kinfo_to_sb(efbuf);
-	if (efbuf->fdp != NULL)
-		FILEDESC_SLOCK(efbuf->fdp);
+	if (efbuf->pdp != NULL)
+		PWDDESC_XLOCK(efbuf->pdp);
 	return (error);
 }
 
@@ -4035,6 +4151,7 @@ kern_proc_filedesc_out(struct proc *p,  struct sbuf *s
 {
 	struct file *fp;
 	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct export_fd_buf *efbuf;
 	struct vnode *cttyvp, *textvp, *tracevp;
 	struct pwd *pwd;
@@ -4059,9 +4176,11 @@ kern_proc_filedesc_out(struct proc *p,  struct sbuf *s
 			vrefact(cttyvp);
 	}
 	fdp = fdhold(p);
+	pdp = pdhold(p);
 	PROC_UNLOCK(p);
 	efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK);
 	efbuf->fdp = NULL;
+	efbuf->pdp = NULL;
 	efbuf->sb = sb;
 	efbuf->remainder = maxlen;
 	efbuf->flags = flags;
@@ -4074,11 +4193,12 @@ kern_proc_filedesc_out(struct proc *p,  struct sbuf *s
 		export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY, FREAD | FWRITE,
 		    efbuf);
 	error = 0;
-	if (fdp == NULL)
+	if (pdp == NULL || fdp == NULL)
 		goto fail;
 	efbuf->fdp = fdp;
-	FILEDESC_SLOCK(fdp);
-	pwd = pwd_hold_filedesc(fdp);
+	efbuf->pdp = pdp;
+	PWDDESC_XLOCK(pdp);
+	pwd = pwd_hold_pwddesc(pdp);
 	if (pwd != NULL) {
 		/* working directory */
 		if (pwd->pwd_cdir != NULL) {
@@ -4096,6 +4216,10 @@ kern_proc_filedesc_out(struct proc *p,  struct sbuf *s
 			export_vnode_to_sb(pwd->pwd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
 		}
 	}
+	PWDDESC_XUNLOCK(pdp);
+	if (pwd != NULL)
+		pwd_drop(pwd);
+	FILEDESC_SLOCK(fdp);
 	lastfile = fdlastfile(fdp);
 	for (i = 0; fdp->fd_refcnt > 0 && i <= lastfile; i++) {
 		if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
@@ -4116,10 +4240,11 @@ kern_proc_filedesc_out(struct proc *p,  struct sbuf *s
 			break;
 	}
 	FILEDESC_SUNLOCK(fdp);
-	if (pwd != NULL)
-		pwd_drop(pwd);
-	fddrop(fdp);
 fail:
+	if (fdp != NULL)
+		fddrop(fdp);
+	if (pdp != NULL)
+		pddrop(pdp);
 	free(efbuf, M_TEMP);
 	return (error);
 }
@@ -4190,16 +4315,16 @@ kinfo_to_okinfo(struct kinfo_file *kif, struct kinfo_o
 
 static int
 export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif,
-    struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req)
+    struct kinfo_ofile *okif, struct pwddesc *pdp, struct sysctl_req *req)
 {
 	int error;
 
 	vrefact(vp);
-	FILEDESC_SUNLOCK(fdp);
+	PWDDESC_XUNLOCK(pdp);
 	export_vnode_to_kinfo(vp, type, 0, kif, KERN_FILEDESC_PACK_KINFO);
 	kinfo_to_okinfo(kif, okif);
 	error = SYSCTL_OUT(req, okif, sizeof(*okif));
-	FILEDESC_SLOCK(fdp);
+	PWDDESC_XLOCK(pdp);
 	return (error);
 }
 
@@ -4212,6 +4337,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
 	struct kinfo_ofile *okif;
 	struct kinfo_file *kif;
 	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct pwd *pwd;
 	int error, i, lastfile, *name;
 	struct file *fp;
@@ -4222,24 +4348,33 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
 	if (error != 0)
 		return (error);
 	fdp = fdhold(p);
+	if (fdp != NULL)
+		pdp = pdhold(p);
 	PROC_UNLOCK(p);
-	if (fdp == NULL)
+	if (fdp == NULL || pdp == NULL) {
+		if (fdp != NULL)
+			fddrop(fdp);
 		return (ENOENT);
+	}
 	kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
 	okif = malloc(sizeof(*okif), M_TEMP, M_WAITOK);
-	FILEDESC_SLOCK(fdp);
-	pwd = pwd_hold_filedesc(fdp);
+	PWDDESC_XLOCK(pdp);
+	pwd = pwd_hold_pwddesc(pdp);
 	if (pwd != NULL) {
 		if (pwd->pwd_cdir != NULL)
 			export_vnode_for_osysctl(pwd->pwd_cdir, KF_FD_TYPE_CWD, kif,
-			    okif, fdp, req);
+			    okif, pdp, req);
 		if (pwd->pwd_rdir != NULL)
 			export_vnode_for_osysctl(pwd->pwd_rdir, KF_FD_TYPE_ROOT, kif,
-			    okif, fdp, req);
+			    okif, pdp, req);
 		if (pwd->pwd_jdir != NULL)
 			export_vnode_for_osysctl(pwd->pwd_jdir, KF_FD_TYPE_JAIL, kif,
-			    okif, fdp, req);
+			    okif, pdp, req);
 	}
+	PWDDESC_XUNLOCK(pdp);
+	if (pwd != NULL)
+		pwd_drop(pwd);
+	FILEDESC_SLOCK(fdp);
 	lastfile = fdlastfile(fdp);
 	for (i = 0; fdp->fd_refcnt > 0 && i <= lastfile; i++) {
 		if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
@@ -4254,9 +4389,8 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
 			break;
 	}
 	FILEDESC_SUNLOCK(fdp);
-	if (pwd != NULL)
-		pwd_drop(pwd);
 	fddrop(fdp);
+	pddrop(pdp);
 	free(kif, M_TEMP);
 	free(okif, M_TEMP);
 	return (0);
@@ -4308,7 +4442,7 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, fil
 int
 kern_proc_cwd_out(struct proc *p,  struct sbuf *sb, ssize_t maxlen)
 {
-	struct filedesc *fdp;
+	struct pwddesc *pdp;
 	struct pwd *pwd;
 	struct export_fd_buf *efbuf;
 	struct vnode *cdir;
@@ -4316,18 +4450,18 @@ kern_proc_cwd_out(struct proc *p,  struct sbuf *sb, ss
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 
-	fdp = fdhold(p);
+	pdp = pdhold(p);
 	PROC_UNLOCK(p);
-	if (fdp == NULL)
+	if (pdp == NULL)
 		return (EINVAL);
 
 	efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK);
-	efbuf->fdp = fdp;
+	efbuf->pdp = pdp;
 	efbuf->sb = sb;
 	efbuf->remainder = maxlen;
 
-	FILEDESC_SLOCK(fdp);
-	pwd = FILEDESC_LOCKED_LOAD_PWD(fdp);
+	PWDDESC_XLOCK(pdp);
+	pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
 	cdir = pwd->pwd_cdir;
 	if (cdir == NULL) {
 		error = EINVAL;
@@ -4335,8 +4469,8 @@ kern_proc_cwd_out(struct proc *p,  struct sbuf *sb, ss
 		vrefact(cdir);
 		error = export_vnode_to_sb(cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
 	}
-	FILEDESC_SUNLOCK(fdp);
-	fddrop(fdp);
+	PWDDESC_XUNLOCK(pdp);
+	pddrop(pdp);
 	free(efbuf, M_TEMP);
 	return (error);
 }

Modified: head/sys/kern/kern_exec.c
==============================================================================
--- head/sys/kern/kern_exec.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/kern_exec.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -700,6 +700,7 @@ interpret:
 		 * cannot be shared after an exec.
 		 */
 		fdunshare(td);
+		pdunshare(td);
 		/* close files on exec */
 		fdcloseexec(td);
 	}

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/kern_exit.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -367,6 +367,7 @@ exit1(struct thread *td, int rval, int signo)
 	 * Close open files and release open-file table.
 	 * This may block!
 	 */
+	pdescfree(td);
 	fdescfree(td);
 
 	/*

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/kern_fork.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -332,16 +332,22 @@ fork_norfproc(struct thread *td, int flags)
 	 */
 	if (flags & RFCFDG) {
 		struct filedesc *fdtmp;
+		struct pwddesc *pdtmp;
+		pdtmp = pdinit(td->td_proc->p_pd, false);
 		fdtmp = fdinit(td->td_proc->p_fd, false, NULL);
+		pdescfree(td);
 		fdescfree(td);
 		p1->p_fd = fdtmp;
+		p1->p_pd = pdtmp;
 	}
 
 	/*
 	 * Unshare file descriptors (from parent).
 	 */
-	if (flags & RFFDG)
+	if (flags & RFFDG) {
 		fdunshare(td);
+		pdunshare(td);
+	}
 
 fail:
 	if (((p1->p_flag & (P_HADTHREADS|P_SYSTEM)) == P_HADTHREADS) &&
@@ -360,6 +366,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct
 	struct proc *p1, *pptr;
 	struct filedesc *fd;
 	struct filedesc_to_leader *fdtol;
+	struct pwddesc *pd;
 	struct sigacts *newsigacts;
 
 	p1 = td->td_proc;
@@ -403,12 +410,15 @@ do_fork(struct thread *td, struct fork_req *fr, struct
 	 * Copy filedesc.
 	 */
 	if (fr->fr_flags & RFCFDG) {
+		pd = pdinit(p1->p_pd, false);
 		fd = fdinit(p1->p_fd, false, NULL);
 		fdtol = NULL;
 	} else if (fr->fr_flags & RFFDG) {
+		pd = pdcopy(p1->p_pd);
 		fd = fdcopy(p1->p_fd);
 		fdtol = NULL;
 	} else {
+		pd = pdshare(p1->p_pd);
 		fd = fdshare(p1->p_fd);
 		if (p1->p_fdtol == NULL)
 			p1->p_fdtol = filedesc_to_leader_alloc(NULL, NULL,
@@ -498,6 +508,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct
 	p2->p_textvp = p1->p_textvp;
 	p2->p_fd = fd;
 	p2->p_fdtol = fdtol;
+	p2->p_pd = pd;
 
 	if (p1->p_flag2 & P2_INHERIT_PROTECTED) {
 		p2->p_flag |= P_PROTECTED;

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/kern_proc.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -1144,6 +1144,7 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc
 	kp->ki_traceflag = p->p_traceflag;
 #endif
 	kp->ki_fd = p->p_fd;
+	kp->ki_pd = p->p_pd;
 	kp->ki_vmspace = p->p_vmspace;
 	kp->ki_flag = p->p_flag;
 	kp->ki_flag2 = p->p_flag2;
@@ -2967,7 +2968,7 @@ sysctl_kern_proc_umask(SYSCTL_HANDLER_ARGS)
 	u_int namelen = arg2;
 	struct proc *p;
 	int error;
-	u_short fd_cmask;
+	u_short cmask;
 	pid_t pid;
 
 	if (namelen != 1)
@@ -2976,7 +2977,7 @@ sysctl_kern_proc_umask(SYSCTL_HANDLER_ARGS)
 	pid = (pid_t)name[0];
 	p = curproc;
 	if (pid == p->p_pid || pid == 0) {
-		fd_cmask = p->p_fd->fd_cmask;
+		cmask = p->p_pd->pd_cmask;
 		goto out;
 	}
 
@@ -2984,10 +2985,10 @@ sysctl_kern_proc_umask(SYSCTL_HANDLER_ARGS)
 	if (error != 0)
 		return (error);
 
-	fd_cmask = p->p_fd->fd_cmask;
+	cmask = p->p_pd->pd_cmask;
 	PRELE(p);
 out:
-	error = SYSCTL_OUT(req, &fd_cmask, sizeof(fd_cmask));
+	error = SYSCTL_OUT(req, &cmask, sizeof(cmask));
 	return (error);
 }
 

Modified: head/sys/kern/kern_thread.c
==============================================================================
--- head/sys/kern/kern_thread.c	Tue Nov 17 20:01:21 2020	(r367776)
+++ head/sys/kern/kern_thread.c	Tue Nov 17 21:14:13 2020	(r367777)
@@ -88,15 +88,15 @@ _Static_assert(offsetof(struct thread, td_frame) == 0x
     "struct thread KBI td_frame");
 _Static_assert(offsetof(struct thread, td_emuldata) == 0x6b0,
     "struct thread KBI td_emuldata");
-_Static_assert(offsetof(struct proc, p_flag) == 0xb0,
+_Static_assert(offsetof(struct proc, p_flag) == 0xb8,
     "struct proc KBI p_flag");
-_Static_assert(offsetof(struct proc, p_pid) == 0xbc,
+_Static_assert(offsetof(struct proc, p_pid) == 0xc4,
     "struct proc KBI p_pid");
-_Static_assert(offsetof(struct proc, p_filemon) == 0x3b8,
+_Static_assert(offsetof(struct proc, p_filemon) == 0x3c0,
     "struct proc KBI p_filemon");
-_Static_assert(offsetof(struct proc, p_comm) == 0x3d0,
+_Static_assert(offsetof(struct proc, p_comm) == 0x3d8,
     "struct proc KBI p_comm");
-_Static_assert(offsetof(struct proc, p_emuldata) == 0x4b0,
+_Static_assert(offsetof(struct proc, p_emuldata) == 0x4b8,
     "struct proc KBI p_emuldata");
 #endif

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list