Subject: Re: bread() returns EINVAL during vfs mount
To: Yevgeny Binder <yevbee@comcast.net>
From: Bill Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 08/22/2005 14:49:19
--OROCMA9jn6tkzFBc
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
On Sat, Aug 20, 2005 at 09:47:18PM -0500, Yevgeny Binder wrote:
> I've tried to follow the ffs code closely while developing hfs+ =20
> support, so it stumped me when I found that bread() invariably =20
> returns EINVAL in my VFS mount routine. I have a valid pointer to the =20
> volume's device node, devvp, obtained using the same ffs code:
>=20
> NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
> if ((error =3D namei(ndp)) !=3D 0)
> return error;
> devvp =3D ndp->ni_vp;
>=20
> ndp comes from the mount arguments, and args.fspec is presently set =20
> to "/dev/cd0a". I open this node and flush it:
>=20
> if ((error =3D VOP_OPEN(devvp, FREAD, FSCRED, p)) !=3D 0)
> goto error;
>=20
> vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
> error =3D vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
> VOP_UNLOCK(devvp, 0);
> if (error !=3D 0)
> goto error;
>=20
> p also comes from the mount arguments, and cred =3D p ? p->p_ucred : =20
> NOCRED. Finally,
>=20
> struct buf *bp =3D NULL;
> error =3D bread(devvp, 16, 1536, cred, &bp);
> if (bp !=3D NULL) {
> /* memcpy() would take the place of the printf() below in =20
> the real implementation */
> printf("bp->b_un.b_addr =3D %#x\n", (unsigned)bp->b_un.b_addr);
> brelse(bp);
> }
>=20
> (The block number and length are temporarily hardcoded for testing.) =20
> This always produces an error 22, EINVAL. Interestingly, bp is not =20
> NULL, and bp->b_un.b_addr points to a seemingly valid location, =20
> albeit one with meaningless data (always 0xDEADBEEF, followed by two =20
> pointers, followed by a bunch of zeroes). I know that the device and =20
> its contents at the specified block range are good, because I have =20
> userland code which calls pread() on that range and returns perfectly =20
> correct data.
The problem is that pread() permits i/o access that is not permitted with=
=20
the buffer cache system. So it covers over issues that bread() won't.
The problem is that you have to read full blocks. On a CD, that means 2k.=
=20
1536 is not an integer number of blocks, thus an EINVAL error.
> After trying dozens of changes that all resulted in the same error, =20
> the only possibility I can imagine is that I've somehow missed a =20
> subtle VFS call or preprocessor macro somewhere. But I've pored over =20
> the ffs code and I don't think I've left anything out. Could someone =20
> please outline the essential steps needed to go from receiving a VFS =20
> mount call to being able to call bread() successfully, including any =20
> vital preprocessor commands? I thought the above code was it, but =20
> then what's causing bread() to fail?
I think the problem is that you have drawn inspiration from file systems=20
that never face this issue. If someone ever built an ffs file system on a=
=20
CD, it would use 2k blocks, so all i/o would be 2k by nature and this=20
issue would never come up. :-|
Take care,
Bill
--OROCMA9jn6tkzFBc
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (NetBSD)
iD8DBQFDCkheWz+3JHUci9cRAuRuAJ0exnLAJaieVnWR612TpNyM8WwRRwCfWy8d
hnblI8rW4kiarBWjqntr+ME=
=mks5
-----END PGP SIGNATURE-----
--OROCMA9jn6tkzFBc--