Date: Sun, 11 Mar 2012 19:36:41 -0500 From: Mark Linimon <linimon@lonesome.com> To: bug-followup@FreeBSD.org Cc: freebsd-fs@FreeBSD.org Subject: [luis.garces@gmail.com: kern/164445: [zfs][patch] WAS: lseek(2) always returns ENXIO with SEEK_DATA/SEEK_HOLE on 9.0 64bit ZFS] Message-ID: <20120312003641.GA7675@lonesome.com>
next in thread | raw e-mail | index | archive | help
----- Forwarded message from Luis Garces-Erice <luis.garces@gmail.com> ----- Date: Wed, 7 Mar 2012 20:53:35 +0100 From: Luis Garces-Erice <luis.garces@gmail.com> To: freebsd-bugs@freebsd.org Subject: kern/164445: [zfs][patch] WAS: lseek(2) always returns ENXIO with SEEK_DATA/SEEK_HOLE on 9.0 64bit ZFS Hi all after digging a bit more into this (http://www.freebsd.org/cgi/query-pr.cgi?pr=164445), I've found the problem to be in ZFS or below. The patch attached addresses the symptom, but the problem remains. When invoking SEEK_DATA/SEEK_HOLE on a file on ZFS in FreeBSD 9.0 64 bit, the functions ddi_copyin and ddi_copyout in zfs_ioctl() do not copy the offset passed from the application to the ioctl. The offset is passed correctly to zfs_ioctl(), though, but those functions copy garbage into the offset used by zfs_holey(). The corrupted offset is often bigger than the file, and thus the ioctl returns ENXIO. The patch does the copy of the offset passed from the application correctly, and allows lseek(2) with SEEK_DATA/SEEK_HOLE to be used on ZFS, but it is not a solution. I couldn't see a problem in the assembler of the copyin and copyout functions in sys/amd64/amd64/support.S, but I might be wrong, I'm no assembler expert. -- Luis **** diff -w -u -r sys.orig/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c --- sys.orig/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2012-01-03 04:27:03.000000000 +0100 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2012-03-06 11:26:27.000000000 +0100 @@ -296,6 +296,8 @@ if (ddi_copyin((void *)data, &off, sizeof (off), flag)) return (EFAULT); + // ddi_copyin did not copy the offset + off = (offset_t)*((offset_t *)data); zp = VTOZ(vp); zfsvfs = zp->z_zfsvfs; ZFS_ENTER(zfsvfs); @@ -308,6 +310,8 @@ return (error); if (ddi_copyout(&off, (void *)data, sizeof (off), flag)) return (EFAULT); + // ddi_copyout did not copy the offset + *((offset_t *)data)=off; return (0); } return (ENOTTY); ----- End forwarded message -----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120312003641.GA7675>