summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2020-09-15 22:13:21 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2020-09-15 22:13:21 +0000
commit4601f5f5ee10e6ea093c6c7289a7157ed527d9d8 (patch)
tree2a751a5186374a1bebf8de7e773fef7031b8d833
parent3c484f325e60e961c476dfb6ebd992290667d6dd (diff)
Notes
-rw-r--r--sys/fs/tmpfs/tmpfs.h3
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c35
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c2
3 files changed, 18 insertions, 22 deletions
diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h
index b15a83af7eba9..ac8fe0c1c2d66 100644
--- a/sys/fs/tmpfs/tmpfs.h
+++ b/sys/fs/tmpfs/tmpfs.h
@@ -228,7 +228,7 @@ struct tmpfs_node {
int tn_vpstate; /* (i) */
/* Transient refcounter on this node. */
- u_int tn_refcount; /* (m) + (i) */
+ u_int tn_refcount; /* 0<->1 (m) + (i) */
/* misc data field for different tn_type node */
union {
@@ -412,7 +412,6 @@ struct tmpfs_dir_cursor {
*/
void tmpfs_ref_node(struct tmpfs_node *node);
-void tmpfs_ref_node_locked(struct tmpfs_node *node);
int tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *, enum vtype,
uid_t uid, gid_t gid, mode_t mode, struct tmpfs_node *,
const char *, dev_t, struct tmpfs_node **);
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index 7d5d719001486..d9844bc3c7c9b 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/random.h>
+#include <sys/refcount.h>
#include <sys/rwlock.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
@@ -211,21 +212,15 @@ tmpfs_pages_check_avail(struct tmpfs_mount *tmp, size_t req_pages)
void
tmpfs_ref_node(struct tmpfs_node *node)
{
+#ifdef INVARIANTS
+ u_int old;
- TMPFS_NODE_LOCK(node);
- tmpfs_ref_node_locked(node);
- TMPFS_NODE_UNLOCK(node);
-}
-
-void
-tmpfs_ref_node_locked(struct tmpfs_node *node)
-{
-
- TMPFS_NODE_ASSERT_LOCKED(node);
- KASSERT(node->tn_refcount > 0, ("node %p zero refcount", node));
- KASSERT(node->tn_refcount < UINT_MAX, ("node %p refcount %u", node,
- node->tn_refcount));
- node->tn_refcount++;
+ old =
+#endif
+ refcount_acquire(&node->tn_refcount);
+#ifdef INVARIANTS
+ KASSERT(old > 0, ("node %p zero refcount", node));
+#endif
}
/*
@@ -370,6 +365,8 @@ tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *tmp, enum vtype type,
void
tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node)
{
+ if (refcount_release_if_not_last(&node->tn_refcount))
+ return;
TMPFS_LOCK(tmp);
TMPFS_NODE_LOCK(node);
@@ -384,19 +381,19 @@ tmpfs_free_node_locked(struct tmpfs_mount *tmp, struct tmpfs_node *node,
bool detach)
{
vm_object_t uobj;
+ bool last;
TMPFS_MP_ASSERT_LOCKED(tmp);
TMPFS_NODE_ASSERT_LOCKED(node);
- KASSERT(node->tn_refcount > 0, ("node %p refcount zero", node));
- node->tn_refcount--;
- if (node->tn_attached && (detach || node->tn_refcount == 0)) {
+ last = refcount_release(&node->tn_refcount);
+ if (node->tn_attached && (detach || last)) {
MPASS(tmp->tm_nodes_inuse > 0);
tmp->tm_nodes_inuse--;
LIST_REMOVE(node, tn_entries);
node->tn_attached = false;
}
- if (node->tn_refcount > 0)
+ if (!last)
return (false);
#ifdef INVARIANTS
@@ -596,7 +593,7 @@ tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, int lkflag,
error = 0;
tm = VFS_TO_TMPFS(mp);
TMPFS_NODE_LOCK(node);
- tmpfs_ref_node_locked(node);
+ tmpfs_ref_node(node);
loop:
TMPFS_NODE_ASSERT_LOCKED(node);
if ((vp = node->tn_vnode) != NULL) {
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 61dd148c73051..c5d0702801e95 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -1663,7 +1663,7 @@ restart:
if (tnp->tn_type != VDIR)
continue;
TMPFS_NODE_LOCK(tnp);
- tmpfs_ref_node_locked(tnp);
+ tmpfs_ref_node(tnp);
/*
* tn_vnode cannot be instantiated while we hold the