Module Name:    src
Committed By:   martin
Date:           Thu Aug 27 09:08:39 UTC 2020

Modified Files:
        src/sys/fs/union [netbsd-9]: union.h union_subr.c union_vnops.c

Log Message:
Pull up following revision(s) (requested by hannken in ticket #1062):

        sys/fs/union/union.h: revision 1.30
        sys/fs/union/union_subr.c: revision 1.79
        sys/fs/union/union_vnops.c: revision 1.74

Operation union_readdirhook() stores the lower directory as un_uppervp.
This breaks the assumption that un_uppervp->v_mount is the upper mount.

Fix by storing the directory as un_lowervp and adapt union_readdir().

Should fix PR kern/55552: panic with union mount


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.29.10.1 src/sys/fs/union/union.h
cvs rdiff -u -r1.77 -r1.77.8.1 src/sys/fs/union/union_subr.c
cvs rdiff -u -r1.70 -r1.70.14.1 src/sys/fs/union/union_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/union/union.h
diff -u src/sys/fs/union/union.h:1.29 src/sys/fs/union/union.h:1.29.10.1
--- src/sys/fs/union/union.h:1.29	Mon Jul 17 09:22:36 2017
+++ src/sys/fs/union/union.h	Thu Aug 27 09:08:39 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: union.h,v 1.29 2017/07/17 09:22:36 hannken Exp $	*/
+/*	$NetBSD: union.h,v 1.29.10.1 2020/08/27 09:08:39 martin Exp $	*/
 
 /*
  * Copyright (c) 1994 The Regents of the University of California.
@@ -130,6 +130,7 @@ struct union_node {
 	char			*un_path;	/* v: saved component name */
 	int			un_openl;	/* v: # of opens on lowervp */
 	unsigned int		un_cflags;	/* c: cache flags */
+	bool			un_hooknode;	/* :: from union_readdirhook */
 	struct vnode		**un_dircache;	/* v: cached union stack */
 	off_t			un_uppersz;	/* l: size of upper object */
 	off_t			un_lowersz;	/* l: size of lower object */

Index: src/sys/fs/union/union_subr.c
diff -u src/sys/fs/union/union_subr.c:1.77 src/sys/fs/union/union_subr.c:1.77.8.1
--- src/sys/fs/union/union_subr.c:1.77	Sun Jan 28 15:48:44 2018
+++ src/sys/fs/union/union_subr.c	Thu Aug 27 09:08:39 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_subr.c,v 1.77 2018/01/28 15:48:44 christos Exp $	*/
+/*	$NetBSD: union_subr.c,v 1.77.8.1 2020/08/27 09:08:39 martin Exp $	*/
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.77 2018/01/28 15:48:44 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.77.8.1 2020/08/27 09:08:39 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -479,6 +479,7 @@ found:
 	un->un_dircache = 0;
 	un->un_openl = 0;
 	un->un_cflags = 0;
+	un->un_hooknode = false;
 
 	un->un_uppersz = VNOVAL;
 	un->un_lowersz = VNOVAL;
@@ -1065,7 +1066,7 @@ union_dircache(struct vnode *vp, struct 
 	} else {
 		vpp = dircache;
 		do {
-			if (*vpp++ == VTOUNION(vp)->un_uppervp)
+			if (*vpp++ == VTOUNION(vp)->un_lowervp)
 				break;
 		} while (*vpp != NULLVP);
 	}
@@ -1074,10 +1075,12 @@ union_dircache(struct vnode *vp, struct 
 		goto out;
 
 	vref(*vpp);
-	error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, 0, *vpp, NULLVP, 0);
+	error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, 0,
+	    NULLVP, *vpp, 0);
 	if (!error) {
 		vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY);
 		VTOUNION(vp)->un_dircache = 0;
+		VTOUNION(nvp)->un_hooknode = true;
 		VTOUNION(nvp)->un_dircache = dircache;
 	}
 

Index: src/sys/fs/union/union_vnops.c
diff -u src/sys/fs/union/union_vnops.c:1.70 src/sys/fs/union/union_vnops.c:1.70.14.1
--- src/sys/fs/union/union_vnops.c:1.70	Fri May 26 14:21:01 2017
+++ src/sys/fs/union/union_vnops.c	Thu Aug 27 09:08:39 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_vnops.c,v 1.70 2017/05/26 14:21:01 riastradh Exp $	*/
+/*	$NetBSD: union_vnops.c,v 1.70.14.1 2020/08/27 09:08:39 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.70 2017/05/26 14:21:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.70.14.1 2020/08/27 09:08:39 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1492,13 +1492,29 @@ union_readdir(void *v)
 		int a_ncookies;
 	} */ *ap = v;
 	struct union_node *un = VTOUNION(ap->a_vp);
-	struct vnode *uvp = un->un_uppervp;
+	struct vnode *vp;
+	int dolock, error;
 
-	if (uvp == NULLVP)
-		return (0);
+	if (un->un_hooknode) {
+		KASSERT(un->un_uppervp == NULLVP);
+		KASSERT(un->un_lowervp != NULLVP);
+		vp = un->un_lowervp;
+		dolock = 1;
+	} else {
+		vp = un->un_uppervp;
+		dolock = 0;
+	}
+	if (vp == NULLVP)
+		return 0;
 
-	ap->a_vp = uvp;
-	return (VCALL(uvp, VOFFSET(vop_readdir), ap));
+	if (dolock)
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	ap->a_vp = vp;
+	error = VCALL(vp, VOFFSET(vop_readdir), ap);
+	if (dolock)
+		VOP_UNLOCK(vp);
+
+	return error;
 }
 
 int

Reply via email to