summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2008-01-01 01:46:42 +0000
committerjeff <jeff@FreeBSD.org>2008-01-01 01:46:42 +0000
commitd473542286827c0c2230741a59bf9977faa79e9d (patch)
treef10c97a280982f9fb9e6ac9344791dbaba0b9925
parent3032c5c97143e8c0b92bae65601cbb7f7c746699 (diff)
downloadFreeBSD-src-d473542286827c0c2230741a59bf9977faa79e9d.zip
FreeBSD-src-d473542286827c0c2230741a59bf9977faa79e9d.tar.gz
- Place the fhold() in unp_internalize_fp to be more consistent with refs.
- Clear all of the gc flags before doing a run. Stale flags were causing us to skip some descriptors. - If a unp socket has been marked REF in a gc pass it can't be dead. Found by: rwatson's test tool.
-rw-r--r--sys/kern/uipc_usrreq.c14
1 files changed, 5 insertions, 9 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 2f2b763..3c80483 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1763,7 +1763,6 @@ unp_internalize(struct mbuf **controlp, struct thread *td)
for (i = 0; i < oldfds; i++) {
fp = fdescp->fd_ofiles[*fdp++];
*rp++ = fp;
- fhold(fp);
unp_internalize_fp(fp);
}
FILEDESC_SUNLOCK(fdescp);
@@ -1887,6 +1886,7 @@ unp_internalize_fp(struct file *fp)
unp->unp_file = fp;
unp->unp_msgcount++;
}
+ fhold(fp);
unp_rights++;
UNP_GLOBAL_WUNLOCK();
}
@@ -1941,7 +1941,8 @@ unp_gc_process(struct unpcb *unp)
* queue as indicated by msgcount, and this must equal the file
* reference count. Note that when msgcount is 0 the file is NULL.
*/
- if (fp && fp->f_count != 0 && fp->f_count == unp->unp_msgcount) {
+ if ((unp->unp_gcflag & UNPGC_REF) == 0 && fp &&
+ unp->unp_msgcount != 0 && fp->f_count == unp->unp_msgcount) {
unp->unp_gcflag |= UNPGC_DEAD;
unp_unreachable++;
return;
@@ -1988,7 +1989,7 @@ unp_gc(__unused void *arg, int pending)
*/
for (head = heads; *head != NULL; head++)
LIST_FOREACH(unp, *head, unp_link)
- unp->unp_gcflag &= ~(UNPGC_REF|UNPGC_DEAD);
+ unp->unp_gcflag = 0;
/*
* Scan marking all reachable sockets with UNPGC_REF. Once a socket
* is reachable all of the sockets it references are reachable.
@@ -2019,6 +2020,7 @@ unp_gc(__unused void *arg, int pending)
LIST_FOREACH(unp, *head, unp_link)
if (unp->unp_gcflag & UNPGC_DEAD) {
unref[i++] = unp->unp_file;
+ fhold(unp->unp_file);
KASSERT(unp->unp_file != NULL,
("unp_gc: Invalid unpcb."));
KASSERT(i <= unp_unreachable,
@@ -2026,12 +2028,6 @@ unp_gc(__unused void *arg, int pending)
}
UNP_GLOBAL_RUNLOCK();
/*
- * All further operation is now done on a local list. We first ref
- * all sockets to avoid closing them until all are flushed.
- */
- for (i = 0; i < unp_unreachable; i++)
- fhold(unref[i]);
- /*
* Now flush all sockets, free'ing rights. This will free the
* struct files associated with these sockets but leave each socket
* with one remaining ref.
OpenPOWER on IntegriCloud