svn commit: r254602 - in head/sys: fs/devfs kern sys

Konstantin Belousov kib at FreeBSD.org
Wed Aug 21 17:36:03 UTC 2013


Author: kib
Date: Wed Aug 21 17:36:01 2013
New Revision: 254602
URL: http://svnweb.freebsd.org/changeset/base/254602

Log:
  Make the seek a method of the struct fileops.
  
  Tested by:	pho
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/fs/devfs/devfs_vnops.c
  head/sys/kern/vfs_syscalls.c
  head/sys/kern/vfs_vnops.c
  head/sys/sys/file.h

Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c	Wed Aug 21 17:23:24 2013	(r254601)
+++ head/sys/fs/devfs/devfs_vnops.c	Wed Aug 21 17:36:01 2013	(r254602)
@@ -1697,6 +1697,7 @@ static struct fileops devfs_ops_f = {
 	.fo_chmod =	vn_chmod,
 	.fo_chown =	vn_chown,
 	.fo_sendfile =	vn_sendfile,
+	.fo_seek =	vn_seek,
 	.fo_flags =	DFLAG_PASSABLE | DFLAG_SEEKABLE
 };
 

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c	Wed Aug 21 17:23:24 2013	(r254601)
+++ head/sys/kern/vfs_syscalls.c	Wed Aug 21 17:36:01 2013	(r254602)
@@ -1879,77 +1879,15 @@ sys_lseek(td, uap)
 		int whence;
 	} */ *uap;
 {
-	struct ucred *cred = td->td_ucred;
 	struct file *fp;
-	struct vnode *vp;
-	struct vattr vattr;
-	off_t foffset, offset, size;
-	int error, noneg;
+	int error;
 
 	AUDIT_ARG_FD(uap->fd);
 	if ((error = fget(td, uap->fd, CAP_SEEK, &fp)) != 0)
 		return (error);
-	if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) {
-		fdrop(fp, td);
-		return (ESPIPE);
-	}
-	vp = fp->f_vnode;
-	foffset = foffset_lock(fp, 0);
-	noneg = (vp->v_type != VCHR);
-	offset = uap->offset;
-	switch (uap->whence) {
-	case L_INCR:
-		if (noneg &&
-		    (foffset < 0 ||
-		    (offset > 0 && foffset > OFF_MAX - offset))) {
-			error = EOVERFLOW;
-			break;
-		}
-		offset += foffset;
-		break;
-	case L_XTND:
-		vn_lock(vp, LK_SHARED | LK_RETRY);
-		error = VOP_GETATTR(vp, &vattr, cred);
-		VOP_UNLOCK(vp, 0);
-		if (error)
-			break;
-
-		/*
-		 * If the file references a disk device, then fetch
-		 * the media size and use that to determine the ending
-		 * offset.
-		 */
-		if (vattr.va_size == 0 && vp->v_type == VCHR &&
-		    fo_ioctl(fp, DIOCGMEDIASIZE, &size, cred, td) == 0)
-			vattr.va_size = size;
-		if (noneg &&
-		    (vattr.va_size > OFF_MAX ||
-		    (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
-			error = EOVERFLOW;
-			break;
-		}
-		offset += vattr.va_size;
-		break;
-	case L_SET:
-		break;
-	case SEEK_DATA:
-		error = fo_ioctl(fp, FIOSEEKDATA, &offset, cred, td);
-		break;
-	case SEEK_HOLE:
-		error = fo_ioctl(fp, FIOSEEKHOLE, &offset, cred, td);
-		break;
-	default:
-		error = EINVAL;
-	}
-	if (error == 0 && noneg && offset < 0)
-		error = EINVAL;
-	if (error != 0)
-		goto drop;
-	VFS_KNOTE_UNLOCKED(vp, 0);
-	*(off_t *)(td->td_retval) = offset;
-drop:
+	error = (fp->f_ops->fo_flags & DFLAG_SEEKABLE) != 0 ?
+	    fo_seek(fp, uap->offset, uap->whence, td) : ESPIPE;
 	fdrop(fp, td);
-	foffset_unlock(fp, offset, error != 0 ? FOF_NOUPDATE : 0);
 	return (error);
 }
 

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Wed Aug 21 17:23:24 2013	(r254601)
+++ head/sys/kern/vfs_vnops.c	Wed Aug 21 17:36:01 2013	(r254602)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/disk.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
 #include <sys/kdb.h>
@@ -101,6 +102,7 @@ struct 	fileops vnops = {
 	.fo_chmod = vn_chmod,
 	.fo_chown = vn_chown,
 	.fo_sendfile = vn_sendfile,
+	.fo_seek = vn_seek,
 	.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
 };
 
@@ -2010,3 +2012,72 @@ unlock:
 		*off = noff;
 	return (error);
 }
