PERFORCE change 85017 for review
soc-chenk
soc-chenk at FreeBSD.org
Sat Oct 8 15:42:27 PDT 2005
http://perforce.freebsd.org/chv.cgi?CH=85017
Change 85017 by soc-chenk at soc-chenk_leavemealone on 2005/10/08 22:41:37
conceptionally bad code eliminated from readdir handler
Submitted by: soc-chenk
Affected files ...
.. //depot/projects/soc2005/fuse4bsd2/fuse_module/fuse.c#12 edit
.. //depot/projects/soc2005/fuse4bsd2/fuselib/fuselib-2.4.0.diff#3 edit
Differences ...
==== //depot/projects/soc2005/fuse4bsd2/fuse_module/fuse.c#12 (text+ko) ====
@@ -3569,7 +3569,6 @@
}
#define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1)
-#define DIRENTSIZE(n) (sizeof(struct dirent) - MAXNAMLEN + (n))
static int
fuse_readdir(struct vop_readdir_args *ap)
@@ -3646,13 +3645,25 @@
err = fuse_read_directbackend(vp, fufh, uio, cred, td, FUSE_READDIR,
fuse_dir_buffeater, &cookediov);
#else
- err = fuse_read_biobackend(vp, NULL, uio, cred, td, FUSE_READDIR,
- fuse_dir_buffeater, &cookediov);
+ /*
+ * We tried hard to use bio, but offsety readdir can't be handled
+ * properly that way -- the offset field of fuse_dirents can't be
+ * mapped to an offset of a bio buffer
+ */
+ err = fuse_read_directbackend(vp, get_filehandle(vp, td, cred, FREAD),
+ uio, cred, td, FUSE_READDIR,
+ fuse_dir_buffeater, &cookediov);
#endif
fuse_iov_teardown(&cookediov);
return (err);
}
+/* A hack for being able to please the GENERIC_DIRSIZ macro */
+
+struct pseudo_dirent {
+ uint32_t d_namlen;
+};
+
static int
fuse_dir_buffeater(struct uio *uio, size_t reqsize, void *buf, size_t bufsize, void *param)
{
@@ -3700,7 +3711,7 @@
cookediov = param;
- DEBUG2G("entering loop\n");
+ DEBUG2G("entering loop with bufsize %d\n", bufsize);
/*
* Can we avoid infite loops? An infinite loop could occur only if we
@@ -3714,15 +3725,23 @@
* was completed, otherwise we hed exited above with -1.
*/
- while (bufsize >= FUSE_NAME_OFFSET) {
+ for (;;) {
#if ZERO_PAD_INCOMPLETE_BUFS
int i;
char *c;
#endif
+
+ if (bufsize < FUSE_NAME_OFFSET) {
+ err = -1;
+ break;
+ }
+
cou++;
fudge = (struct fuse_dirent *)buf;
freclen = FUSE_DIRENT_SIZE(fudge);
+ DEBUG("bufsize %d, freclen %d\n", bufsize, freclen);
+
/*
* Here is an exit condition: we terminate the whole reading
* process if a fresh chunk of buffer is already too short to
@@ -3747,42 +3766,17 @@
break;
}
#endif
-
+
/* Sanity checks */
- if (fudge->off < uio->uio_offset) {
- DEBUG2G("offsets out of sync at %d: fudge->off %d, uio->uio_offset %d\n",
- cou, (int)fudge->off, (int)uio->uio_offset);
- err = EIO;
- break;
- }
- /*
- * The "imaginary" amount of incoming data,
- * we fake towards userspace that we got this much,
- * to maintain offset consistency.
- * (The whole story starts with the "off" field of
- * fuse_dirent being imaginary -- it need not to be
- * the same as the amount of data got from the daemon.
- * It should be at least as much as the incoming data though,
- * hence the above sanity check.)
- */
- bytesavail = fudge->off - uio->uio_offset;
- if (!fudge->namelen || fudge->namelen > MAXNAMLEN) {
- DEBUG2G("bogus namelen at %d\n", cou);
- err = EIO;
- break;
- }
- if (freclen > bytesavail) {
- DEBUG2G("inconsistent fuse dirent at %d\n", cou);
- err = EIO;
- break;
- }
- if (DIRENTSIZE(fudge->namelen) > bytesavail) {
- DEBUG2G("fuse dirent is mystically too tight for our purposes at %d\n", cou);
+ if (!fudge->namelen || fudge->namelen > MAXNAMLEN) {
+ DEBUG2G("bogus namelen %d at turn %d\n",
+ fudge->namelen, cou);
err = EIO;
break;
}
+ bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *)&fudge->namelen);
/*
* Exit condition 2: if the pretended amount of input is more
@@ -3796,9 +3790,6 @@
break;
}
- DEBUG("bytesavail %d, fudge->off %llu, fudge->namelen %d, uio->uio_offset %d\n",
- bytesavail, fudge->off, fudge->namelen, (int)uio->uio_offset);
-
fuse_iov_audit(cookediov);
fuse_iov_adjust(cookediov, bytesavail);
de = (struct dirent *) cookediov->base;
@@ -3806,17 +3797,22 @@
de->d_reclen = bytesavail;
de->d_type = fudge->type;
de->d_namlen = fudge->namelen;
- memcpy((char *)cookediov->base + DIRENTSIZE(-1),
+ memcpy((char *)cookediov->base + sizeof(struct dirent) - MAXNAMLEN - 1,
(char *)buf + FUSE_NAME_OFFSET, fudge->namelen);
+ ((char *)cookediov->base)[bytesavail] = '\0';
+ DEBUG("bytesavail %d, fudge->off %llu, fudge->namelen %d, uio->uio_offset %d, name %s\n",
+ bytesavail, fudge->off, fudge->namelen, (int)uio->uio_offset,
+ (char *)cookediov->base + sizeof(struct dirent) - MAXNAMLEN - 1);
+
err = uiomove(cookediov->base, cookediov->len, uio);
if (err)
break;
- buf = (char*)buf + bytesavail;
- reqsize -= bytesavail;
- bufsize -= bytesavail;
+ buf = (char*)buf + freclen;
+ bufsize -= freclen;
+ uio->uio_offset = fudge->off;
}
return (err);
==== //depot/projects/soc2005/fuse4bsd2/fuselib/fuselib-2.4.0.diff#3 (text+ko) ====
@@ -56,7 +56,7 @@
st.st_ino = de->d_ino;
st.st_mode = de->d_type << 12;
+#ifdef __FreeBSD__
-+ if (filler(buf, de->d_name, &st, 0))
++ if (filler(buf, de->d_name, &st, telldir(dp)))
+#else
if (filler(buf, de->d_name, &st, de->d_off))
+#endif
More information about the p4-projects
mailing list