Subject: bread() returns EINVAL during vfs mount
To: None <tech-kern@NetBSD.org>
From: Yevgeny Binder <yevbee@comcast.net>
List: tech-kern
Date: 08/20/2005 21:47:18
I've tried to follow the ffs code closely while developing hfs+  
support, so it stumped me when I found that bread() invariably  
returns EINVAL in my VFS mount routine. I have a valid pointer to the  
volume's device node, devvp, obtained using the same ffs code:

     NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
     if ((error = namei(ndp)) != 0)
         return error;
     devvp = ndp->ni_vp;

ndp comes from the mount arguments, and args.fspec is presently set  
to "/dev/cd0a". I open this node and flush it:

     if ((error = VOP_OPEN(devvp, FREAD, FSCRED, p)) != 0)
         goto error;

     vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
     VOP_UNLOCK(devvp, 0);
     if (error != 0)
         goto error;

p also comes from the mount arguments, and cred = p ? p->p_ucred :  
NOCRED. Finally,

     struct buf *bp = NULL;
     error = bread(devvp, 16, 1536, cred, &bp);
     if (bp != NULL) {
         /* memcpy() would take the place of the printf() below in  
the real implementation */
         printf("bp->b_un.b_addr = %#x\n", (unsigned)bp->b_un.b_addr);
         brelse(bp);
     }

(The block number and length are temporarily hardcoded for testing.)  
This always produces an error 22, EINVAL. Interestingly, bp is not  
NULL, and bp->b_un.b_addr points to a seemingly valid location,  
albeit one with meaningless data (always 0xDEADBEEF, followed by two  
pointers, followed by a bunch of zeroes). I know that the device and  
its contents at the specified block range are good, because I have  
userland code which calls pread() on that range and returns perfectly  
correct data.

After trying dozens of changes that all resulted in the same error,  
the only possibility I can imagine is that I've somehow missed a  
subtle VFS call or preprocessor macro somewhere. But I've pored over  
the ffs code and I don't think I've left anything out. Could someone  
please outline the essential steps needed to go from receiving a VFS  
mount call to being able to call bread() successfully, including any  
vital preprocessor commands? I thought the above code was it, but  
then what's causing bread() to fail?

Thank you,
Yevgeny Binder