From d473542286827c0c2230741a59bf9977faa79e9d Mon Sep 17 00:00:00 2001 From: jeff Date: Tue, 1 Jan 2008 01:46:42 +0000 Subject: - 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. --- sys/kern/uipc_usrreq.c | 14 +++++--------- 1 file 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. -- cgit v1.1