aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2023-11-19 22:23:20 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2023-11-19 22:25:45 +0000
commit305a2676ae93fb50a623024d51039415521cb2da (patch)
tree9ef87990264a865ddaa2dec739e525665e60fe9a
parent99c79cab422705f92f05a2924a29bdf823372ebf (diff)
downloadsrc-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.c27
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: