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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to