On Tue, Sep 01, 2009 at 04:13:50PM +0000, Alex Hornung (via DragonFly issue 
tracker) wrote:
> 
> Alex Hornung <[email protected]> added the comment:
> 
> A test program showing the problem with linux_getdents (if it occurs with it) 
> would be helpful, too.

Unfortunately, I don't know enough about userland system programming to create
one.

Howewer, I have tracked the bug to this commit:
http://gitweb.dragonflybsd.org/dragonfly.git/commit/e54488bbec5c9f80e95cedd395b0e3d31fde253d
"AMD64 - Refactor uio_resid and size_t assumptions."

The attached patch allows the Linux ls(1) is again able to list files.
It is to be applied in /usr/src/sys/emulation/linux and basically reverts
linux_file.c to the previous version, with enough changes to make it compile
in a recent trunk.

Think of it as a quick-and-dirty hack, there were many more changes in the
Linux emulation files which I haven't yet reviewed.

-- 
Francois Tigeot
--- linux_file.c.orig   2009-09-02 10:26:44 +0200
+++ linux_file.c        2009-09-02 10:32:42 +0200
@@ -75,7 +75,7 @@
        error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
        if (error == 0) {
                error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC,
-                                 args->mode, &args->sysmsg_iresult);
+                                   args->mode, &args->sysmsg_result);
        }
        linux_free_path(&path);
        return(error);
@@ -135,14 +135,14 @@
        error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
        if (error == 0) {
                error = kern_open(&nd, flags,
-                                 args->mode, &args->sysmsg_iresult);
+                                   args->mode, &args->sysmsg_result);
        }
 
        if (error == 0 && !(flags & O_NOCTTY) && 
                SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
                struct file *fp;
 
-               fp = holdfp(p->p_fd, args->sysmsg_iresult, -1);
+               fp = holdfp(p->p_fd, args->sysmsg_result, -1);
                if (fp) {
                        if (fp->f_type == DTYPE_VNODE)
                                fo_ioctl(fp, TIOCSCTTY, NULL, p->p_ucred, NULL);
@@ -202,9 +202,9 @@
        lda.fd = args->fd;
        lda.dent = args->dent;
        lda.count = -1;
-       lda.sysmsg_iresult = 0;
+       lda.sysmsg_result = 0;
        error = sys_linux_getdents(&lda);
-       args->sysmsg_iresult = lda.sysmsg_iresult;
+       args->sysmsg_result = lda.sysmsg_result;
        return(error);
 }
 
@@ -245,11 +245,9 @@
        struct dirent *bdp;
        struct vnode *vp;
        caddr_t inp, buf;               /* BSD-format */
-       int reclen;                     /* BSD-format */
-       size_t len;
+       int len, reclen;                /* BSD-format */
        caddr_t outp;                   /* Linux-format */
-       int linuxreclen = 0;            /* Linux-format */
-       size_t resid;
+       int resid, linuxreclen=0;       /* Linux-format */
        struct file *fp;
        struct uio auio;
        struct iovec aiov;
@@ -257,8 +255,7 @@
        off_t off;
        struct l_dirent linux_dirent;
        struct l_dirent64 linux_dirent64;
-       int error, eofflag, justone;
-       size_t buflen, nbytes;
+       int buflen, error, eofflag, nbytes, justone;
        off_t *cookies = NULL, *cookiep;
        int ncookies;
 
@@ -282,7 +279,7 @@
                goto done;
 
        nbytes = args->count;
-       if (nbytes == (size_t)-1) {
+       if (nbytes == -1) {
                /* readdir(2) case. Always struct dirent. */
                if (is64bit) {
                        error = EINVAL;
@@ -293,7 +290,7 @@
        } else {
                justone = 0;
        }
-       if ((size_t)nbytes < 0)
+       if (nbytes < 0)
                nbytes = 0;
 
        off = fp->f_offset;
@@ -327,9 +324,9 @@
        inp = buf;
        outp = (caddr_t)args->dirent;
        resid = nbytes;
-       if (auio.uio_resid >= buflen);
+       if ((len = buflen - auio.uio_resid) <= 0)
                goto eof;
-       len = buflen - auio.uio_resid;
+
        cookiep = cookies;
 
        if (cookies) {
@@ -440,7 +437,7 @@
                nbytes = resid + linuxreclen;
 
 eof:
-       args->sysmsg_iresult = (int)(nbytes - resid);
+       args->sysmsg_result = nbytes - resid;
 
 out:
        if (cookies)
@@ -692,7 +689,7 @@
        error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
        if (error == 0) {
                error = kern_readlink(&nd, args->buf, args->count,
-                                     &args->sysmsg_iresult);
+                                       &args->sysmsg_result);
        }
        nlookup_done(&nd);
        linux_free_path(&path);
@@ -814,10 +811,10 @@
        int error;
 
        bsd.fd = uap->fd;
-       bsd.sysmsg_iresult = 0;
+       bsd.sysmsg_result = 0;
 
        error = sys_fsync(&bsd);
-       uap->sysmsg_iresult = bsd.sysmsg_iresult;
+       uap->sysmsg_result = bsd.sysmsg_result;
        return(error);
 }
 
@@ -839,12 +836,10 @@
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_td = td;
 
-       if ((ssize_t)auio.uio_resid < 0) {
+       if (auio.uio_resid < 0)
                error = EINVAL;
-       } else {
-               error = kern_preadv(uap->fd, &auio, O_FOFFSET,
-                                   &uap->sysmsg_szresult);
-       }
+       else
+               error = kern_preadv(uap->fd, &auio, O_FOFFSET, 
&uap->sysmsg_result);
        return(error);
 }
 
@@ -866,12 +861,11 @@
         auio.uio_segflg = UIO_USERSPACE;
         auio.uio_td = td;
 
-       if ((ssize_t)auio.uio_resid < 0) {
+       if (auio.uio_resid < 0)
                error = EINVAL;
-       } else {
-               error = kern_pwritev(uap->fd, &auio, O_FOFFSET,
-                                    &uap->sysmsg_szresult);
-       }
+       else
+               error = kern_pwritev(uap->fd, &auio, O_FOFFSET, 
&uap->sysmsg_result);
+
        return(error);
 }
 
