diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2023-11-19 22:23:20 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2023-11-19 22:25:45 +0000 |
commit | 305a2676ae93fb50a623024d51039415521cb2da (patch) | |
tree | 9ef87990264a865ddaa2dec739e525665e60fe9a | |
parent | 99c79cab422705f92f05a2924a29bdf823372ebf (diff) | |
download | src-305a2676ae93fb50a623024d51039415521cb2da.tar.gz src-305a2676ae93fb50a623024d51039415521cb2da.zip |
vfs: dodge locking for lseek(fd, 0, SEEK_CUR)
It is very common and according to dtrace while running poudriere almost
all calls with SEEK_CUR pass 0.
-rw-r--r-- | sys/kern/vfs_vnops.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index f81516608eeb..4669296750e4 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -828,6 +828,13 @@ foffset_unlock(struct file *fp, off_t val, int flags) sleepq_broadcast(&fp->f_vnread_flags, SLEEPQ_SLEEP, 0, 0); sleepq_release(&fp->f_vnread_flags); } + +static off_t +foffset_read(struct file *fp) +{ + + return (atomic_load_long(&fp->f_offset)); +} #else off_t foffset_lock(struct file *fp, int flags) @@ -876,6 +883,13 @@ foffset_unlock(struct file *fp, off_t val, int flags) } mtx_unlock(mtxp); } + +static off_t +foffset_read(struct file *fp) +{ + + return (foffset_lock(fp, FOF_NOLOCK)); +} #endif void @@ -2647,8 +2661,19 @@ vn_seek(struct file *fp, off_t offset, int whence, struct thread *td) cred = td->td_ucred; vp = fp->f_vnode; - foffset = foffset_lock(fp, 0); noneg = (vp->v_type != VCHR); + /* + * Try to dodge locking for common case of querying the offset. + */ + if (whence == L_INCR && offset == 0) { + foffset = foffset_read(fp); + if (__predict_false(foffset < 0 && noneg)) { + return (EOVERFLOW); + } + td->td_uretoff.tdu_off = foffset; + return (0); + } + foffset = foffset_lock(fp, 0); error = 0; switch (whence) { case L_INCR: |