summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
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/kern_descrip.c
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/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c44
1 files changed, 44 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;
OpenPOWER on IntegriCloud