看板 DFBSD_bugs 關於我們 聯絡資訊
Here's the patch to fix the linprocfs problem. Since linprocfs wasn't working at all before (in HEAD), I have already committed this. I also ripped out the single sequential linked list with a simple hash table to make linprocfs more efficient. -Matt Matthew Dillon <dillon@backplane.com> Index: linprocfs_subr.c =================================================================== RCS file: /cvs/src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v retrieving revision 1.13 diff -u -r1.13 linprocfs_subr.c --- linprocfs_subr.c 12 Oct 2004 19:20:38 -0000 1.13 +++ linprocfs_subr.c 19 Oct 2004 09:27:21 -0000 @@ -39,7 +39,7 @@ * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 * * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_subr.c,v 1.3.2.4 2001/06/25 19:46:47 pirzyk Exp $ - * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.13 2004/10/12 19:20:38 dillon Exp $ + * $DragonFly$ */ #include <sys/param.h> @@ -50,7 +50,10 @@ #include <sys/mount.h> #include "linprocfs.h" -static struct pfsnode *pfshead; +#define PFSHSIZE 256 +#define PFSHMASK (PFSHSIZE - 1) + +static struct pfsnode *pfshead[PFSHSIZE]; static int pfsvplock; extern int procfs_domem (struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio); @@ -95,7 +98,7 @@ int error; loop: - for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) { + for (pfs = pfshead[pid & PFSHMASK]; pfs; pfs = pfs->pfs_next) { vp = PFSTOV(pfs); if (pfs->pfs_pid == pid && pfs->pfs_type == pfs_type && @@ -199,7 +202,7 @@ } /* add to procfs vnode list */ - for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next) + for (pp = &pfshead[pid & PFSHMASK]; *pp; pp = &(*pp)->pfs_next) continue; *pp = pfs; @@ -223,15 +226,14 @@ struct pfsnode **pfspp; struct pfsnode *pfs = VTOPFS(vp); - for (pfspp = &pfshead; *pfspp != 0; pfspp = &(*pfspp)->pfs_next) { - if (*pfspp == pfs) { - *pfspp = pfs->pfs_next; - break; - } + pfspp = &pfshead[pfs->pfs_pid & PFSHMASK]; + while (*pfspp != pfs) { + KKASSERT(*pfspp != NULL); + pfspp = &(*pfspp)->pfs_next; } - + *pfspp = pfs->pfs_next; FREE(vp->v_data, M_TEMP); - vp->v_data = 0; + vp->v_data = NULL; return (0); } @@ -365,32 +367,23 @@ linprocfs_exit(struct thread *td) { struct pfsnode *pfs; - pid_t pid = (td->td_proc) ? td->td_proc->p_pid : -1; /* YYY */ + struct vnode *vp; + pid_t pid; + + KKASSERT(td->td_proc); + pid = td->td_proc->p_pid; /* - * The reason for this loop is not obvious -- basicly, - * linprocfs_freevp(), which is called via vgone() (eventually), - * removes the specified procfs node from the pfshead list. - * It does this by *pfsp = pfs->pfs_next, meaning that it - * overwrites the node. So when we do pfs = pfs->next, we - * end up skipping the node that replaces the one that was - * vgone'd. Since it may have been the last one on the list, - * it may also have been set to null -- but *our* pfs pointer, - * here, doesn't see this. So the loop starts from the beginning - * again. - * - * This is not a for() loop because the final event - * would be "pfs = pfs->pfs_next"; in the case where - * pfs is set to pfshead again, that would mean that - * pfshead is skipped over. - * + * Remove all the procfs vnodes associated with an exiting process. */ - pfs = pfshead; - while (pfs) { +restart: + for (pfs = pfshead[pid & PFSHMASK]; pfs; pfs = pfs->pfs_next) { if (pfs->pfs_pid == pid) { - vgone(PFSTOV(pfs)); - pfs = pfshead; - } else - pfs = pfs->pfs_next; + vp = PFSTOV(pfs); + if (vx_get(vp) == 0) + vgone(vp); + goto restart; + } } } +