Skip site navigation (1)Skip section navigation (2)
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>