Date: Wed, 2 May 2007 13:07:21 +0200 From: Csaba Henk <csaba.henk@creo.hu> To: Anish Mistry <amistry@am-productions.biz> Cc: freebsd-current@freebsd.org, Robert Watson <rwatson@freebsd.org>, Harald Schmalzbauer <h.schmalzbauer@omnisec.de> Subject: Re: Panic: fusefs crashes -current Message-ID: <20070502110721.GG79199@beastie.creo.hu> In-Reply-To: <200704281412.19978.amistry@am-productions.biz> References: <4630D572.1020204@omnisec.de> <20070428114243.N28395@fledge.watson.org> <200704281633.32639.h.schmalzbauer@omnisec.de> <200704281412.19978.amistry@am-productions.biz>
next in thread | previous in thread | raw e-mail | index | archive | help
--XRI2XbIfl/05pQwm
Content-Type: multipart/mixed; boundary="XIiC+We3v3zHqZ6Z"
Content-Disposition: inline
--XIiC+We3v3zHqZ6Z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi,
On Sat, Apr 28, 2007 at 02:12:14PM -0400, Anish Mistry wrote:
> I've been able to reproduce this issue. I've CC'd Csaba.
OK, I've fixed it. I send the patch against fuse4bsd-0.3.0_4
(it can be applied after running "make patch").
I also attach another bugfix backported from the devel version.
Csaba
--XIiC+We3v3zHqZ6Z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fix-CURRENT-newvnode.diff"
Content-Transfer-Encoding: quoted-printable
diff -r 205480c57d59 fuse_module/fuse.c
--- a/fuse_module/fuse.c Tue May 01 20:54:55 2007 +0200
+++ b/fuse_module/fuse.c Tue May 01 21:05:58 2007 +0200
@@ -2070,23 +2070,36 @@ fuse_mount(struct mount *mp, struct thre
M_WAITOK | M_ZERO);
=20
err =3D getnewvnode("fuse", mp, &fuse_vnops, &rvp);
+ if (! err) {
+ err =3D vn_lock(rvp, LK_EXCLUSIVE | LK_RETRY, td);
+#if NEW_VNODES_ADJUSTED_MANUALLY
+ if (err)
+ printf("fuse4bsd: leaking vnode %p\n", rvp);
+#endif
+ }
+
+ if (! err) {
+ /*
+ * FUSE_ROOT_ID as an inode number will be resolved directly.
+ * without resorting to the vfs hashing mechanism, thus it also
+ * can be inserted directly to the v_hash slot.
+ */
+ rvp->v_hash =3D FUSE_ROOT_ID;
+ fmnt->rvp =3D rvp;
+ fuse_vnode_init(rvp, fvdat, FUSE_ROOT_ID, VNON);
+ rvp->v_vflag |=3D VV_ROOT;
+#if NEW_VNODES_ADJUSTED_MANUALLY
+ err =3D insmntque(rvp, mp);
+#endif
+ }
=20
if (err) {
fdata_kick_set(data);
sx_xunlock(slock);
FREE(fvdat, M_FUSEFS);
goto out;
- }
-
- /*
- * FUSE_ROOT_ID as an inode number will be resolved directly.
- * without resorting to the vfs hashing mechanism, thus it also
- * can be inserted directly to the v_hash slot.
- */
- rvp->v_hash =3D FUSE_ROOT_ID;
- fmnt->rvp =3D rvp; =09
- fuse_vnode_init(rvp, fvdat, FUSE_ROOT_ID, VNON);
- rvp->v_vflag |=3D VV_ROOT;
+ } else
+ VOP_UNLOCK(rvp, 0, td);
=20
rootdone:
=20
@@ -2405,11 +2418,11 @@ fuse_vget_i(struct mount *mp, struct thr
fuse_vget_i(struct mount *mp, struct thread *td, uint64_t nodeid,
enum vtype vtyp, struct vnode **vpp, int wantnew)
{
+#define myflags LK_EXCLUSIVE | LK_RETRY
int err =3D 0;
struct fuse_mnt_data *fmnt;
struct fuse_vnode_data *fvdat;
struct vnode *vp2;
- int myflags =3D LK_EXCLUSIVE;
=20
DEBUG2G("mp %p: %s\n", mp, mp->mnt_stat.f_mntfromname);
DEBUG("been asked for vno #%llu\n", (unsigned long long)nodeid);
@@ -2470,6 +2483,18 @@ audit:
return (err);
}
=20
+#if NEW_VNODES_ADJUSTED_MANUALLY
+ err =3D vn_lock(*vpp, myflags, td);
+ if (err)
+ printf("fuse4bsd: leaking vnode %p\n", *vpp);
+ else
+ err =3D insmntque(*vpp, mp);
+ if (err) {
+ free(fvdat, M_FUSEFS);
+ return (err);
+ }
+#endif
+
/*
* There is no harm in fully initializing the vnode before trying
* at insertion, because vnodes are gc-d anyway. For the same reason,
@@ -2504,6 +2529,7 @@ audit:
vn_printf(*vpp, " * ");
#endif
return (err);
+#undef myflags
}
=20
=20
@@ -3571,7 +3597,20 @@ bringup:
bzero(fvdat, sizeof(*fvdat));
fuse_vnode_init(vp, fvdat, feo->nodeid, VREG);
vp->v_op =3D &fuse_vnops;
+#if NEW_VNODES_ADJUSTED_MANUALLY
+ {
+ struct mount *mp =3D vp->v_mount;
+
+ vp->v_mount =3D NULL;
+ err =3D insmntque(vp, mp);
+ if (err) {
+ free(fvdat, M_FUSEFS);
+ return (err);
+ }
+ }
+#else
VOP_UNLOCK(vp, 0, td);
+#endif
/*
* We can't let the vnode being vput() here, the caller wants
* that do by herself.
@@ -4687,8 +4726,12 @@ fuse_create(struct vop_create_args *ap)
if ((err =3D getnewvnode("fuse", dvp->v_mount, &fuse_vnops, vpp)))
return (err);
=20
- if ((err =3D vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread)))
+ if ((err =3D vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread))) {
+#if NEW_VNODES_ADJUSTED_MANUALLY
+ printf("fuse4bsd: leaking vnode %p\n", *vpp);
+#endif
return (err);
+ }
=20
MALLOC(fvdat, struct fuse_vnode_data *, sizeof(*fvdat), M_FUSEFS,
M_WAITOK | M_ZERO);
@@ -4708,6 +4751,9 @@ fuse_create(struct vop_create_args *ap)
*/
(*vpp)->v_op =3D &fuse_germ_vnops;
(*vpp)->v_data =3D fvdat;
+#if NEW_VNODES_ADJUSTED_MANUALLY
+ (*vpp)->v_mount =3D dvp->v_mount;
+#endif
=20
return (0);
=20
diff -r 205480c57d59 fuse_module/fuse.h
--- a/fuse_module/fuse.h Tue May 01 20:54:55 2007 +0200
+++ b/fuse_module/fuse.h Tue May 01 20:56:25 2007 +0200
@@ -9,6 +9,14 @@
#ifndef USE_OLD_CLONEHANDLER_API
#if __FreeBSD_version < 600034 || ( __FreeBSD_version >=3D 700000 && __Fre=
eBSD_version < 700002 )
#define USE_OLD_CLONEHANDLER_API
+#endif
+#endif
+
+#ifndef NEW_VNODES_ADJUSTED_MANUALLY
+#if __FreeBSD_version >=3D 700034
+#define NEW_VNODES_ADJUSTED_MANUALLY 1
+#else
+#define NEW_VNODES_ADJUSTED_MANUALLY 0
#endif
#endif
=20
--XIiC+We3v3zHqZ6Z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fix-io-on-hole-xd.diff"
Content-Transfer-Encoding: quoted-printable
diff -r c9549d324226 fuse_module/fuse.c
--- a/fuse_module/fuse.c Sat Feb 11 01:30:59 2006 +0200
+++ b/fuse_module/fuse.c Wed May 02 11:13:41 2007 +0200
@@ -4215,10 +4215,8 @@ fuse_read_biobackend(struct fuse_io_data
#if _DEBUG
prettyprint(bp->b_data, 48);
printf("\n");
-#if ZERO_PAD_INCOMPLETE_BUFS
prettyprint(bp->b_data + PAGE_SIZE, 48);
printf("\n");
-#endif
#endif
if (err) {
brelse(bp);
@@ -4492,13 +4490,6 @@ fuse_dir_buffeater(struct uio *uio, size
err =3D ((cou =3D=3D 1) ? -1 : 0);
break;
}
-
-#ifdef ZERO_PAD_INCOMPLETE_BUFS
- if (isbzero(buf), FUSE_NAME_OFFSET) {
- err =3D -1;
- break;
- }
-#endif
=20
/* Sanity checks */
=20
@@ -5741,23 +5732,16 @@ fuse_strategy_i(struct vnode *vp, struct
chunksize, (long long unsigned)fri->offset, respsize);
=09
if (respsize < chunksize) {
-#ifdef ZERO_PAD_INCOMPLETE_BUFS
/*
- * "if we don't get enough data, just fill the
- * rest with zeros."
- * in nfs context this means a hole in the
- * file, I don't know what to do with this
- * here... [we just get a buch of zeroes
- * instead of EOF, baaad]
+ * if we don't get enough data, just fill the
+ * rest with zeros.
*/=20
DEBUG("zeroing tail of %ld bytes\n",
bp->b_resid);
bzero((char *)bp->b_data + bp->b_bcount - bp->b_resid,
bp->b_resid);
- bp->b_resid =3D 0;
-#else
+
break;
-#endif
}
ticket_refresh(fdi.tick);
DEBUG("bp->b_data %p\n", bp->b_data);
--XIiC+We3v3zHqZ6Z--
--XRI2XbIfl/05pQwm
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (FreeBSD)
iD8DBQFGOHDn6tF8nOdLsHQRAkpXAKDRSaSbdjPMAIU0LsXEKLyukxAWWQCgt69T
Eji8kO0gQCCLg3+xFxgz3Mo=
=1sDn
-----END PGP SIGNATURE-----
--XRI2XbIfl/05pQwm--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070502110721.GG79199>
