Date: Mon, 25 Apr 2005 10:41:55 +0200 From: des@des.no (=?iso-8859-1?q?Dag-Erling_Sm=F8rgrav?=) To: stable@freebsd.org Subject: pseudofs bugfixes Message-ID: <868y376yek.fsf@xps.des.no>
next in thread | raw e-mail | index | archive | help
--Boundary_(ID_BfKroZeg3QB+3VncTgL1tw) Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: quoted-printable Could somebody please test the attached patch on a recent RELENG_5? It fixes a number of bugs in procfs and linprocfs; most notably, the output of "ls /proc" (or "ls /compat/linux/proc") would be truncated on systems with a largish number of processes (more than ~120). There's a locking fix there too; please look out for LORs and let me know if it introduces new ones (there are locking differences between HEAD and RELENG_5, so sauce for the goose is not necessarily sauce for the gander) DES --=20 Dag-Erling Sm=F8rgrav - des@des.no --Boundary_(ID_BfKroZeg3QB+3VncTgL1tw) Content-type: text/x-patch; NAME=pseudofs-mfc.diff Content-transfer-encoding: 7BIT Content-disposition: attachment; filename=pseudofs-mfc.diff Index: sys/fs/pseudofs/pseudofs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/pseudofs/pseudofs.c,v retrieving revision 1.22 diff -u -r1.22 pseudofs.c --- sys/fs/pseudofs/pseudofs.c 30 Jul 2004 22:08:50 -0000 1.22 +++ sys/fs/pseudofs/pseudofs.c 25 Apr 2005 08:35:19 -0000 @@ -24,10 +24,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_pseudofs.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> Index: sys/fs/pseudofs/pseudofs_fileno.c =================================================================== RCS file: /home/ncvs/src/sys/fs/pseudofs/pseudofs_fileno.c,v retrieving revision 1.10 diff -u -r1.10 pseudofs_fileno.c --- sys/fs/pseudofs/pseudofs_fileno.c 29 Apr 2003 13:36:01 -0000 1.10 +++ sys/fs/pseudofs/pseudofs_fileno.c 25 Apr 2005 08:35:19 -0000 @@ -24,10 +24,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_pseudofs.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> Index: sys/fs/pseudofs/pseudofs_vncache.c =================================================================== RCS file: /home/ncvs/src/sys/fs/pseudofs/pseudofs_vncache.c,v retrieving revision 1.26 diff -u -r1.26 pseudofs_vncache.c --- sys/fs/pseudofs/pseudofs_vncache.c 15 Aug 2004 21:58:02 -0000 1.26 +++ sys/fs/pseudofs/pseudofs_vncache.c 25 Apr 2005 08:35:19 -0000 @@ -24,10 +24,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_pseudofs.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -215,6 +218,10 @@ /* * Free all vnodes associated with a defunct process + * + * XXXRW: It is unfortunate that pfs_exit() always acquires and releases two + * mutexes (one of which is Giant) for every process exit, even if procfs + * isn't mounted. */ static void pfs_exit(void *arg, struct proc *p) @@ -222,6 +229,8 @@ struct pfs_vdata *pvd; struct vnode *vnp; + if (pfs_vncache == NULL) + return; mtx_lock(&Giant); /* * This is extremely inefficient due to the fact that vgone() not @@ -242,7 +251,9 @@ if (pvd->pvd_pid == p->p_pid) { vnp = pvd->pvd_vnode; mtx_unlock(&pfs_vncache_mutex); + VOP_LOCK(vnp, LK_EXCLUSIVE, curthread); vgone(vnp); + VOP_UNLOCK(vnp, 0, curthread); mtx_lock(&pfs_vncache_mutex); pvd = pfs_vncache; } else { @@ -272,7 +283,9 @@ if (pvd->pvd_pn == pn) { vnp = pvd->pvd_vnode; mtx_unlock(&pfs_vncache_mutex); + VOP_LOCK(vnp, LK_EXCLUSIVE, curthread); vgone(vnp); + VOP_UNLOCK(vnp, 0, curthread); mtx_lock(&pfs_vncache_mutex); pvd = pfs_vncache; } else { Index: sys/fs/pseudofs/pseudofs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/pseudofs/pseudofs_vnops.c,v retrieving revision 1.45.2.1 diff -u -r1.45.2.1 pseudofs_vnops.c --- sys/fs/pseudofs/pseudofs_vnops.c 6 Sep 2004 19:38:01 -0000 1.45.2.1 +++ sys/fs/pseudofs/pseudofs_vnops.c 25 Apr 2005 08:36:18 -0000 @@ -24,10 +24,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_pseudofs.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -36,6 +39,7 @@ #include <sys/fcntl.h> #include <sys/limits.h> #include <sys/lock.h> +#include <sys/malloc.h> #include <sys/mount.h> #include <sys/mutex.h> #include <sys/namei.h> @@ -48,17 +52,25 @@ #include <fs/pseudofs/pseudofs.h> #include <fs/pseudofs/pseudofs_internal.h> -#if 0 +#ifdef PSEUDOFS_TRACE +static int pfs_trace; +SYSCTL_INT(_vfs_pfs, OID_AUTO, trace, CTLFLAG_RW, &pfs_trace, 0, + "enable tracing of pseudofs vnode operations"); + #define PFS_TRACE(foo) \ do { \ - printf("pseudofs: %s(): line %d: ", __func__, __LINE__); \ - printf foo ; \ - printf("\n"); \ + if (pfs_trace) { \ + printf("%s(): line %d: ", __func__, __LINE__); \ + printf foo ; \ + printf("\n"); \ + } \ } while (0) #define PFS_RETURN(err) \ do { \ - printf("pseudofs: %s(): line %d: returning %d\n", \ - __func__, __LINE__, err); \ + if (pfs_trace) { \ + printf("%s(): line %d: returning %d\n", \ + __func__, __LINE__, err); \ + } \ return (err); \ } while (0) #else @@ -265,7 +277,7 @@ struct proc *proc = NULL; int error; - PFS_TRACE((pd->pn_name)); + PFS_TRACE((pn->pn_name)); if (!pfs_visible(curthread, pn, pvd->pvd_pid)) PFS_RETURN (ENOENT); @@ -299,18 +311,9 @@ /* * Look up a file or directory - * - * XXX NOTE! pfs_lookup() has been hooked into vop_lookup_desc! This - * will result in a lookup operation for a vnode which may already be - * cached, therefore we have to be careful to purge the VFS cache when - * reusing a vnode. - * - * This code will work, but is not really correct. Normally we would hook - * vfs_cache_lookup() into vop_lookup_desc and hook pfs_lookup() into - * vop_cachedlookup_desc. */ static int -pfs_lookup(struct vop_lookup_args *va) +pfs_lookup(struct vop_cachedlookup_args *va) { struct vnode *vn = va->a_dvp; struct vnode **vpp = va->a_vpp; @@ -319,24 +322,25 @@ struct pfs_node *pd = pvd->pvd_pn; struct pfs_node *pn, *pdn = NULL; pid_t pid = pvd->pvd_pid; - int lockparent; - int wantparent; char *pname; int error, i, namelen; PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr)); - cnp->cn_flags &= ~PDIRUNLOCK; - if (vn->v_type != VDIR) PFS_RETURN (ENOTDIR); + error = VOP_ACCESS(vn, VEXEC, cnp->cn_cred, cnp->cn_thread); + if (error) + PFS_RETURN (error); + /* * Don't support DELETE or RENAME. CREATE is supported so * that O_CREAT will work, but the lookup will still fail if * the file does not exist. */ - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) + if ((cnp->cn_flags & ISLASTCN) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) PFS_RETURN (EOPNOTSUPP); /* shortcut: check if the name is too long */ @@ -347,14 +351,10 @@ if (!pfs_visible(curthread, pd, pvd->pvd_pid)) PFS_RETURN (ENOENT); - lockparent = cnp->cn_flags & LOCKPARENT; - wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); - - /* self */ namelen = cnp->cn_namelen; pname = cnp->cn_nameptr; - if (namelen == 1 && *pname == '.') { + if (namelen == 1 && pname[0] == '.') { pn = pd; *vpp = vn; VREF(vn); @@ -366,8 +366,6 @@ if (pd->pn_type == pfstype_root) PFS_RETURN (EIO); VOP_UNLOCK(vn, 0, cnp->cn_thread); - cnp->cn_flags |= PDIRUNLOCK; - KASSERT(pd->pn_parent, ("non-root directory has no parent")); /* * This one is tricky. Descendents of procdir nodes @@ -388,8 +386,8 @@ for (pn = pd->pn_nodes; pn != NULL; pn = pn->pn_next) if (pn->pn_type == pfstype_procdir) pdn = pn; - else if (pn->pn_name[namelen] == '\0' - && bcmp(pname, pn->pn_name, namelen) == 0) + else if (pn->pn_name[namelen] == '\0' && + bcmp(pname, pn->pn_name, namelen) == 0) goto got_pnode; /* process dependent node */ @@ -406,28 +404,24 @@ got_pnode: if (pn != pd->pn_parent && !pn->pn_parent) pn->pn_parent = pd; - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) - PFS_RETURN (ENOENT); + if (!pfs_visible(curthread, pn, pvd->pvd_pid)) { + error = ENOENT; + goto failed; + } error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid); if (error) - PFS_RETURN (error); + goto failed; - if ((cnp->cn_flags & ISDOTDOT) && (cnp->cn_flags & ISLASTCN) - && lockparent) { + if (cnp->cn_flags & ISDOTDOT) vn_lock(vn, LK_EXCLUSIVE|LK_RETRY, cnp->cn_thread); - cnp->cn_flags &= ~PDIRUNLOCK; - } - if (!((lockparent && (cnp->cn_flags & ISLASTCN)) || - (cnp->cn_flags & ISDOTDOT))) - VOP_UNLOCK(vn, 0, cnp->cn_thread); - - /* - * XXX See comment at top of the routine. - */ if (cnp->cn_flags & MAKEENTRY) cache_enter(vn, *vpp, cnp); PFS_RETURN (0); + failed: + if (cnp->cn_flags & ISDOTDOT) + vn_lock(vn, LK_EXCLUSIVE|LK_RETRY, cnp->cn_thread); + PFS_RETURN(error); } /* @@ -606,7 +600,7 @@ struct proc *p; off_t offset; int error, i, resid; - struct sbuf sb; + char *buf, *ent; PFS_TRACE((pd->pn_name)); @@ -621,11 +615,11 @@ /* only allow reading entire entries */ offset = uio->uio_offset; resid = uio->uio_resid; - if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN) + if (offset < 0 || offset % PFS_DELEN != 0 || + (resid && resid < PFS_DELEN)) PFS_RETURN (EINVAL); - - if (sbuf_new(&sb, NULL, resid, SBUF_FIXEDLEN) == NULL) - PFS_RETURN (ENOMEM); + if (resid == 0) + PFS_RETURN (0); /* skip unwanted entries */ sx_slock(&allproc_lock); @@ -633,13 +627,14 @@ if (pfs_iterate(curthread, pid, pd, &pn, &p) == -1) { /* nothing left... */ sx_sunlock(&allproc_lock); - sbuf_delete(&sb); PFS_RETURN (0); } /* fill in entries */ + ent = buf = malloc(resid, M_IOV, M_WAITOK); entry.d_reclen = PFS_DELEN; - while (pfs_iterate(curthread, pid, pd, &pn, &p) != -1 && resid > 0) { + while (pfs_iterate(curthread, pid, pd, &pn, &p) != -1 && + resid >= PFS_DELEN) { if (!pn->pn_parent) pn->pn_parent = pd; if (!pn->pn_fileno) @@ -677,14 +672,14 @@ panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type); } PFS_TRACE((entry.d_name)); - sbuf_bcat(&sb, &entry, PFS_DELEN); + bcopy(&entry, ent, PFS_DELEN); /* XXX waste of cycles */ offset += PFS_DELEN; resid -= PFS_DELEN; + ent += PFS_DELEN; } sx_sunlock(&allproc_lock); - sbuf_finish(&sb); - error = uiomove(sbuf_data(&sb), sbuf_len(&sb), uio); - sbuf_delete(&sb); + error = uiomove(buf, ent - buf, uio); + free(buf, M_IOV); PFS_RETURN (error); } @@ -763,7 +758,7 @@ * Read from a file */ static int -pfs_write(struct vop_read_args *va) +pfs_write(struct vop_write_args *va) { struct vnode *vn = va->a_vp; struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; @@ -826,13 +821,14 @@ static struct vnodeopv_entry_desc pfs_vnodeop_entries[] = { { &vop_default_desc, (vop_t *)vop_defaultop }, { &vop_access_desc, (vop_t *)pfs_access }, + { &vop_cachedlookup_desc, (vop_t *)pfs_lookup }, { &vop_close_desc, (vop_t *)pfs_close }, { &vop_create_desc, (vop_t *)vop_eopnotsupp }, { &vop_getattr_desc, (vop_t *)pfs_getattr }, { &vop_getextattr_desc, (vop_t *)pfs_getextattr }, { &vop_ioctl_desc, (vop_t *)pfs_ioctl }, { &vop_link_desc, (vop_t *)vop_eopnotsupp }, - { &vop_lookup_desc, (vop_t *)pfs_lookup }, + { &vop_lookup_desc, (vop_t *)vfs_cache_lookup }, { &vop_mkdir_desc, (vop_t *)vop_eopnotsupp }, { &vop_mknod_desc, (vop_t *)vop_eopnotsupp }, { &vop_open_desc, (vop_t *)pfs_open }, --Boundary_(ID_BfKroZeg3QB+3VncTgL1tw)--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?868y376yek.fsf>