Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/fs/tmpfs PR kern/55268: tmpfs is slow
details: https://anonhg.NetBSD.org/src/rev/d6e91ce71ae0
branches: trunk
changeset: 932926:d6e91ce71ae0
user: ad <ad%NetBSD.org@localhost>
date: Sun May 17 19:39:15 2020 +0000
description:
PR kern/55268: tmpfs is slow
tmpfs_getpages(): handle the PGO_LOCKED case and implement lazy update of
atime/mtime.
diffstat:
sys/fs/tmpfs/tmpfs.h | 8 ++++-
sys/fs/tmpfs/tmpfs_subr.c | 54 ++++++++++++++++++++++++++++++++----
sys/fs/tmpfs/tmpfs_vnops.c | 68 +++++++++++++++++++++++++++++----------------
3 files changed, 97 insertions(+), 33 deletions(-)
diffs (truncated from 323 to 300 lines):
diff -r dd256004338c -r d6e91ce71ae0 sys/fs/tmpfs/tmpfs.h
--- a/sys/fs/tmpfs/tmpfs.h Sun May 17 19:38:16 2020 +0000
+++ b/sys/fs/tmpfs/tmpfs.h Sun May 17 19:39:15 2020 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: tmpfs.h,v 1.55 2018/04/19 21:50:09 christos Exp $ */
+/* $NetBSD: tmpfs.h,v 1.56 2020/05/17 19:39:15 ad Exp $ */
/*
- * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 2005, 2006, 2007, 2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -112,10 +112,12 @@
mode_t tn_mode;
int tn_flags;
nlink_t tn_links;
+ unsigned tn_tflags;
struct timespec tn_atime;
struct timespec tn_mtime;
struct timespec tn_ctime;
struct timespec tn_birthtime;
+ kmutex_t tn_timelock;
/* Head of byte-level lock list (used by tmpfs_advlock). */
struct lockf * tn_lockf;
@@ -274,6 +276,8 @@
const struct timespec *, const struct timespec *, int,
kauth_cred_t, lwp_t *);
void tmpfs_update(vnode_t *, unsigned);
+void tmpfs_update_locked(vnode_t *, unsigned);
+void tmpfs_update_lazily(vnode_t *, unsigned);
/*
* Prototypes for tmpfs_mem.c.
diff -r dd256004338c -r d6e91ce71ae0 sys/fs/tmpfs/tmpfs_subr.c
--- a/sys/fs/tmpfs/tmpfs_subr.c Sun May 17 19:38:16 2020 +0000
+++ b/sys/fs/tmpfs/tmpfs_subr.c Sun May 17 19:39:15 2020 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: tmpfs_subr.c,v 1.111 2020/05/16 18:31:49 christos Exp $ */
+/* $NetBSD: tmpfs_subr.c,v 1.112 2020/05/17 19:39:15 ad Exp $ */
/*
- * Copyright (c) 2005-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2005-2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.111 2020/05/16 18:31:49 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.112 2020/05/17 19:39:15 ad Exp $");
#include <sys/param.h>
#include <sys/cprng.h>
@@ -230,10 +230,12 @@
node->tn_flags = 0;
node->tn_lockf = NULL;
+ node->tn_tflags = 0;
vfs_timestamp(&node->tn_atime);
node->tn_birthtime = node->tn_atime;
node->tn_ctime = node->tn_atime;
node->tn_mtime = node->tn_atime;
+ mutex_init(&node->tn_timelock, MUTEX_DEFAULT, IPL_NONE);
if (dvp == NULL) {
KASSERT(vap->va_uid != VNOVAL && vap->va_gid != VNOVAL);
@@ -350,6 +352,7 @@
KASSERT(node->tn_vnode == NULL);
KASSERT(node->tn_links == 0);
+ mutex_destroy(&node->tn_timelock);
tmpfs_node_put(tmp, node);
}
@@ -1167,29 +1170,35 @@
if (error)
return error;
+ mutex_enter(&node->tn_timelock);
if (atime->tv_sec != VNOVAL) {
+ atomic_and_uint(&node->tn_tflags, ~TMPFS_UPDATE_ATIME);
node->tn_atime = *atime;
}
if (mtime->tv_sec != VNOVAL) {
+ atomic_and_uint(&node->tn_tflags, ~TMPFS_UPDATE_MTIME);
node->tn_mtime = *mtime;
}
if (btime->tv_sec != VNOVAL) {
node->tn_birthtime = *btime;
}
+ mutex_exit(&node->tn_timelock);
VN_KNOTE(vp, NOTE_ATTRIB);
return 0;
}
/*
- * tmpfs_update: update the timestamps as indicated by the flags.
+ * tmpfs_update_locked: update the timestamps as indicated by the flags.
*/
void
-tmpfs_update(vnode_t *vp, unsigned tflags)
+tmpfs_update_locked(vnode_t *vp, unsigned tflags)
{
tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
struct timespec nowtm;
- if (tflags == 0) {
+ KASSERT(mutex_owned(&node->tn_timelock));
+
+ if ((tflags |= atomic_swap_uint(&node->tn_tflags, 0)) == 0) {
return;
}
vfs_timestamp(&nowtm);
@@ -1204,3 +1213,36 @@
node->tn_ctime = nowtm;
}
}
+
+/*
+ * tmpfs_update: update the timestamps as indicated by the flags.
+ */
+void
+tmpfs_update(vnode_t *vp, unsigned tflags)
+{
+ tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
+
+ if ((tflags | atomic_load_relaxed(&node->tn_tflags)) == 0) {
+ return;
+ }
+
+ mutex_enter(&node->tn_timelock);
+ tmpfs_update_locked(vp, tflags);
+ mutex_exit(&node->tn_timelock);
+}
+
+/*
+ * tmpfs_update_lazily: schedule a deferred timestamp update.
+ */
+void
+tmpfs_update_lazily(vnode_t *vp, unsigned tflags)
+{
+ tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
+ unsigned cur;
+
+ cur = atomic_load_relaxed(&node->tn_tflags);
+ if ((cur & tflags) != tflags) {
+ atomic_or_uint(&node->tn_tflags, tflags);
+ return;
+ }
+}
diff -r dd256004338c -r d6e91ce71ae0 sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c Sun May 17 19:38:16 2020 +0000
+++ b/sys/fs/tmpfs/tmpfs_vnops.c Sun May 17 19:39:15 2020 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: tmpfs_vnops.c,v 1.138 2020/05/16 18:31:49 christos Exp $ */
+/* $NetBSD: tmpfs_vnops.c,v 1.139 2020/05/17 19:39:15 ad Exp $ */
/*
- * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 2005, 2006, 2007, 2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.138 2020/05/16 18:31:49 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.139 2020/05/17 19:39:15 ad Exp $");
#include <sys/param.h>
#include <sys/dirent.h>
@@ -438,10 +438,6 @@
vap->va_fileid = node->tn_id;
vap->va_size = node->tn_size;
vap->va_blocksize = PAGE_SIZE;
- vap->va_atime = node->tn_atime;
- vap->va_mtime = node->tn_mtime;
- vap->va_ctime = node->tn_ctime;
- vap->va_birthtime = node->tn_birthtime;
vap->va_gen = TMPFS_NODE_GEN(node);
vap->va_flags = node->tn_flags;
vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ?
@@ -451,6 +447,14 @@
vap->va_vaflags = 0;
vap->va_spare = VNOVAL; /* XXX */
+ mutex_enter(&node->tn_timelock);
+ tmpfs_update_locked(vp, 0);
+ vap->va_atime = node->tn_atime;
+ vap->va_mtime = node->tn_mtime;
+ vap->va_ctime = node->tn_ctime;
+ vap->va_birthtime = node->tn_birthtime;
+ mutex_exit(&node->tn_timelock);
+
return 0;
}
@@ -661,7 +665,7 @@
vnode_t *dvp = ap->a_dvp, *vp = ap->a_vp;
tmpfs_node_t *dnode, *node;
tmpfs_dirent_t *de;
- int error;
+ int error, tflags;
KASSERT(VOP_ISLOCKED(dvp));
KASSERT(VOP_ISLOCKED(vp));
@@ -710,11 +714,12 @@
else
tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de);
+ tflags = TMPFS_UPDATE_MTIME | TMPFS_UPDATE_CTIME;
if (node->tn_links > 0) {
/* We removed a hard link. */
- tmpfs_update(vp, TMPFS_UPDATE_CTIME);
+ tflags |= TMPFS_UPDATE_CTIME;
}
- tmpfs_update(dvp, TMPFS_UPDATE_MTIME | TMPFS_UPDATE_CTIME);
+ tmpfs_update(dvp, tflags);
error = 0;
out:
/* Drop the reference and unlock the node. */
@@ -1062,6 +1067,7 @@
}
*ap->a_recycle = true;
} else {
+ tmpfs_update(vp, 0);
*ap->a_recycle = false;
}
@@ -1170,7 +1176,7 @@
const vm_prot_t access_type = ap->a_access_type;
const int advice = ap->a_advice;
const int flags = ap->a_flags;
- int error, npages = *ap->a_count;
+ int error, iflag, npages = *ap->a_count;
tmpfs_node_t *node;
struct uvm_object *uobj;
@@ -1190,18 +1196,30 @@
npages = (round_page(vp->v_size) - offset) >> PAGE_SHIFT;
}
- if ((flags & PGO_LOCKED) != 0)
- return EBUSY;
-
- mutex_enter(vp->v_interlock);
- error = vdead_check(vp, VDEAD_NOWAIT);
- mutex_exit(vp->v_interlock);
- if (error != 0)
- return ENOENT;
+ /*
+ * Check for reclaimed vnode. v_interlock is not held here, but
+ * VI_DEADCHECK is set with vmobjlock held.
+ */
+ iflag = atomic_load_relaxed(&vp->v_iflag);
+ if (__predict_false((iflag & VI_DEADCHECK) != 0) {
+ mutex_enter(vp->v_interlock);
+ error = vdead_check(vp, VDEAD_NOWAIT);
+ mutex_exit(vp->v_interlock);
+ if (error) {
+ if ((flags & PGO_LOCKED) == 0)
+ rw_exit(vp->v_uobj.vmobjlock);
+ return error;
+ }
+ }
node = VP_TO_TMPFS_NODE(vp);
uobj = node->tn_spec.tn_reg.tn_aobj;
+ /*
+ * Update timestamp lazily. The update will be made real when
+ * a synchronous update is next made -- or by tmpfs_getattr,
+ * tmpfs_putpages, and tmpfs_inactive.
+ */
if ((flags & PGO_NOTIMESTAMP) == 0) {
u_int tflags = 0;
@@ -1213,7 +1231,7 @@
if (vp->v_mount->mnt_flag & MNT_RELATIME)
tflags |= TMPFS_UPDATE_ATIME;
}
- tmpfs_update(vp, tflags);
+ tmpfs_update_lazily(vp, tflags);
}
/*
@@ -1222,19 +1240,17 @@
* Clean the array of pages before. XXX: PR/32166
* Note that vnode lock is shared with underlying UVM object.
*/
- if (pgs) {
+ if ((flags & PGO_LOCKED) == 0 && pgs) {
memset(pgs, 0, sizeof(struct vm_pages *) * npages);
}
KASSERT(vp->v_uobj.vmobjlock == uobj->vmobjlock);
Home |
Main Index |
Thread Index |
Old Index