Author: delphij
Date: Mon Sep 28 16:59:47 2009
New Revision: 197579
URL: http://svn.freebsd.org/changeset/base/197579

Log:
  Add two new fcntls to enable/disable read-ahead:
  
   - F_READAHEAD: specify the amount for sequential access.  The amount is
     specified in bytes and is rounded up to nearest block size.
   - F_RDAHEAD: Darwin compatible version that use 128KB as the sequential
     access size.
  
  A third argument of zero disables the read-ahead behavior.
  
  Please note that the read-ahead amount is also constrainted by sysctl
  variable, vfs.read_max, which may need to be raised in order to better
  utilize this feature.
  
  Thanks Igor Sysoev for proposing the feature and submitting the original
  version, and kib@ for his valuable comments.
  
  Submitted by: Igor Sysoev <is rambler-co ru>
  Reviewed by:  kib@
  MFC after:    1 month

Modified:
  head/lib/libc/sys/fcntl.2
  head/sys/kern/kern_descrip.c
  head/sys/kern/vfs_vnops.c
  head/sys/sys/fcntl.h

Modified: head/lib/libc/sys/fcntl.2
==============================================================================
--- head/lib/libc/sys/fcntl.2   Mon Sep 28 15:11:49 2009        (r197578)
+++ head/lib/libc/sys/fcntl.2   Mon Sep 28 16:59:47 2009        (r197579)
@@ -28,7 +28,7 @@
 .\"     @(#)fcntl.2    8.2 (Berkeley) 1/12/94
 .\" $FreeBSD$
 .\"
-.Dd March 8, 2008
+.Dd September 28, 2009
 .Dt FCNTL 2
 .Os
 .Sh NAME
@@ -241,6 +241,22 @@ will be interrupted if the signal handle
 .Dv SA_RESTART
 (see
 .Xr sigaction 2 ) .
+.It Dv F_READAHEAD
+Set or clear the read ahead amount for sequential access to the third
+argument,
+.Fa arg ,
+which is rounded up to the nearest block size.
+A zero value in
+.Fa arg
+turns off read ahead.
+.It Dv F_RDAHEAD
+Equivalent to Darwin counterpart which sets read ahead amount of 128KB
+when the third argument,
+.Fa arg
+is non-zero.
+A zero value in
+.Fa arg
+turns off read ahead.
 .El
 .Pp
 When a shared lock has been set on a segment of a file,

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Mon Sep 28 15:11:49 2009        
(r197578)
+++ head/sys/kern/kern_descrip.c        Mon Sep 28 16:59:47 2009        
(r197579)
@@ -421,6 +421,8 @@ kern_fcntl(struct thread *td, int fd, in
        struct vnode *vp;
        int error, flg, tmp;
        int vfslocked;
+       u_int old, new;
+       uint64_t bsize;
 
        vfslocked = 0;
        error = 0;
@@ -686,6 +688,48 @@ kern_fcntl(struct thread *td, int fd, in
                vfslocked = 0;
                fdrop(fp, td);
                break;
+
+       case F_RDAHEAD:
+               arg = arg ? 128 * 1024: 0;
+               /* FALLTHROUGH */
+       case F_READAHEAD:
+               FILEDESC_SLOCK(fdp);
+               if ((fp = fdtofp(fd, fdp)) == NULL) {
+                       FILEDESC_SUNLOCK(fdp);
+                       error = EBADF;
+                       break;
+               }
+               if (fp->f_type != DTYPE_VNODE) {
+                       FILEDESC_SUNLOCK(fdp);
+                       error = EBADF;
+                       break;
+               }
+               fhold(fp);
+               FILEDESC_SUNLOCK(fdp);
+               if (arg != 0) {
+                       vp = fp->f_vnode;
+                       vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+                       error = vn_lock(vp, LK_SHARED);
+                       if (error != 0)
+                               goto readahead_vnlock_fail;
+                       bsize = fp->f_vnode->v_mount->mnt_stat.f_iosize;
+                       VOP_UNLOCK(vp, 0);
+                       fp->f_seqcount = (arg + bsize - 1) / bsize;
+                       do {
+                               new = old = fp->f_flag;
+                               new |= FRDAHEAD;
+                       } while (atomic_cmpset_rel_int(&fp->f_flag, old, new) 
== 0);
+readahead_vnlock_fail:
+                       VFS_UNLOCK_GIANT(vfslocked);
+               } else {
+                       do {
+                               new = old = fp->f_flag;
+                               new &= ~FRDAHEAD;
+                       } while (atomic_cmpset_rel_int(&fp->f_flag, old, new) 
== 0);
+               }
+               fdrop(fp, td);
+               break;
+
        default:
                error = EINVAL;
                break;

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c   Mon Sep 28 15:11:49 2009        (r197578)
+++ head/sys/kern/vfs_vnops.c   Mon Sep 28 16:59:47 2009        (r197579)
@@ -312,6 +312,9 @@ static int
 sequential_heuristic(struct uio *uio, struct file *fp)
 {
 
+       if (atomic_load_acq_int(&(fp->f_flag)) & FRDAHEAD)
+               return (fp->f_seqcount << IO_SEQSHIFT);
+
        /*
         * Offset 0 is handled specially.  open() sets f_seqcount to 1 so
         * that the first I/O is normally considered to be slightly

Modified: head/sys/sys/fcntl.h
==============================================================================
--- head/sys/sys/fcntl.h        Mon Sep 28 15:11:49 2009        (r197578)
+++ head/sys/sys/fcntl.h        Mon Sep 28 16:59:47 2009        (r197579)
@@ -140,7 +140,7 @@ typedef     __pid_t         pid_t;
 /* bits to save after open */
 #define        FMASK   
(FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT|FEXEC)
 /* bits settable by fcntl(F_SETFL, ...) */
-#define        FCNTLFLAGS      (FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT)
+#define        FCNTLFLAGS      
(FAPPEND|FASYNC|FFSYNC|FNONBLOCK|FRDAHEAD|O_DIRECT)
 
 #if defined(COMPAT_FREEBSD7) || defined(COMPAT_FREEBSD6) || \
     defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4)
@@ -151,7 +151,8 @@ typedef     __pid_t         pid_t;
  */
 #define        FPOSIXSHM       O_NOFOLLOW
 #undef FCNTLFLAGS
-#define        FCNTLFLAGS      
(FAPPEND|FASYNC|FFSYNC|FNONBLOCK|FPOSIXSHM|O_DIRECT)
+#define        FCNTLFLAGS      
(FAPPEND|FASYNC|FFSYNC|FNONBLOCK|FPOSIXSHM|FRDAHEAD| \
+                        O_DIRECT)
 #endif
 #endif
 
@@ -176,6 +177,8 @@ typedef     __pid_t         pid_t;
  * different meaning for fcntl(2).
  */
 #if __BSD_VISIBLE
+/* Read ahead */
+#define        FRDAHEAD        O_CREAT
 #endif
 
 /* Defined by POSIX Extended API Set Part 2 */
@@ -218,6 +221,8 @@ typedef     __pid_t         pid_t;
 #define        F_SETLK         12              /* set record locking 
information */
 #define        F_SETLKW        13              /* F_SETLK; wait if blocked */
 #define        F_SETLK_REMOTE  14              /* debugging support for remote 
locks */
+#define        F_READAHEAD     15              /* read ahead */
+#define        F_RDAHEAD       16              /* Darwin compatible read ahead 
*/
 
 /* file descriptor flags (F_GETFD, F_SETFD) */
 #define        FD_CLOEXEC      1               /* close-on-exec flag */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to