Date: Thu, 11 Aug 2016 22:53:03 +0000 From: Rick Macklem <rmacklem@uoguelph.ca> To: Harry Schmalzbauer <freebsd@omnilan.de>, Mark Johnston <markj@freebsd.org> Cc: FreeBSD Stable <freebsd-stable@freebsd.org>, "kib@FreeBSD.org" <kib@FreeBSD.org> Subject: Re: unionfs bugs, a partial patch and some comments [Was: Re: 1-BETA3 Panic: __lockmgr_args: downgrade a recursed lockmgr nfs @ /usr/local/share/deploy-tools/RELENG_11/src/sys/fs/unionfs/union_vnops.c:1905] Message-ID: <YTOPR01MB0412B2A08F1A3C1A3B2EB160DD1E0@YTOPR01MB0412.CANPRD01.PROD.OUTLOOK.COM> In-Reply-To: <57A9A6C0.9060609@omnilan.de> References: <57A79E24.8000100@omnilan.de> <YQBPR01MB0401201977AEA8A803F27B23DD1A0@YQBPR01MB0401.CANPRD01.PROD.OUTLOOK.COM> <57A83C78.1070403@omnilan.de> <20160809060213.GA67664@raichu>,<57A9A6C0.9060609@omnilan.de>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] Harry Schmalzbauer wrote: Bezüglich Mark Johnston's Nachricht vom 09.08.2016 08:02 (localtime): … >> >> Just for anybody else needing unionfs: >> https://people.freebsd.org/~attilio/unionfs_missing_insmntque_lock.patch >> >> This patch still applies and I'm successfully using this (unmodified) up >> to FreeBSD-10.3 and never had any panic in all these years. > > Having spent some time looking at unionfs, I'm a bit skeptical that this > patch will address the panic you reported earlier, though I'd be > interested to know if it does. [stuff snipped for brevity] I took a look at this. (I know nothing about unionfs, but a little w.r.t. the VFS). I can confirm that this function (unionfs_nodeget()) is weird and appears to be broken to me. The function calls insmntque() before it initializes the vnode, which seems racey, especially if it isn't LK_EXCLUSIVE locked. Also, line#s 278-281: if (uppervp != NULLVP) vp->v_vnlock = uppervp->v_vnlock; else vp->v_vnlock = lowervp->v_vnlock; so your patch isn't locking the vnode lock that it actually uses. I think the vp argument to insmntque() is required to be LK_EXCLUSIVE locked mostly so other threads won't fiddle with the vnode until this function is done with it, but I am not sure? I think a more correct version of this (not saying it would be correct[😉], would call insmntque() later in the function, after it has been initialized. (This means that the cleanup if it fails is more involved, but...) I've attached a patch (untested) that does this. Maybe you could try it? rick ps: I've cc'd Kostik, in case he has some insight w.r.t. how this should be handled? [-- Attachment #2 --] --- fs/unionfs/union_subr.c.sav 2016-08-11 18:20:10.585999000 -0400 +++ fs/unionfs/union_subr.c 2016-08-11 18:40:51.119220000 -0400 @@ -255,11 +255,6 @@ unionfs_nodeget(struct mount *mp, struct free(unp, M_UNIONFSNODE); return (error); } - error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */ - if (error != 0) { - free(unp, M_UNIONFSNODE); - return (error); - } if (dvp != NULLVP) vref(dvp); if (uppervp != NULLVP) @@ -293,6 +288,28 @@ unionfs_nodeget(struct mount *mp, struct (lowervp != NULLVP && ump->um_lowervp == lowervp)) vp->v_vflag |= VV_ROOT; + /* + * Not sure if LK_RETRY is needed here? + * Normally, this would be done with a lockmgr() call, but in + * this case, v_vnlock is actually a vnode lock for either the + * uppervp or lowervp, so I used the vn_lock() call. + */ + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + error = insmntque(vp, mp); + if (error != 0) { + if (dvp != NULLVP) + vrele(dvp); + if (uppervp != NULLVP) + vrele(uppervp); + if (lowervp != NULLVP) + vrele(lowervp); + free(unp->un_hashtbl, M_UNIONFSHASH); + free(unp->un_path, M_UNIONFSPATH); + free(unp, M_UNIONFSNODE); + return (error); + } + VOP_UNLOCK(vp, 0); + if (path != NULL && dvp != NULLVP && vt == VDIR) *vpp = unionfs_ins_cached_vnode(unp, dvp, path); if ((*vpp) != NULLVP) { @@ -314,6 +331,7 @@ unionfs_nodeget(struct mount *mp, struct unionfs_nodeget_out: if (lkflags & LK_TYPE_MASK) + /* Should there be a check for VI_DOOMED here? */ vn_lock(vp, lkflags | LK_RETRY); return (0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?YTOPR01MB0412B2A08F1A3C1A3B2EB160DD1E0>
