Linux emulation adjustments.
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 28 Sep 2008 05:08:16 +0000 (05:08 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 28 Sep 2008 05:08:16 +0000 (05:08 +0000)
* Change the special case value for the compat option to getdents,
  newer versions of linux were using the value to probe availability
  of the 64 bit getdents.

* Change the cookie sequencing a bit for getdents.  It still isn't quite
  right.

* Generate a hashed 32 bit inode number from our 64 bit inode number.

sys/emulation/linux/linux_file.c
sys/emulation/linux/linux_stats.c
sys/emulation/linux/linux_util.h

index dd0dfc5..341aa77 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $
- * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.38 2007/11/20 21:36:07 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.39 2008/09/28 05:08:16 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -201,7 +201,7 @@ sys_linux_readdir(struct linux_readdir_args *args)
 
        lda.fd = args->fd;
        lda.dent = args->dent;
-       lda.count = 1;
+       lda.count = -1;
        lda.sysmsg_result = 0;
        error = sys_linux_getdents(&lda);
        args->sysmsg_result = lda.sysmsg_result;
@@ -279,7 +279,7 @@ getdents_common(struct linux_getdents64_args *args, int is64bit)
                goto done;
 
        nbytes = args->count;
-       if (nbytes == 1) {
+       if (nbytes == -1) {
                /* readdir(2) case. Always struct dirent. */
                if (is64bit) {
                        error = EINVAL;
@@ -290,6 +290,8 @@ getdents_common(struct linux_getdents64_args *args, int is64bit)
        } else {
                justone = 0;
        }
+       if (nbytes < 0)
+               nbytes = 0;
 
        off = fp->f_offset;
 
@@ -313,6 +315,8 @@ again:
                cookies = NULL;
        }
 
+       eofflag = 0;
+       ncookies = 0;
        if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
                 &cookies)))
                goto out;
@@ -333,7 +337,7 @@ again:
                 * partway through a directory entry, even if the directory
                 * has been compacted).
                 */
-               while (len > 0 && ncookies > 0 && *cookiep <= off) {
+               while (len > 0 && ncookies > 0 && *cookiep < off) {
                        bdp = (struct dirent *) inp;
                        len -= _DIRENT_DIRSIZ(bdp);
                        inp += _DIRENT_DIRSIZ(bdp);
@@ -356,10 +360,11 @@ again:
                        inp += reclen;
                        if (cookiep) {
                                off = *cookiep++;
+                               ++off;
                                ncookies--;
-                       } else
+                       } else {
                                off += reclen;
-
+                       }
                        len -= reclen;
                        continue;
                }
@@ -373,9 +378,11 @@ again:
                        break;
                }
 
+               bzero(&linux_dirent, sizeof(linux_dirent));
+               bzero(&linux_dirent64, sizeof(linux_dirent64));
                if (justone) {
                        /* readdir(2) case. */
-                       linux_dirent.d_ino = (l_long)bdp->d_ino;
+                       linux_dirent.d_ino = (l_long)INO64TO32(bdp->d_ino);
                        linux_dirent.d_off = (l_off_t)linuxreclen;
                        linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
                        strcpy(linux_dirent.d_name, bdp->d_name);
@@ -393,7 +400,7 @@ again:
                                error = copyout(&linux_dirent64, outp,
                                    linuxreclen);
                        } else {
-                               linux_dirent.d_ino = bdp->d_ino;
+                               linux_dirent.d_ino = INO64TO32(bdp->d_ino);
                                linux_dirent.d_off = (cookiep)
                                    ? (l_off_t)*cookiep
                                    : (l_off_t)(off + reclen);
@@ -409,9 +416,11 @@ again:
                inp += reclen;
                if (cookiep) {
                        off = *cookiep++;
+                       ++off;
                        ncookies--;
-               } else
+               } else {
                        off += reclen;
+               }
 
                outp += linuxreclen;
                resid -= linuxreclen;
index 2a455ad..74ebcb4 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_stats.c,v 1.22.2.3 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.26 2007/05/08 02:31:42 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.27 2008/09/28 05:08:16 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -59,7 +59,7 @@ newstat_copyout(struct stat *buf, void *ubuf)
        int error;
 
        tbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
-       tbuf.st_ino = buf->st_ino;
+       tbuf.st_ino = INO64TO32(buf->st_ino);
        tbuf.st_mode = buf->st_mode;
        tbuf.st_nlink = buf->st_nlink;
        tbuf.st_uid = buf->st_uid;
@@ -364,7 +364,7 @@ stat64_copyout(struct stat *buf, void *ubuf)
         * but without the assignment to __st_ino the runtime linker refuses
         * to mmap(2) any shared libraries. I guess it's broken alright :-)
         */
-       lbuf.__st_ino = buf->st_ino;
+       lbuf.__st_ino = INO64TO32(buf->st_ino);
 
        error = copyout(&lbuf, ubuf, sizeof(lbuf));
        return (error);
index 901c3a4..93d3772 100644 (file)
@@ -29,7 +29,7 @@
  * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp
  * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp
  * $FreeBSD: src/sys/compat/linux/linux_util.h,v 1.12.2.2 2000/11/02 23:31:28 obrien Exp $
- * $DragonFly: src/sys/emulation/linux/linux_util.h,v 1.11 2006/12/23 00:27:02 swildner Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_util.h,v 1.12 2008/09/28 05:08:16 dillon Exp $
  */
 
 /*
@@ -113,4 +113,6 @@ unsupported_msg(const char *fname)
        return (ENOSYS);
 }
 
+#define INO64TO32(v64) ((l_ulong)(v64) ^ (l_ulong)((v64) >> 32))
+
 #endif /* !_LINUX_UTIL_H_ */