@@ -883,9 +877,9 @@
 
        args2.path = args->path;
        args2.flags = 0;
-       args2.sysmsg_iresult = 0;
+       args2.sysmsg_result = 0;
        error = sys_linux_umount(&args2);
-       args->sysmsg_iresult = args2.sysmsg_iresult;
+       args->sysmsg_result = args2.sysmsg_result;
        return(error);
 }
 
@@ -897,10 +891,10 @@
 
        bsd.path = args->path;
        bsd.flags = args->flags;        /* XXX correct? */
-       bsd.sysmsg_iresult = 0;
+       bsd.sysmsg_result = 0;
 
        error = sys_unmount(&bsd);
-       args->sysmsg_iresult = bsd.sysmsg_iresult;
+       args->sysmsg_result = bsd.sysmsg_result;
        return(error);
 }
 
@@ -1087,29 +1081,29 @@
        if (error == 0) {
                switch (args->cmd) {
                case LINUX_F_DUPFD:
-                       args->sysmsg_iresult = dat.fc_fd;
+                       args->sysmsg_result = dat.fc_fd;
                        break;
                case LINUX_F_GETFD:
-                       args->sysmsg_iresult = dat.fc_cloexec;
+                       args->sysmsg_result = dat.fc_cloexec;
                        break;
                case LINUX_F_SETFD:
                        break;
                case LINUX_F_GETFL:
-                       args->sysmsg_iresult = 0;
+                       args->sysmsg_result = 0;
                        if (dat.fc_flags & O_RDONLY)
-                               args->sysmsg_iresult |= LINUX_O_RDONLY;
+                               args->sysmsg_result |= LINUX_O_RDONLY;
                        if (dat.fc_flags & O_WRONLY)
-                               args->sysmsg_iresult |= LINUX_O_WRONLY;
+                               args->sysmsg_result |= LINUX_O_WRONLY;
                        if (dat.fc_flags & O_RDWR)
-                               args->sysmsg_iresult |= LINUX_O_RDWR;
+                               args->sysmsg_result |= LINUX_O_RDWR;
                        if (dat.fc_flags & O_NDELAY)
-                               args->sysmsg_iresult |= LINUX_O_NONBLOCK;
+                               args->sysmsg_result |= LINUX_O_NONBLOCK;
                        if (dat.fc_flags & O_APPEND)
-                               args->sysmsg_iresult |= LINUX_O_APPEND;
+                               args->sysmsg_result |= LINUX_O_APPEND;
                        if (dat.fc_flags & O_FSYNC)
-                               args->sysmsg_iresult |= LINUX_O_SYNC;
+                               args->sysmsg_result |= LINUX_O_SYNC;
                        if (dat.fc_flags & O_ASYNC)
-                               args->sysmsg_iresult |= LINUX_FASYNC;
+                               args->sysmsg_result |= LINUX_FASYNC;
                        break;
                case LINUX_F_GETLK:
                        bsd_to_linux_flock(&dat.fc_flock, &linux_flock);
@@ -1120,7 +1114,7 @@
                case LINUX_F_SETLKW:
                        break;
                case LINUX_F_GETOWN:
-                       args->sysmsg_iresult = dat.fc_owner;
+                       args->sysmsg_result = dat.fc_owner;
                        break;
                case LINUX_F_SETOWN:
                        break;
@@ -1144,9 +1138,9 @@
        args64.fd = args->fd;
        args64.cmd = args->cmd;
        args64.arg = args->arg;
-       args64.sysmsg_iresult = 0;
+       args64.sysmsg_result = 0;
        error = linux_fcntl_common(&args64);
-       args->sysmsg_iresult = args64.sysmsg_iresult;
+       args->sysmsg_result = args64.sysmsg_result;
        return(error);
 }
 

Reply via email to