Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 May 2007 12:05:27 -0500
From:      "Scot Hetzel" <swhetzel@gmail.com>
To:        emulation@freebsd.org
Subject:   Re: linuxolator: LTP lseek03 failure
Message-ID:  <790a9fff0705061005v1a1a883ehc155bac7f747c3eb@mail.gmail.com>
In-Reply-To: <790a9fff0705040819u24e4c2f0s5c9fc34b93770e13@mail.gmail.com>
References:  <790a9fff0705021345j2ad9ae98o56aaf357d556fe27@mail.gmail.com> <790a9fff0705040004oab16ed8q1a1c476386379ea9@mail.gmail.com> <20070504190007.Y37951@besplex.bde.org> <790a9fff0705040819u24e4c2f0s5c9fc34b93770e13@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
On 5/4/07, Scot Hetzel <swhetzel@gmail.com> wrote:
> > The main bug is in the implementation of SEEK_HOLE and SEEK_DATA.  This
> > uses fo_ioctl() and fo_ioctl() returns ENOTTY if the file system doesn't
> > support these seeks, but ENOTTY (Inappropriate ioctl for device) is a
> > very inappropriate errno for a syscall that is not ioctl(), especially
> > on a file that is not a device.  POSIX requires EINVAL if the `whence'
> > arg is not a standard POSIX one, and I think ENOTTY should be translated
> > to this.
> >
>
> I see three places where this could be fixed:
>
>  kern/vfs_vnops.c:vn_ioctl(...)
>  kern/vfs_syscalls.c:lseek(...)
>  compat/linux/linux_file.c:(linux_lseek and linux_llseek)
>
> Would the best fix be to change the native lseek to return EINVAL when
> fo_ioctl returns ENOTTY?
>
I had a look at the OpenSolaris implementation of lseek and found that
we are returning the wrong error code for the ENOTTY case.  When
ENOTTY is returned by fo_ioctl, we should be checking for the
following cases:

SEEK_DATA - Is offset past end of file
SEEK_HOLE - Return virtual hole at end of file, if offset is valid

on error, SEEK_DATA and SEEK_HOLE should be returning ENXIO for these
cases.  OpenSolaris also checks offset > OFF_MAX, and returns
EOVERFLOW.

When the lseek03 test is run, with these changes, it returns with ENXIO.

I sent the attached patch for kern/vfs_syscalls.c to pjd for review.

Scot
-- 
DISCLAIMER:
No electrons were mamed while sending this message. Only slightly bruised.

[-- Attachment #2 --]
Index: vfs_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.438
diff -u -r1.438 vfs_syscalls.c
--- vfs_syscalls.c	4 May 2007 14:23:28 -0000	1.438
+++ vfs_syscalls.c	6 May 2007 15:37:39 -0000
@@ -1755,9 +1755,36 @@
 		break;
 	case SEEK_DATA:
 		error = fo_ioctl(fp, FIOSEEKDATA, &offset, cred, td);
+		if (error == ENOTTY) {
+			/*
+			 * The ioctl is not supported. Is the offset
+			 * past the end of the file.
+			 */
+			error = VOP_GETATTR(vp, &vattr, fp->f_cred, td);
+			if (error == 0 &&
+			   (offset >= (uoff_t)vattr.va_size))
+				error = ENXIO;
+		}
+		if (noneg && (offset > OFF_MAX))
+			error = EOVERFLOW;
 		break;
 	case SEEK_HOLE:
 		error = fo_ioctl(fp, FIOSEEKHOLE, &offset, cred, td);
+		if (error == ENOTTY) {
+			/*
+			 * The ioctl is not supported. Return virtual
+			 * hole at end of file, if offset is valid.
+			 */
+			error = VOP_GETATTR(vp, &vattr, fp->f_cred, td);
+			if (error == 0) {
+				if (uap->offset < (off_t)vattr.va_size)
+					offset = (uoff_t)vattr.va_size;
+				else
+					error = ENXIO;
+			}
+		}
+		if (noneg && (offset > OFF_MAX))
+			error = EOVERFLOW;
 		break;
 	default:
 		error = EINVAL;

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?790a9fff0705061005v1a1a883ehc155bac7f747c3eb>