Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150796032
D23913.id73738.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D23913.id73738.diff
View Options
Index: sys/kern/vfs_cache.c
===================================================================
--- sys/kern/vfs_cache.c
+++ sys/kern/vfs_cache.c
@@ -56,11 +56,13 @@
#include <sys/proc.h>
#include <sys/rwlock.h>
#include <sys/sdt.h>
+#include <sys/smr.h>
#include <sys/smp.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
#include <sys/vnode.h>
+#include <ck_queue.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@@ -104,7 +106,7 @@
*/
struct namecache {
- LIST_ENTRY(namecache) nc_hash; /* hash chain */
+ CK_LIST_ENTRY(namecache) nc_hash;/* hash chain */
LIST_ENTRY(namecache) nc_src; /* source vnode list */
TAILQ_ENTRY(namecache) nc_dst; /* destination vnode list */
struct vnode *nc_dvp; /* vnode of parent of name */
@@ -143,6 +145,25 @@
#define NCF_DVDROP 0x10
#define NCF_NEGATIVE 0x20
#define NCF_HOTNEGATIVE 0x40
+#define NCF_INVALID 0x80
+
+static bool
+cache_ncp_invalid(struct namecache *ncp)
+{
+
+ atomic_thread_fence_acq();
+ return ((ncp->nc_flag & NCF_INVALID) != 0);
+}
+
+static void
+cache_ncp_invalidate(struct namecache *ncp)
+{
+
+ atomic_thread_fence_rel();
+ KASSERT((ncp->nc_flag & NCF_INVALID) == 0,
+ ("%s: entry %p already invalid", __func__, ncp));
+ ncp->nc_flag |= NCF_INVALID;
+}
/*
* Name caching works as follows:
@@ -192,12 +213,14 @@
* the first node, locking everything in order and revalidating the state.
*/
+VFS_SMR_DECLARE;
+
/*
* Structures associated with name caching.
*/
#define NCHHASH(hash) \
(&nchashtbl[(hash) & nchash])
-static __read_mostly LIST_HEAD(nchashhead, namecache) *nchashtbl;/* Hash Table */
+static __read_mostly CK_LIST_HEAD(nchashhead, namecache) *nchashtbl;/* Hash Table */
static u_long __read_mostly nchash; /* size of hash table */
SYSCTL_ULONG(_debug, OID_AUTO, nchash, CTLFLAG_RD, &nchash, 0,
"Size of namecache hash table");
@@ -275,15 +298,15 @@
if (__predict_false(ts)) {
if (len <= CACHE_PATH_CUTOFF)
- ncp_ts = uma_zalloc(cache_zone_small_ts, M_WAITOK);
+ ncp_ts = uma_zalloc_smr(cache_zone_small_ts, M_WAITOK);
else
- ncp_ts = uma_zalloc(cache_zone_large_ts, M_WAITOK);
+ ncp_ts = uma_zalloc_smr(cache_zone_large_ts, M_WAITOK);
ncp = &ncp_ts->nc_nc;
} else {
if (len <= CACHE_PATH_CUTOFF)
- ncp = uma_zalloc(cache_zone_small, M_WAITOK);
+ ncp = uma_zalloc_smr(cache_zone_small, M_WAITOK);
else
- ncp = uma_zalloc(cache_zone_large, M_WAITOK);
+ ncp = uma_zalloc_smr(cache_zone_large, M_WAITOK);
}
return (ncp);
}
@@ -300,14 +323,14 @@
if (__predict_false(ncp->nc_flag & NCF_TS)) {
ncp_ts = __containerof(ncp, struct namecache_ts, nc_nc);
if (ncp->nc_nlen <= CACHE_PATH_CUTOFF)
- uma_zfree(cache_zone_small_ts, ncp_ts);
+ uma_zfree_smr(cache_zone_small_ts, ncp_ts);
else
- uma_zfree(cache_zone_large_ts, ncp_ts);
+ uma_zfree_smr(cache_zone_large_ts, ncp_ts);
} else {
if (ncp->nc_nlen <= CACHE_PATH_CUTOFF)
- uma_zfree(cache_zone_small, ncp);
+ uma_zfree_smr(cache_zone_small, ncp);
else
- uma_zfree(cache_zone_large, ncp);
+ uma_zfree_smr(cache_zone_large, ncp);
}
}
@@ -336,6 +359,9 @@
"VFS namecache enabled");
#endif
+static bool __read_mostly cache_try_smr = true;
+SYSCTL_BOOL(_debug, OID_AUTO, cache_try_smr, CTLFLAG_RW, &cache_try_smr, 0, "");
+
/* Export size information to userland */
SYSCTL_INT(_debug_sizeof, OID_AUTO, namecache, CTLFLAG_RD, SYSCTL_NULL_INT_PTR,
sizeof(struct namecache), "sizeof(struct namecache)");
@@ -606,7 +632,7 @@
}
/* Scan hash tables counting entries */
for (ncpp = nchashtbl, i = 0; i < n_nchash; ncpp++, i++)
- LIST_FOREACH(ncp, ncpp, nc_hash)
+ CK_LIST_FOREACH(ncp, ncpp, nc_hash)
cntbuf[i]++;
cache_unlock_all_buckets();
for (error = 0, i = 0; i < n_nchash; i++)
@@ -639,7 +665,7 @@
/* Scan hash tables for applicable entries */
for (ncpp = nchashtbl; n_nchash > 0; n_nchash--, ncpp++) {
count = 0;
- LIST_FOREACH(ncp, ncpp, nc_hash) {
+ CK_LIST_FOREACH(ncp, ncpp, nc_hash) {
count++;
}
if (count)
@@ -860,7 +886,10 @@
CTR2(KTR_VFS, "cache_zap(%p) vp %p", ncp,
(ncp->nc_flag & NCF_NEGATIVE) ? NULL : ncp->nc_vp);
- LIST_REMOVE(ncp, nc_hash);
+
+ cache_ncp_invalidate(ncp);
+
+ CK_LIST_REMOVE(ncp, nc_hash);
if (!(ncp->nc_flag & NCF_NEGATIVE)) {
SDT_PROBE3(vfs, namecache, zap, done, ncp->nc_dvp,
ncp->nc_name, ncp->nc_vp);
@@ -1013,7 +1042,7 @@
cache_sort_vnodes(&dvlp, &vlp);
cache_lock_vnodes(dvlp, vlp);
rw_wlock(blp);
- LIST_FOREACH(rncp, (NCHHASH(hash)), nc_hash) {
+ CK_LIST_FOREACH(rncp, (NCHHASH(hash)), nc_hash) {
if (rncp == ncp && rncp->nc_dvp == dvp &&
rncp->nc_nlen == cnp->cn_namelen &&
!bcmp(rncp->nc_name, cnp->cn_nameptr, rncp->nc_nlen))
@@ -1225,12 +1254,12 @@
hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp);
blp = HASH2BUCKETLOCK(hash);
retry:
- if (LIST_EMPTY(NCHHASH(hash)))
+ if (CK_LIST_EMPTY(NCHHASH(hash)))
goto out_no_entry;
rw_wlock(blp);
- LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
+ CK_LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
counter_u64_add(numchecks, 1);
if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen &&
!bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen))
@@ -1305,6 +1334,7 @@
uint32_t hash;
enum vgetstate vs;
int error, ltype;
+ bool try_smr, doing_smr;
#ifdef DEBUG_CACHE
if (__predict_false(!doingcache)) {
@@ -1321,7 +1351,11 @@
if ((cnp->cn_flags & MAKEENTRY) == 0)
return (cache_lookup_nomakeentry(dvp, vpp, cnp, tsp, ticksp));
+ try_smr = atomic_load_char(&cache_try_smr);
+ if (cnp->cn_nameiop == CREATE)
+ try_smr = false;
retry:
+ doing_smr = false;
blp = NULL;
dvlp = NULL;
error = 0;
@@ -1361,10 +1395,17 @@
}
hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp);
- blp = HASH2BUCKETLOCK(hash);
- rw_rlock(blp);
+retry_hashed:
+ if (try_smr) {
+ vfs_smr_enter();
+ doing_smr = true;
+ try_smr = false;
+ } else {
+ blp = HASH2BUCKETLOCK(hash);
+ rw_rlock(blp);
+ }
- LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
+ CK_LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
counter_u64_add(numchecks, 1);
if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen &&
!bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen))
@@ -1373,7 +1414,10 @@
/* We failed to find an entry */
if (__predict_false(ncp == NULL)) {
- rw_runlock(blp);
+ if (doing_smr)
+ vfs_smr_exit();
+ else
+ rw_runlock(blp);
SDT_PROBE3(vfs, namecache, lookup, miss, dvp, cnp->cn_nameptr,
NULL);
counter_u64_add(nummiss, 1);
@@ -1402,8 +1446,22 @@
ltype = VOP_ISLOCKED(dvp);
VOP_UNLOCK(dvp);
}
- vs = vget_prep(*vpp);
- cache_lookup_unlock(blp, dvlp);
+ if (doing_smr) {
+ if (cache_ncp_invalid(ncp)) {
+ vfs_smr_exit();
+ *vpp = NULL;
+ goto retry;
+ }
+ vs = vget_prep_smr(*vpp);
+ vfs_smr_exit();
+ if (vs == VGET_NONE) {
+ *vpp = NULL;
+ goto retry;
+ }
+ } else {
+ vs = vget_prep(*vpp);
+ cache_lookup_unlock(blp, dvlp);
+ }
error = vget_finish(*vpp, cnp->cn_lkflags, vs);
if (cnp->cn_flags & ISDOTDOT) {
vn_lock(dvp, ltype | LK_RETRY);
@@ -1427,21 +1485,37 @@
negative_success:
/* We found a negative match, and want to create it, so purge */
if (cnp->cn_nameiop == CREATE) {
+ MPASS(!doing_smr);
counter_u64_add(numnegzaps, 1);
goto zap_and_exit;
}
+ if (doing_smr) {
+ if ((ncp->nc_flag & NCF_HOTNEGATIVE) == 0) {
+ /*
+ * We need to take locks to promote the entry.
+ */
+ vfs_smr_exit();
+ doing_smr = false;
+ goto retry_hashed;
+ }
+ } else {
+ cache_negative_hit(ncp);
+ }
counter_u64_add(numneghits, 1);
- cache_negative_hit(ncp);
if (ncp->nc_flag & NCF_WHITE)
cnp->cn_flags |= ISWHITEOUT;
SDT_PROBE2(vfs, namecache, lookup, hit__negative, dvp,
ncp->nc_name);
cache_out_ts(ncp, tsp, ticksp);
- cache_lookup_unlock(blp, dvlp);
+ if (doing_smr)
+ vfs_smr_exit();
+ else
+ cache_lookup_unlock(blp, dvlp);
return (ENOENT);
zap_and_exit:
+ MPASS(!doing_smr);
if (blp != NULL)
error = cache_zap_rlocked_bucket(ncp, cnp, hash, blp);
else
@@ -1775,7 +1849,7 @@
* the same path name.
*/
ncpp = NCHHASH(hash);
- LIST_FOREACH(n2, ncpp, nc_hash) {
+ CK_LIST_FOREACH(n2, ncpp, nc_hash) {
if (n2->nc_dvp == dvp &&
n2->nc_nlen == cnp->cn_namelen &&
!bcmp(n2->nc_name, cnp->cn_nameptr, n2->nc_nlen)) {
@@ -1839,12 +1913,6 @@
LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src);
}
- /*
- * Insert the new namecache entry into the appropriate chain
- * within the cache entries table.
- */
- LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
-
/*
* If the entry is "negative", we place it into the
* "negative" cache queue, otherwise, we place it into the
@@ -1861,6 +1929,14 @@
SDT_PROBE2(vfs, namecache, enter_negative, done, dvp,
ncp->nc_name);
}
+
+ atomic_thread_fence_rel();
+ /*
+ * Insert the new namecache entry into the appropriate chain
+ * within the cache entries table.
+ */
+ CK_LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
+
cache_enter_unlock(&cel);
if (numneg * ncnegfactor > lnumcache)
cache_negative_zap_one();
@@ -1908,6 +1984,11 @@
NULL, NULL, NULL, NULL, UMA_ALIGNOF(struct namecache_ts),
UMA_ZONE_ZINIT);
+ VFS_SMR_ZONE_SET(cache_zone_small);
+ VFS_SMR_ZONE_SET(cache_zone_small_ts);
+ VFS_SMR_ZONE_SET(cache_zone_large);
+ VFS_SMR_ZONE_SET(cache_zone_large_ts);
+
ncsize = desiredvnodes * ncsizefactor;
nchashtbl = hashinit(desiredvnodes * 2, M_VFSCACHE, &nchash);
ncbuckethash = cache_roundup_2(mp_ncpus * mp_ncpus) - 1;
@@ -1973,11 +2054,11 @@
nchashtbl = new_nchashtbl;
nchash = new_nchash;
for (i = 0; i <= old_nchash; i++) {
- while ((ncp = LIST_FIRST(&old_nchashtbl[i])) != NULL) {
+ while ((ncp = CK_LIST_FIRST(&old_nchashtbl[i])) != NULL) {
hash = cache_get_hash(ncp->nc_name, ncp->nc_nlen,
ncp->nc_dvp);
- LIST_REMOVE(ncp, nc_hash);
- LIST_INSERT_HEAD(NCHHASH(hash), ncp, nc_hash);
+ CK_LIST_REMOVE(ncp, nc_hash);
+ CK_LIST_INSERT_HEAD(NCHHASH(hash), ncp, nc_hash);
}
}
ncsize = newncsize;
@@ -2091,7 +2172,7 @@
for (j = i; j < n_nchash; j += numbucketlocks) {
retry:
bucket = &nchashtbl[j];
- LIST_FOREACH_SAFE(ncp, bucket, nc_hash, nnp) {
+ CK_LIST_FOREACH_SAFE(ncp, bucket, nc_hash, nnp) {
cache_assert_bucket_locked(ncp, RA_WLOCKED);
if (ncp->nc_dvp->v_mount != mp)
continue;
Index: sys/kern/vfs_subr.c
===================================================================
--- sys/kern/vfs_subr.c
+++ sys/kern/vfs_subr.c
@@ -76,6 +76,7 @@
#include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/sleepqueue.h>
+#include <sys/smr.h>
#include <sys/smp.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
@@ -238,6 +239,8 @@
static uma_zone_t vnode_zone;
static uma_zone_t vnodepoll_zone;
+__read_frequently smr_t vfs_smr;
+
/*
* The workitem queue.
*
@@ -661,7 +664,8 @@
vnode_list_reclaim_marker = vn_alloc_marker(NULL);
TAILQ_INSERT_HEAD(&vnode_list, vnode_list_reclaim_marker, v_vnodelist);
vnode_zone = uma_zcreate("VNODE", sizeof (struct vnode), NULL, NULL,
- vnode_init, vnode_fini, UMA_ALIGN_PTR, 0);
+ vnode_init, vnode_fini, UMA_ALIGN_PTR, UMA_ZONE_SMR);
+ vfs_smr = uma_zone_get_smr(vnode_zone);
vnodepoll_zone = uma_zcreate("VNODEPOLL", sizeof (struct vpollinfo),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
/*
@@ -1603,7 +1607,7 @@
if (vnlru_under(rnumvnodes, vlowat))
vnlru_kick();
mtx_unlock(&vnode_list_mtx);
- return (uma_zalloc(vnode_zone, M_WAITOK));
+ return (uma_zalloc_smr(vnode_zone, M_WAITOK));
}
static struct vnode *
@@ -1619,7 +1623,7 @@
return (vn_alloc_hard(mp));
}
- return (uma_zalloc(vnode_zone, M_WAITOK));
+ return (uma_zalloc_smr(vnode_zone, M_WAITOK));
}
static void
@@ -1627,7 +1631,7 @@
{
atomic_subtract_long(&numvnodes, 1);
- uma_zfree(vnode_zone, vp);
+ uma_zfree_smr(vnode_zone, vp);
}
/*
@@ -1758,7 +1762,7 @@
CTR2(KTR_VFS, "%s: destroying the vnode %p", __func__, vp);
bo = &vp->v_bufobj;
VNASSERT(vp->v_data == NULL, vp, ("cleaned vnode isn't"));
- VNASSERT(vp->v_holdcnt == 0, vp, ("Non-zero hold count"));
+ VNPASS(vp->v_holdcnt == VHOLD_NO_SMR, vp);
VNASSERT(vp->v_usecount == 0, vp, ("Non-zero use count"));
VNASSERT(vp->v_writecount == 0, vp, ("Non-zero write count"));
VNASSERT(bo->bo_numoutput == 0, vp, ("Clean vnode has pending I/O's"));
@@ -2848,7 +2852,29 @@
*
* holdcnt can be manipulated using atomics without holding any locks,
* except when transitioning 1<->0, in which case the interlock is held.
+ *
+ * Consumers which don't guarantee liveness of the vnode can use SMR to
+ * try to get a reference. Note this operation can fail since the vnode
+ * may be awaiting getting freed by the time they get to it.
*/
+enum vgetstate
+vget_prep_smr(struct vnode *vp)
+{
+ enum vgetstate vs;
+
+ VFS_SMR_ASSERT_ENTERED();
+
+ if (refcount_acquire_if_not_zero(&vp->v_usecount)) {
+ vs = VGET_USECOUNT;
+ } else {
+ if (vhold_smr(vp))
+ vs = VGET_HOLDCNT;
+ else
+ vs = VGET_NONE;
+ }
+ return (vs);
+}
+
enum vgetstate
vget_prep(struct vnode *vp)
{
@@ -2919,6 +2945,7 @@
ASSERT_VI_LOCKED(vp, __func__);
else
ASSERT_VI_UNLOCKED(vp, __func__);
+ VNPASS(vs == VGET_HOLDCNT || vs == VGET_USECOUNT, vp);
VNPASS(vp->v_holdcnt > 0, vp);
VNPASS(vs == VGET_HOLDCNT || vp->v_usecount > 0, vp);
@@ -3380,7 +3407,8 @@
CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
old = atomic_fetchadd_int(&vp->v_holdcnt, 1);
- VNASSERT(old >= 0, vp, ("%s: wrong hold count %d", __func__, old));
+ VNASSERT(old >= 0 && (old & VHOLD_ALL_FLAGS) == 0, vp,
+ ("%s: wrong hold count %d", __func__, old));
if (old != 0)
return;
critical_enter();
@@ -3405,12 +3433,40 @@
CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
#ifdef INVARIANTS
int old = atomic_fetchadd_int(&vp->v_holdcnt, 1);
- VNASSERT(old > 0, vp, ("%s: wrong hold count %d", __func__, old));
+ VNASSERT(old > 0 && (old & VHOLD_ALL_FLAGS) == 0, vp,
+ ("%s: wrong hold count %d", __func__, old));
#else
atomic_add_int(&vp->v_holdcnt, 1);
#endif
}
+/*
+ * Grab a hold count as long as the vnode is not getting freed.
+ *
+ * Only use this routine if vfs smr is the only protection you have against
+ * freeing the vnode.
+ */
+bool
+vhold_smr(struct vnode *vp)
+{
+ int count;
+
+ VFS_SMR_ASSERT_ENTERED();
+
+ count = atomic_load_int(&vp->v_holdcnt);
+ for (;;) {
+ if (count & VHOLD_NO_SMR) {
+ VNASSERT((count & ~VHOLD_NO_SMR) == 0, vp,
+ ("non-zero hold count with flags %d\n", count));
+ return (false);
+ }
+
+ VNASSERT(count >= 0, vp, ("invalid hold count %d\n", count));
+ if (atomic_fcmpset_int(&vp->v_holdcnt, &count, count + 1))
+ return (true);
+ }
+}
+
static void __noinline
vdbatch_process(struct vdbatch *vd)
{
@@ -3581,11 +3637,25 @@
VI_UNLOCK(vp);
return;
}
- if (VN_IS_DOOMED(vp)) {
- freevnode(vp);
+ if (!VN_IS_DOOMED(vp)) {
+ vdrop_deactivate(vp);
+ return;
+ }
+ /*
+ * We may be racing against vhold_smr.
+ *
+ * If they win we can just pretend we never got this far, they will
+ * vdrop later.
+ */
+ if (!atomic_cmpset_int(&vp->v_holdcnt, 0, VHOLD_NO_SMR)) {
+ /*
+ * We lost the aforementioned race. Note that any subsequent
+ * access is invalid as they might have managed to vdropl on
+ * their own.
+ */
return;
}
- vdrop_deactivate(vp);
+ freevnode(vp);
}
/*
@@ -4041,20 +4111,25 @@
{"VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD",
"VMARKER"};
+_Static_assert((VHOLD_ALL_FLAGS & ~VHOLD_NO_SMR) == 0,
+ "new hold count flag not added to vn_printf");
+
void
vn_printf(struct vnode *vp, const char *fmt, ...)
{
va_list ap;
char buf[256], buf2[16];
u_long flags;
+ u_int holdcnt;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("%p: ", (void *)vp);
printf("type %s\n", typename[vp->v_type]);
+ holdcnt = atomic_load_int(&vp->v_holdcnt);
printf(" usecount %d, writecount %d, refcount %d",
- vp->v_usecount, vp->v_writecount, vp->v_holdcnt);
+ vp->v_usecount, vp->v_writecount, holdcnt & ~VHOLD_ALL_FLAGS);
switch (vp->v_type) {
case VDIR:
printf(" mountedhere %p\n", vp->v_mountedhere);
@@ -4072,6 +4147,12 @@
printf("\n");
break;
}
+ buf[0] = '\0';
+ buf[1] = '\0';
+ if (holdcnt & VHOLD_NO_SMR)
+ strlcat(buf, "|VHOLD_NO_SMR", sizeof(buf));
+ printf(" hold count flags (%s)\n", buf + 1);
+
buf[0] = '\0';
buf[1] = '\0';
if (vp->v_irflag & VIRF_DOOMED)
Index: sys/sys/vnode.h
===================================================================
--- sys/sys/vnode.h
+++ sys/sys/vnode.h
@@ -58,7 +58,7 @@
enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD,
VMARKER };
-enum vgetstate { VGET_HOLDCNT, VGET_USECOUNT };
+enum vgetstate { VGET_NONE, VGET_HOLDCNT, VGET_USECOUNT };
/*
* Each underlying filesystem allocates its own private area and hangs
* it from v_data. If non-null, this area is freed in getnewvnode().
@@ -236,6 +236,9 @@
* VIRF_DOOMED is doubly protected by the interlock and vnode lock. Both
* are required for writing but the status may be checked with either.
*/
+#define VHOLD_NO_SMR (1<<29) /* Disable vhold_smr */
+#define VHOLD_ALL_FLAGS (VHOLD_NO_SMR)
+
#define VIRF_DOOMED 0x0001 /* This vnode is being recycled */
#define VI_TEXT_REF 0x0001 /* Text ref grabbed use ref */
@@ -657,12 +660,14 @@
void vdropl(struct vnode *);
int vflush(struct mount *mp, int rootrefs, int flags, struct thread *td);
int vget(struct vnode *vp, int flags, struct thread *td);
+enum vgetstate vget_prep_smr(struct vnode *vp);
enum vgetstate vget_prep(struct vnode *vp);
int vget_finish(struct vnode *vp, int flags, enum vgetstate vs);
void vgone(struct vnode *vp);
void vhold(struct vnode *);
void vholdl(struct vnode *);
void vholdnz(struct vnode *);
+bool vhold_smr(struct vnode *);
void vinactive(struct vnode *vp);
int vinvalbuf(struct vnode *vp, int save, int slpflag, int slptimeo);
int vtruncbuf(struct vnode *vp, off_t length, int blksize);
@@ -974,6 +979,16 @@
SYSINIT(vfs_vector_##vnodeops##_f, SI_SUB_VFS, SI_ORDER_ANY, \
vfs_vector_op_register, &vnodeops)
+#define VFS_SMR_DECLARE \
+ extern smr_t vfs_smr
+
+#define VFS_SMR() vfs_smr
+#define vfs_smr_enter() smr_enter(VFS_SMR())
+#define vfs_smr_exit() smr_exit(VFS_SMR())
+#define VFS_SMR_ASSERT_ENTERED() SMR_ASSERT_ENTERED(VFS_SMR())
+#define VFS_SMR_ASSERT_NOT_ENTERED() SMR_ASSERT_NOT_ENTERED(VFS_SMR())
+#define VFS_SMR_ZONE_SET(zone) uma_zone_set_smr((zone), VFS_SMR())
+
#endif /* _KERNEL */
#endif /* !_SYS_VNODE_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 5, 2:55 AM (13 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30864090
Default Alt Text
D23913.id73738.diff (18 KB)
Attached To
Mode
D23913: vfs: introduce basic smr-protected path lookup
Attached
Detach File
Event Timeline
Log In to Comment