Page MenuHomeFreeBSD

D35987.diff
No OneTemporary

D35987.diff

Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c
+++ sys/kern/kern_descrip.c
@@ -2153,6 +2153,9 @@
if (fcaps != NULL)
filecaps_validate(fcaps, __func__);
FILEDESC_XLOCK_ASSERT(fdp);
+ KASSERT(refcount_load(&fdp->fd_refcnt) == 1 ||
+ (fp->f_ops->fo_flags & DFLAG_PASSABLE) != 0,
+ ("%s: file %p cannot be shared", __func__, fp));
fde = &fdp->fd_ofiles[fd];
#ifdef CAPABILITIES
@@ -2179,10 +2182,13 @@
MPASS(fd != NULL);
FILEDESC_XLOCK(fdp);
- error = fdalloc(td, 0, fd);
- if (__predict_true(error == 0)) {
+ if (__predict_false(refcount_load(&fdp->fd_refcnt) > 1) &&
+ (fp->f_ops->fo_flags & DFLAG_PASSABLE) == 0)
+ error = EOPNOTSUPP;
+ else
+ error = fdalloc(td, 0, fd);
+ if (__predict_true(error == 0))
_finstall(fdp, fp, *fd, flags, fcaps);
- }
FILEDESC_XUNLOCK(fdp);
return (error);
}
@@ -2336,14 +2342,38 @@
}
/*
- * Share a filedesc structure.
+ * Share a filedesc structure (among multiple processes). Descriptors that
+ * cannot be passed among processes may not exist in a shared table.
*/
struct filedesc *
fdshare(struct filedesc *fdp)
{
+ struct file *fp;
+ int i;
+ bool ok;
- refcount_acquire(&fdp->fd_refcnt);
- return (fdp);
+ ok = true;
+ FILEDESC_SLOCK(fdp);
+ FILEDESC_FOREACH_FP(fdp, i, fp) {
+ if ((fp->f_ops->fo_flags & DFLAG_PASSABLE) == 0) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok)
+ refcount_acquire(&fdp->fd_refcnt);
+ FILEDESC_SUNLOCK(fdp);
+ return (ok ? fdp : NULL);
+}
+
+void
+fdshare_abort(struct filedesc *fdp)
+{
+ bool released __diagused;
+
+ released = refcount_release(&fdp->fd_refcnt);
+ KASSERT(!released,
+ ("fdshare_abort: released last reference on %p", fdp));
}
/*
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -442,7 +442,9 @@
pd = pdcopy(p1->p_pd);
else
pd = pdshare(p1->p_pd);
- fd = fdshare(p1->p_fd);
+
+ /* FD table is already shared by the caller. */
+ fd = p1->p_fd;
if (p1->p_fdtol == NULL)
p1->p_fdtol = filedesc_to_leader_alloc(NULL, NULL,
p1->p_leader);
@@ -867,6 +869,7 @@
struct vmspace *vm2;
struct ucred *cred;
struct file *fp_procdesc;
+ struct filedesc *fdp;
vm_ooffset_t mem_charged;
int error, nprocs_new;
static int curfail;
@@ -925,10 +928,21 @@
return (fork_norfproc(td, flags));
}
+ fdp = NULL;
fp_procdesc = NULL;
newproc = NULL;
vm2 = NULL;
+ /*
+ * Take an extra reference to the file descriptor table if the table is
+ * to be shared.
+ */
+ if ((flags & RFFDG) == 0) {
+ fdp = fdshare(td->td_proc->p_fd);
+ if (fdp == NULL)
+ return (EOPNOTSUPP);
+ }
+
/*
* Increment the nprocs resource before allocations occur.
* Although process entries are dynamically created, we still
@@ -1060,6 +1074,8 @@
fail2:
if (vm2 != NULL)
vmspace_free(vm2);
+ if (fdp != NULL)
+ fdshare_abort(fdp);
uma_zfree(proc_zone, newproc);
if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) {
fdclose(td, fp_procdesc, *fr->fr_pd_fd);
Index: sys/sys/filedesc.h
===================================================================
--- sys/sys/filedesc.h
+++ sys/sys/filedesc.h
@@ -115,7 +115,7 @@
struct fdescenttbl *fd_files; /* open files table */
NDSLOTTYPE *fd_map; /* bitmap of free fds */
int fd_freefile; /* approx. next free file */
- int fd_refcnt; /* thread reference count */
+ int fd_refcnt; /* process reference count */
int fd_holdcnt; /* hold count on structure + mutex */
struct sx fd_sx; /* protects members of this struct */
struct kqlist fd_kqlist; /* list of kqueues on this filedesc */
@@ -267,6 +267,7 @@
int fdlastfile_single(struct filedesc *fdp);
struct filedesc *fdinit(void);
struct filedesc *fdshare(struct filedesc *fdp);
+void fdshare_abort(struct filedesc *fdp);
struct filedesc_to_leader *
filedesc_to_leader_alloc(struct filedesc_to_leader *old,
struct filedesc *fdp, struct proc *leader);

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 19, 10:34 PM (12 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31804922
Default Alt Text
D35987.diff (3 KB)

Event Timeline