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
This commit is contained in:
parent
557532b407
commit
379e7f5553
|
@ -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 */
|
||||
|
|
|
@ -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 lwp *l)
|
|||
} 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 lwp *l)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue