Skip site navigation (1)Skip section navigation (2)
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>