summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2009-09-28 16:59:47 +0000
committerdelphij <delphij@FreeBSD.org>2009-09-28 16:59:47 +0000
commit79f2f8c774b48d4ef62f92d4a09e80af3ceaca7c (patch)
tree1cca7c0ea10e2ad0213a1d75a2c8a8fe0061f4d4 /sys/kern
parentfd5f08e3e82b6caa8a7fff6a32c9e56b9212003e (diff)
downloadFreeBSD-src-79f2f8c774b48d4ef62f92d4a09e80af3ceaca7c.zip
FreeBSD-src-79f2f8c774b48d4ef62f92d4a09e80af3ceaca7c.tar.gz
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
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c44
-rw-r--r--sys/kern/vfs_vnops.c3
2 files changed, 47 insertions, 0 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 91733db..434f54a 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -421,6 +421,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
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, int cmd, intptr_t arg)
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;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 1b77352..03e8d93 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -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
OpenPOWER on IntegriCloud