From: Matthew Dillon Date: Sun, 28 Sep 2008 05:08:16 +0000 (+0000) Subject: Linux emulation adjustments. X-Git-Tag: v2.1.1~310 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/8b9535593fae52bd35c58089ec78e6d4244f11e6 Linux emulation adjustments. * 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. --- diff --git a/sys/emulation/linux/linux_file.c b/sys/emulation/linux/linux_file.c index dd0dfc5f01..341aa77231 100644 --- a/sys/emulation/linux/linux_file.c +++ b/sys/emulation/linux/linux_file.c @@ -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; diff --git a/sys/emulation/linux/linux_stats.c b/sys/emulation/linux/linux_stats.c index 2a455adfcf..74ebcb4a76 100644 --- a/sys/emulation/linux/linux_stats.c +++ b/sys/emulation/linux/linux_stats.c @@ -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 @@ -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); diff --git a/sys/emulation/linux/linux_util.h b/sys/emulation/linux/linux_util.h index 901c3a4c5f..93d37728b0 100644 --- a/sys/emulation/linux/linux_util.h +++ b/sys/emulation/linux/linux_util.h @@ -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_ */