diff options
author | delphij <delphij@FreeBSD.org> | 2009-09-28 16:59:47 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2009-09-28 16:59:47 +0000 |
commit | 79f2f8c774b48d4ef62f92d4a09e80af3ceaca7c (patch) | |
tree | 1cca7c0ea10e2ad0213a1d75a2c8a8fe0061f4d4 /sys/kern/kern_descrip.c | |
parent | fd5f08e3e82b6caa8a7fff6a32c9e56b9212003e (diff) | |
download | FreeBSD-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.c | 44 |
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; |