+
+int
+vn_seek(struct file *fp, off_t offset, int whence, struct thread *td)
+{
+	struct ucred *cred;
+	struct vnode *vp;
+	struct vattr vattr;
+	off_t foffset, size;
+	int error, noneg;
+
+	cred = td->td_ucred;
+	vp = fp->f_vnode;
+	foffset = foffset_lock(fp, 0);
+	noneg = (vp->v_type != VCHR);
+	error = 0;
+	switch (whence) {
+	case L_INCR:
+		if (noneg &&
+		    (foffset < 0 ||
+		    (offset > 0 && foffset > OFF_MAX - offset))) {
+			error = EOVERFLOW;
+			break;
+		}
+		offset += foffset;
+		break;
+	case L_XTND:
+		vn_lock(vp, LK_SHARED | LK_RETRY);
+		error = VOP_GETATTR(vp, &vattr, cred);
+		VOP_UNLOCK(vp, 0);
+		if (error)
+			break;
+
+		/*
+		 * If the file references a disk device, then fetch
+		 * the media size and use that to determine the ending
+		 * offset.
+		 */
+		if (vattr.va_size == 0 && vp->v_type == VCHR &&
+		    fo_ioctl(fp, DIOCGMEDIASIZE, &size, cred, td) == 0)
+			vattr.va_size = size;
+		if (noneg &&
+		    (vattr.va_size > OFF_MAX ||
+		    (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
+			error = EOVERFLOW;
+			break;
+		}
+		offset += vattr.va_size;
+		break;
+	case L_SET:
+		break;
+	case SEEK_DATA:
+		error = fo_ioctl(fp, FIOSEEKDATA, &offset, cred, td);
+		break;
+	case SEEK_HOLE:
+		error = fo_ioctl(fp, FIOSEEKHOLE, &offset, cred, td);
+		break;
+	default:
+		error = EINVAL;
+	}
+	if (error == 0 && noneg && offset < 0)
+		error = EINVAL;
+	if (error != 0)
+		goto drop;
+	VFS_KNOTE_UNLOCKED(vp, 0);
+	*(off_t *)(td->td_retval) = offset;
+drop:
+	foffset_unlock(fp, offset, error != 0 ? FOF_NOUPDATE : 0);
+	return (error);
+}

Modified: head/sys/sys/file.h
==============================================================================
--- head/sys/sys/file.h	Wed Aug 21 17:23:24 2013	(r254601)
+++ head/sys/sys/file.h	Wed Aug 21 17:36:01 2013	(r254602)
@@ -108,6 +108,8 @@ typedef	int fo_chown_t(struct file *fp, 
 typedef int fo_sendfile_t(struct file *fp, int sockfd, struct uio *hdr_uio,
 		    struct uio *trl_uio, off_t offset, size_t nbytes,
 		    off_t *sent, int flags, int kflags, struct thread *td);
+typedef int fo_seek_t(struct file *fp, off_t offset, int whence,
+		    struct thread *td);
 typedef	int fo_flags_t;
 
 struct fileops {
@@ -122,6 +124,7 @@ struct fileops {
 	fo_chmod_t	*fo_chmod;
 	fo_chown_t	*fo_chown;
 	fo_sendfile_t	*fo_sendfile;
+	fo_seek_t	*fo_seek;
 	fo_flags_t	fo_flags;	/* DFLAG_* below */
 };
 
@@ -242,6 +245,7 @@ fo_chown_t	invfo_chown;
 fo_sendfile_t	invfo_sendfile;
 
 fo_sendfile_t	vn_sendfile;
+fo_seek_t	vn_seek;
 
 void finit(struct file *, u_int, short, void *, struct fileops *);
 int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
@@ -370,6 +374,13 @@ fo_sendfile(struct file *fp, int sockfd,
 	    nbytes, sent, flags, kflags, td));
 }
 
+static __inline int
+fo_seek(struct file *fp, off_t offset, int whence, struct thread *td)
+{
+
+	return ((*fp->f_ops->fo_seek)(fp, offset, whence, td));
+}
+
 #endif /* _KERNEL */
 
 #endif /* !SYS_FILE_H */


More information about the svn-src-head mailing list