Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/vfs_vnops.c
Show First 20 Lines • Show All 483 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Heuristic to detect sequential operation. | * Heuristic to detect sequential operation. | ||||
*/ | */ | ||||
static int | static int | ||||
sequential_heuristic(struct uio *uio, struct file *fp) | sequential_heuristic(struct uio *uio, struct file *fp) | ||||
{ | { | ||||
enum uio_rw rw; | |||||
ASSERT_VOP_LOCKED(fp->f_vnode, __func__); | ASSERT_VOP_LOCKED(fp->f_vnode, __func__); | ||||
rw = uio->uio_rw; | |||||
if (fp->f_flag & FRDAHEAD) | if (fp->f_flag & FRDAHEAD) | ||||
return (fp->f_seqcount << IO_SEQSHIFT); | return (fp->f_seqcount[rw] << IO_SEQSHIFT); | ||||
/* | /* | ||||
* Offset 0 is handled specially. open() sets f_seqcount to 1 so | * Offset 0 is handled specially. open() sets f_seqcount to 1 so | ||||
* that the first I/O is normally considered to be slightly | * that the first I/O is normally considered to be slightly | ||||
* sequential. Seeking to offset 0 doesn't change sequentiality | * sequential. Seeking to offset 0 doesn't change sequentiality | ||||
* unless previous seeks have reduced f_seqcount to 0, in which | * unless previous seeks have reduced f_seqcount to 0, in which | ||||
* case offset 0 is not special. | * case offset 0 is not special. | ||||
*/ | */ | ||||
if ((uio->uio_offset == 0 && fp->f_seqcount > 0) || | if ((uio->uio_offset == 0 && fp->f_seqcount[rw] > 0) || | ||||
uio->uio_offset == fp->f_nextoff) { | uio->uio_offset == fp->f_nextoff[rw]) { | ||||
/* | /* | ||||
* f_seqcount is in units of fixed-size blocks so that it | * f_seqcount is in units of fixed-size blocks so that it | ||||
* depends mainly on the amount of sequential I/O and not | * depends mainly on the amount of sequential I/O and not | ||||
* much on the number of sequential I/O's. The fixed size | * much on the number of sequential I/O's. The fixed size | ||||
* of 16384 is hard-coded here since it is (not quite) just | * of 16384 is hard-coded here since it is (not quite) just | ||||
* a magic size that works well here. This size is more | * a magic size that works well here. This size is more | ||||
* closely related to the best I/O size for real disks than | * closely related to the best I/O size for real disks than | ||||
* to any block size used by software. | * to any block size used by software. | ||||
*/ | */ | ||||
if (uio->uio_resid >= IO_SEQMAX * 16384) | if (uio->uio_resid >= IO_SEQMAX * 16384) | ||||
fp->f_seqcount = IO_SEQMAX; | fp->f_seqcount[rw] = IO_SEQMAX; | ||||
else { | else { | ||||
fp->f_seqcount += howmany(uio->uio_resid, 16384); | fp->f_seqcount[rw] += howmany(uio->uio_resid, 16384); | ||||
if (fp->f_seqcount > IO_SEQMAX) | if (fp->f_seqcount[rw] > IO_SEQMAX) | ||||
fp->f_seqcount = IO_SEQMAX; | fp->f_seqcount[rw] = IO_SEQMAX; | ||||
} | } | ||||
return (fp->f_seqcount << IO_SEQSHIFT); | return (fp->f_seqcount[rw] << IO_SEQSHIFT); | ||||
} | } | ||||
/* Not sequential. Quickly draw-down sequentiality. */ | /* Not sequential. Quickly draw-down sequentiality. */ | ||||
if (fp->f_seqcount > 1) | if (fp->f_seqcount[rw] > 1) | ||||
fp->f_seqcount = 1; | fp->f_seqcount[rw] = 1; | ||||
else | else | ||||
fp->f_seqcount = 0; | fp->f_seqcount[rw] = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Package up an I/O request on a vnode into a uio and do it. | * Package up an I/O request on a vnode into a uio and do it. | ||||
*/ | */ | ||||
int | int | ||||
vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, | vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
volatile short *flagsp; | volatile short *flagsp; | ||||
short state; | short state; | ||||
KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); | KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); | ||||
if ((flags & FOF_NOUPDATE) == 0) | if ((flags & FOF_NOUPDATE) == 0) | ||||
atomic_store_long(&fp->f_offset, val); | atomic_store_long(&fp->f_offset, val); | ||||
if ((flags & FOF_NEXTOFF) != 0) | if ((flags & FOF_NEXTOFF_R) != 0) | ||||
fp->f_nextoff = val; | fp->f_nextoff[UIO_READ] = val; | ||||
if ((flags & FOF_NEXTOFF_W) != 0) | |||||
fp->f_nextoff[UIO_WRITE] = val; | |||||
if ((flags & FOF_NOLOCK) != 0) | if ((flags & FOF_NOLOCK) != 0) | ||||
return; | return; | ||||
flagsp = &fp->f_vnread_flags; | flagsp = &fp->f_vnread_flags; | ||||
state = atomic_load_16(flagsp); | state = atomic_load_16(flagsp); | ||||
if ((state & FOFFSET_LOCK_WAITING) == 0 && | if ((state & FOFFSET_LOCK_WAITING) == 0 && | ||||
atomic_cmpset_rel_16(flagsp, state, 0)) | atomic_cmpset_rel_16(flagsp, state, 0)) | ||||
Show All 36 Lines | foffset_unlock(struct file *fp, off_t val, int flags) | ||||
struct mtx *mtxp; | struct mtx *mtxp; | ||||
KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); | KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); | ||||
mtxp = mtx_pool_find(mtxpool_sleep, fp); | mtxp = mtx_pool_find(mtxpool_sleep, fp); | ||||
mtx_lock(mtxp); | mtx_lock(mtxp); | ||||
if ((flags & FOF_NOUPDATE) == 0) | if ((flags & FOF_NOUPDATE) == 0) | ||||
fp->f_offset = val; | fp->f_offset = val; | ||||
if ((flags & FOF_NEXTOFF) != 0) | if ((flags & FOF_NEXTOFF_R) != 0) | ||||
fp->f_nextoff = val; | fp->f_nextoff[UIO_READ] = val; | ||||
if ((flags & FOF_NEXTOFF_W) != 0) | |||||
fp->f_nextoff[UIO_WRITE] = val; | |||||
if ((flags & FOF_NOLOCK) == 0) { | if ((flags & FOF_NOLOCK) == 0) { | ||||
KASSERT((fp->f_vnread_flags & FOFFSET_LOCKED) != 0, | KASSERT((fp->f_vnread_flags & FOFFSET_LOCKED) != 0, | ||||
("Lost FOFFSET_LOCKED")); | ("Lost FOFFSET_LOCKED")); | ||||
if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING) | if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING) | ||||
wakeup(&fp->f_vnread_flags); | wakeup(&fp->f_vnread_flags); | ||||
fp->f_vnread_flags = 0; | fp->f_vnread_flags = 0; | ||||
} | } | ||||
mtx_unlock(mtxp); | mtx_unlock(mtxp); | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | vn_read(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, | ||||
} | } | ||||
orig_offset = uio->uio_offset; | orig_offset = uio->uio_offset; | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_vnode_check_read(active_cred, fp->f_cred, vp); | error = mac_vnode_check_read(active_cred, fp->f_cred, vp); | ||||
if (error == 0) | if (error == 0) | ||||
#endif | #endif | ||||
error = VOP_READ(vp, uio, ioflag, fp->f_cred); | error = VOP_READ(vp, uio, ioflag, fp->f_cred); | ||||
fp->f_nextoff = uio->uio_offset; | fp->f_nextoff[UIO_READ] = uio->uio_offset; | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
if (error == 0 && advice == POSIX_FADV_NOREUSE && | if (error == 0 && advice == POSIX_FADV_NOREUSE && | ||||
orig_offset != uio->uio_offset) | orig_offset != uio->uio_offset) | ||||
/* | /* | ||||
* Use POSIX_FADV_DONTNEED to flush pages and buffers | * Use POSIX_FADV_DONTNEED to flush pages and buffers | ||||
* for the backing file after a POSIX_FADV_NOREUSE | * for the backing file after a POSIX_FADV_NOREUSE | ||||
* read(2). | * read(2). | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | vn_write(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, | ||||
} | } | ||||
orig_offset = uio->uio_offset; | orig_offset = uio->uio_offset; | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_vnode_check_write(active_cred, fp->f_cred, vp); | error = mac_vnode_check_write(active_cred, fp->f_cred, vp); | ||||
if (error == 0) | if (error == 0) | ||||
#endif | #endif | ||||
error = VOP_WRITE(vp, uio, ioflag, fp->f_cred); | error = VOP_WRITE(vp, uio, ioflag, fp->f_cred); | ||||
fp->f_nextoff = uio->uio_offset; | fp->f_nextoff[UIO_WRITE] = uio->uio_offset; | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
if (vp->v_type != VCHR) | if (vp->v_type != VCHR) | ||||
vn_finished_write(mp); | vn_finished_write(mp); | ||||
if (error == 0 && advice == POSIX_FADV_NOREUSE && | if (error == 0 && advice == POSIX_FADV_NOREUSE && | ||||
orig_offset != uio->uio_offset) | orig_offset != uio->uio_offset) | ||||
/* | /* | ||||
* Use POSIX_FADV_DONTNEED to flush pages and buffers | * Use POSIX_FADV_DONTNEED to flush pages and buffers | ||||
* for the backing file after a POSIX_FADV_NOREUSE | * for the backing file after a POSIX_FADV_NOREUSE | ||||
▲ Show 20 Lines • Show All 2,300 Lines • Show Last 20 Lines |