Merge from ad-namecache:
- Have a stab at clustering the members of vnode_t and vnode_impl_t in a more cache-conscious way. With that done, go back to adjusting v_usecount with atomics and keep vi_lock directly in vnode_impl_t (saves KVA). - Allow VOP_LOCK(LK_NONE) for the benefit of VFS_VGET() and VFS_ROOT(). Make sure LK_UPGRADE always comes with LK_NOWAIT. - Make cwdinfo use mostly lockless.
This commit is contained in:
parent
97e9007d62
commit
926b25e154
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: netbsd32_fs.c,v 1.86 2020/01/31 09:01:23 maxv Exp $ */
|
||||
/* $NetBSD: netbsd32_fs.c,v 1.87 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Matthew R. Green
|
||||
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.86 2020/01/31 09:01:23 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.87 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -740,13 +740,12 @@ netbsd32___getcwd(struct lwp *l, const struct netbsd32___getcwd_args *uap, regis
|
||||
syscallarg(char *) bufp;
|
||||
syscallarg(size_t) length;
|
||||
} */
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
char *path;
|
||||
char *bp, *bend;
|
||||
int len = (int)SCARG(uap, length);
|
||||
int lenused;
|
||||
struct cwdinfo *cwdi;
|
||||
struct vnode *dvp;
|
||||
|
||||
if (len > MAXPATHLEN*4)
|
||||
len = MAXPATHLEN*4;
|
||||
@ -764,11 +763,10 @@ netbsd32___getcwd(struct lwp *l, const struct netbsd32___getcwd_args *uap, regis
|
||||
* limit it to N/2 vnodes for an N byte buffer.
|
||||
*/
|
||||
#define GETCWD_CHECK_ACCESS 0x0001
|
||||
cwdi = p->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
error = getcwd_common (cwdi->cwdi_cdir, NULL, &bp, path, len/2,
|
||||
dvp = cwdcdir();
|
||||
error = getcwd_common (dvp, NULL, &bp, path, len/2,
|
||||
GETCWD_CHECK_ACCESS, l);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
vrele(dvp);
|
||||
|
||||
if (error)
|
||||
goto out;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: kern_exec.c,v 1.492 2020/02/15 17:13:55 ad Exp $ */
|
||||
/* $NetBSD: kern_exec.c,v 1.493 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008, 2019 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.492 2020/02/15 17:13:55 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.493 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#include "opt_exec.h"
|
||||
#include "opt_execfmt.h"
|
||||
@ -672,7 +672,7 @@ exec_makepathbuf(struct lwp *l, const char *upath, enum uio_seg seg,
|
||||
char *path, *bp;
|
||||
size_t len, tlen;
|
||||
int error;
|
||||
struct cwdinfo *cwdi;
|
||||
struct vnode *dvp;
|
||||
|
||||
path = PNBUF_GET();
|
||||
if (seg == UIO_SYSSPACE) {
|
||||
@ -698,11 +698,10 @@ exec_makepathbuf(struct lwp *l, const char *upath, enum uio_seg seg,
|
||||
memmove(bp, path, len);
|
||||
*(--bp) = '/';
|
||||
|
||||
cwdi = l->l_proc->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
error = getcwd_common(cwdi->cwdi_cdir, NULL, &bp, path, MAXPATHLEN / 2,
|
||||
dvp = cwdcdir();
|
||||
error = getcwd_common(dvp, NULL, &bp, path, MAXPATHLEN / 2,
|
||||
GETCWD_CHECK_ACCESS, l);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
vrele(dvp);
|
||||
|
||||
if (error)
|
||||
goto err;
|
||||
@ -1119,6 +1118,7 @@ static void
|
||||
emulexec(struct lwp *l, struct exec_package *epp)
|
||||
{
|
||||
struct proc *p = l->l_proc;
|
||||
struct cwdinfo *cwdi;
|
||||
|
||||
/* The emulation root will usually have been found when we looked
|
||||
* for the elf interpreter (or similar), if not look now. */
|
||||
@ -1127,9 +1127,10 @@ emulexec(struct lwp *l, struct exec_package *epp)
|
||||
emul_find_root(l, epp);
|
||||
|
||||
/* Any old emulation root got removed by fdcloseexec */
|
||||
rw_enter(&p->p_cwdi->cwdi_lock, RW_WRITER);
|
||||
p->p_cwdi->cwdi_edir = epp->ep_emul_root;
|
||||
rw_exit(&p->p_cwdi->cwdi_lock);
|
||||
KASSERT(p == curproc);
|
||||
cwdi = cwdenter(RW_WRITER);
|
||||
cwdi->cwdi_edir = epp->ep_emul_root;
|
||||
cwdexit(cwdi);
|
||||
epp->ep_emul_root = NULL;
|
||||
if (epp->ep_interp != NULL)
|
||||
vrele(epp->ep_interp);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: kern_proc.c,v 1.241 2020/02/21 00:26:22 joerg Exp $ */
|
||||
/* $NetBSD: kern_proc.c,v 1.242 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1999, 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.241 2020/02/21 00:26:22 joerg Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.242 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_kstack.h"
|
||||
@ -106,6 +106,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.241 2020/02/21 00:26:22 joerg Exp $"
|
||||
#include <sys/exec.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/compat_stub.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
#include <uvm/uvm.h>
|
||||
@ -476,7 +477,7 @@ proc0_init(void)
|
||||
p->p_cred = cred0;
|
||||
|
||||
/* Create the CWD info. */
|
||||
rw_init(&cwdi0.cwdi_lock);
|
||||
mutex_init(&cwdi0.cwdi_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
/* Create the limits structures. */
|
||||
mutex_init(&limit0.pl_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
@ -2594,7 +2595,7 @@ fill_cwd(struct lwp *l, pid_t pid, void *oldp, size_t *oldlenp)
|
||||
struct proc *p;
|
||||
char *path;
|
||||
char *bp, *bend;
|
||||
struct cwdinfo *cwdi;
|
||||
const struct cwdinfo *cwdi;
|
||||
struct vnode *vp;
|
||||
size_t len, lenused;
|
||||
|
||||
@ -2609,11 +2610,12 @@ fill_cwd(struct lwp *l, pid_t pid, void *oldp, size_t *oldlenp)
|
||||
bend = bp;
|
||||
*(--bp) = '\0';
|
||||
|
||||
cwdi = p->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
cwdi = cwdlock(p);
|
||||
vp = cwdi->cwdi_cdir;
|
||||
vref(vp);
|
||||
cwdunlock(p);
|
||||
error = getcwd_common(vp, NULL, &bp, path, len/2, 0, l);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
vrele(vp);
|
||||
|
||||
if (error)
|
||||
goto out;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: uipc_usrreq.c,v 1.196 2020/02/01 02:23:23 riastradh Exp $ */
|
||||
/* $NetBSD: uipc_usrreq.c,v 1.197 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000, 2004, 2008, 2009 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1998, 2000, 2004, 2008, 2009, 2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -96,7 +96,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.196 2020/02/01 02:23:23 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.197 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_compat_netbsd.h"
|
||||
@ -1395,6 +1395,7 @@ unp_externalize(struct mbuf *rights, struct lwp *l, int flags)
|
||||
{
|
||||
struct cmsghdr * const cm = mtod(rights, struct cmsghdr *);
|
||||
struct proc * const p = l->l_proc;
|
||||
struct vnode *rvp = NULL;
|
||||
file_t **rp;
|
||||
int error = 0;
|
||||
|
||||
@ -1404,9 +1405,11 @@ unp_externalize(struct mbuf *rights, struct lwp *l, int flags)
|
||||
goto noop;
|
||||
|
||||
int * const fdp = kmem_alloc(nfds * sizeof(int), KM_SLEEP);
|
||||
rw_enter(&p->p_cwdi->cwdi_lock, RW_READER);
|
||||
|
||||
KASSERT(l == curlwp);
|
||||
|
||||
/* Make sure the recipient should be able to see the files.. */
|
||||
rvp = cwdrdir();
|
||||
rp = (file_t **)CMSG_DATA(cm);
|
||||
for (size_t i = 0; i < nfds; i++) {
|
||||
file_t * const fp = *rp++;
|
||||
@ -1420,16 +1423,15 @@ unp_externalize(struct mbuf *rights, struct lwp *l, int flags)
|
||||
* sure it's inside the subtree we're allowed
|
||||
* to access.
|
||||
*/
|
||||
if (p->p_cwdi->cwdi_rdir != NULL && fp->f_type == DTYPE_VNODE) {
|
||||
if (rvp != NULL && fp->f_type == DTYPE_VNODE) {
|
||||
vnode_t *vp = fp->f_vnode;
|
||||
if ((vp->v_type == VDIR) &&
|
||||
!vn_isunder(vp, p->p_cwdi->cwdi_rdir, l)) {
|
||||
if ((vp->v_type == VDIR) && !vn_isunder(vp, rvp, l)) {
|
||||
error = EPERM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
restart:
|
||||
/*
|
||||
* First loop -- allocate file descriptor table slots for the
|
||||
@ -1506,7 +1508,6 @@ unp_externalize(struct mbuf *rights, struct lwp *l, int flags)
|
||||
cm->cmsg_len = CMSG_LEN(0);
|
||||
rights->m_len = CMSG_SPACE(0);
|
||||
}
|
||||
rw_exit(&p->p_cwdi->cwdi_lock);
|
||||
kmem_free(fdp, nfds * sizeof(int));
|
||||
|
||||
noop:
|
||||
@ -1516,6 +1517,10 @@ unp_externalize(struct mbuf *rights, struct lwp *l, int flags)
|
||||
KASSERT(cm->cmsg_len <= rights->m_len);
|
||||
memset(&mtod(rights, char *)[cm->cmsg_len], 0, rights->m_len -
|
||||
cm->cmsg_len);
|
||||
|
||||
/* Async release since in the networking code. */
|
||||
if (rvp != NULL)
|
||||
vrele_async(rvp);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: vfs_cwd.c,v 1.4 2011/02/15 15:54:28 pooka Exp $ */
|
||||
/* $NetBSD: vfs_cwd.c,v 1.5 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -31,13 +31,14 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_cwd.c,v 1.4 2011/02/15 15:54:28 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_cwd.c,v 1.5 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/atomic.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/xcall.h>
|
||||
|
||||
static int cwdi_ctor(void *, void *, int);
|
||||
static void cwdi_dtor(void *, void *);
|
||||
@ -64,9 +65,8 @@ cwdinit(void)
|
||||
struct cwdinfo *copy;
|
||||
|
||||
cwdi = pool_cache_get(cwdi_cache, PR_WAITOK);
|
||||
copy = curproc->p_cwdi;
|
||||
|
||||
rw_enter(©->cwdi_lock, RW_READER);
|
||||
copy = cwdenter(RW_READER);
|
||||
cwdi->cwdi_cdir = copy->cwdi_cdir;
|
||||
if (cwdi->cwdi_cdir)
|
||||
vref(cwdi->cwdi_cdir);
|
||||
@ -78,7 +78,7 @@ cwdinit(void)
|
||||
vref(cwdi->cwdi_edir);
|
||||
cwdi->cwdi_cmask = copy->cwdi_cmask;
|
||||
cwdi->cwdi_refcnt = 1;
|
||||
rw_exit(©->cwdi_lock);
|
||||
cwdexit(copy);
|
||||
|
||||
return (cwdi);
|
||||
}
|
||||
@ -88,7 +88,7 @@ cwdi_ctor(void *arg, void *obj, int flags)
|
||||
{
|
||||
struct cwdinfo *cwdi = obj;
|
||||
|
||||
rw_init(&cwdi->cwdi_lock);
|
||||
mutex_init(&cwdi->cwdi_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -98,7 +98,7 @@ cwdi_dtor(void *arg, void *obj)
|
||||
{
|
||||
struct cwdinfo *cwdi = obj;
|
||||
|
||||
rw_destroy(&cwdi->cwdi_lock);
|
||||
mutex_destroy(&cwdi->cwdi_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -159,3 +159,120 @@ cwdexec(struct proc *p)
|
||||
vrele(p->p_cwdi->cwdi_edir);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used when curlwp wants to use or update its cwdinfo, and needs to prevent
|
||||
* concurrent changes.
|
||||
*
|
||||
* "op" is either RW_READER or RW_WRITER indicating the kind of lock
|
||||
* required. If a read lock on the cwdinfo is requested, then curlwp must
|
||||
* not block while holding the lock, or the cwdinfo could become stale.
|
||||
* It's okay to block while holding a write lock.
|
||||
*/
|
||||
struct cwdinfo *
|
||||
cwdenter(krw_t op)
|
||||
{
|
||||
struct cwdinfo *cwdi = curproc->p_cwdi;
|
||||
|
||||
if (__predict_true(op == RW_READER)) {
|
||||
/*
|
||||
* Disable preemption to hold off the writer side's xcall,
|
||||
* then observe the lock. If it's already taken, we need to
|
||||
* join in the melee. Otherwise we're good to go; keeping
|
||||
* the xcall at bay with kpreempt_disable() will prevent any
|
||||
* changes while the caller is pondering the cwdinfo.
|
||||
*/
|
||||
kpreempt_disable();
|
||||
if (__predict_true(mutex_owner(&cwdi->cwdi_lock) == NULL)) {
|
||||
membar_consumer();
|
||||
return cwdi;
|
||||
}
|
||||
kpreempt_enable();
|
||||
mutex_enter(&cwdi->cwdi_lock);
|
||||
} else {
|
||||
/*
|
||||
* About to make changes. If there's more than one
|
||||
* reference on the cwdinfo, or curproc has more than one
|
||||
* LWP, then LWPs other than curlwp can also see the
|
||||
* cwdinfo. Run a cross call to get all LWPs out of the
|
||||
* read section.
|
||||
*/
|
||||
mutex_enter(&cwdi->cwdi_lock);
|
||||
if (cwdi->cwdi_refcnt + curproc->p_nlwps > 2)
|
||||
xc_barrier(0);
|
||||
}
|
||||
return cwdi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a lock previously taken with cwdenter().
|
||||
*/
|
||||
void
|
||||
cwdexit(struct cwdinfo *cwdi)
|
||||
{
|
||||
struct lwp *l = curlwp;
|
||||
|
||||
KASSERT(cwdi == l->l_proc->p_cwdi);
|
||||
|
||||
if (__predict_true(mutex_owner(&cwdi->cwdi_lock) != l))
|
||||
kpreempt_enable();
|
||||
else
|
||||
mutex_exit(&cwdi->cwdi_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when there is a need to inspect some other process' cwdinfo. Used
|
||||
* by procfs and sysctl. This gets you a read lock; the cwdinfo must NOT be
|
||||
* changed.
|
||||
*/
|
||||
const struct cwdinfo *
|
||||
cwdlock(struct proc *p)
|
||||
{
|
||||
struct cwdinfo *cwdi = p->p_cwdi;
|
||||
|
||||
mutex_enter(&cwdi->cwdi_lock);
|
||||
return cwdi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a lock acquired with cwdlock().
|
||||
*/
|
||||
void
|
||||
cwdunlock(struct proc *p)
|
||||
{
|
||||
struct cwdinfo *cwdi = p->p_cwdi;
|
||||
|
||||
mutex_exit(&cwdi->cwdi_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a reference to the current working directory and return it.
|
||||
*/
|
||||
struct vnode *
|
||||
cwdcdir(void)
|
||||
{
|
||||
struct cwdinfo *cwdi;
|
||||
struct vnode *vp;
|
||||
|
||||
cwdi = cwdenter(RW_READER);
|
||||
if ((vp = cwdi->cwdi_cdir) != NULL)
|
||||
vref(vp);
|
||||
cwdexit(cwdi);
|
||||
return vp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a reference to the root directory and return it.
|
||||
*/
|
||||
struct vnode *
|
||||
cwdrdir(void)
|
||||
{
|
||||
struct cwdinfo *cwdi;
|
||||
struct vnode *vp;
|
||||
|
||||
cwdi = cwdenter(RW_READER);
|
||||
if ((vp = cwdi->cwdi_rdir) != NULL)
|
||||
vref(vp);
|
||||
cwdexit(cwdi);
|
||||
return vp;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_getcwd.c,v 1.54 2020/01/08 12:04:56 ad Exp $ */
|
||||
/* $NetBSD: vfs_getcwd.c,v 1.55 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_getcwd.c,v 1.54 2020/01/08 12:04:56 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_getcwd.c,v 1.55 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -503,7 +503,7 @@ sys___getcwd(struct lwp *l, const struct sys___getcwd_args *uap, register_t *ret
|
||||
char *bp, *bend;
|
||||
int len = SCARG(uap, length);
|
||||
int lenused;
|
||||
struct cwdinfo *cwdi;
|
||||
struct vnode *dvp;
|
||||
|
||||
if (len > MAXPATHLEN * 4)
|
||||
len = MAXPATHLEN * 4;
|
||||
@ -520,11 +520,10 @@ sys___getcwd(struct lwp *l, const struct sys___getcwd_args *uap, register_t *ret
|
||||
* Since each entry takes up at least 2 bytes in the output buffer,
|
||||
* limit it to N/2 vnodes for an N byte buffer.
|
||||
*/
|
||||
cwdi = l->l_proc->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
error = getcwd_common(cwdi->cwdi_cdir, NULL, &bp, path,
|
||||
dvp = cwdcdir();
|
||||
error = getcwd_common(dvp, NULL, &bp, path,
|
||||
len/2, GETCWD_CHECK_ACCESS, l);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
vrele(dvp);
|
||||
|
||||
if (error)
|
||||
goto out;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_lookup.c,v 1.213 2020/01/17 20:08:09 ad Exp $ */
|
||||
/* $NetBSD: vfs_lookup.c,v 1.214 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.213 2020/01/17 20:08:09 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.214 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_magiclinks.h"
|
||||
@ -535,7 +535,6 @@ namei_getstartdir(struct namei_state *state)
|
||||
struct nameidata *ndp = state->ndp;
|
||||
struct componentname *cnp = state->cnp;
|
||||
struct cwdinfo *cwdi; /* pointer to cwd state */
|
||||
struct lwp *self = curlwp; /* thread doing namei() */
|
||||
struct vnode *rootdir, *erootdir, *curdir, *startdir;
|
||||
|
||||
if (state->root_referenced) {
|
||||
@ -546,8 +545,8 @@ namei_getstartdir(struct namei_state *state)
|
||||
state->root_referenced = 0;
|
||||
}
|
||||
|
||||
cwdi = self->l_proc->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
/* NB: must not block while inspecting the cwdinfo. */
|
||||
cwdi = cwdenter(RW_READER);
|
||||
|
||||
/* root dir */
|
||||
if (cwdi->cwdi_rdir == NULL || (cnp->cn_flags & NOCHROOT)) {
|
||||
@ -605,7 +604,7 @@ namei_getstartdir(struct namei_state *state)
|
||||
vref(state->ndp->ni_erootdir);
|
||||
state->root_referenced = 1;
|
||||
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
cwdexit(cwdi);
|
||||
return startdir;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: vfs_mount.c,v 1.74 2020/01/17 20:08:09 ad Exp $ */
|
||||
/* $NetBSD: vfs_mount.c,v 1.75 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2019 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1997-2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -67,7 +67,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.74 2020/01/17 20:08:09 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.75 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -90,6 +90,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.74 2020/01/17 20:08:09 ad Exp $");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/vfs_syscalls.h>
|
||||
#include <sys/vnode_impl.h>
|
||||
#include <sys/xcall.h>
|
||||
|
||||
#include <miscfs/genfs/genfs.h>
|
||||
#include <miscfs/specfs/specdev.h>
|
||||
@ -675,18 +676,23 @@ mount_checkdirs(vnode_t *olddp)
|
||||
rele2 = NULL;
|
||||
atomic_inc_uint(&cwdi->cwdi_refcnt);
|
||||
mutex_exit(proc_lock);
|
||||
rw_enter(&cwdi->cwdi_lock, RW_WRITER);
|
||||
if (cwdi->cwdi_cdir == olddp) {
|
||||
rele1 = cwdi->cwdi_cdir;
|
||||
vref(newdp);
|
||||
cwdi->cwdi_cdir = newdp;
|
||||
mutex_enter(&cwdi->cwdi_lock);
|
||||
if (cwdi->cwdi_cdir == olddp ||
|
||||
cwdi->cwdi_rdir == olddp) {
|
||||
/* XXX belongs in vfs_cwd.c, but rump. */
|
||||
xc_barrier(0);
|
||||
if (cwdi->cwdi_cdir == olddp) {
|
||||
rele1 = cwdi->cwdi_cdir;
|
||||
vref(newdp);
|
||||
cwdi->cwdi_cdir = newdp;
|
||||
}
|
||||
if (cwdi->cwdi_rdir == olddp) {
|
||||
rele2 = cwdi->cwdi_rdir;
|
||||
vref(newdp);
|
||||
cwdi->cwdi_rdir = newdp;
|
||||
}
|
||||
}
|
||||
if (cwdi->cwdi_rdir == olddp) {
|
||||
rele2 = cwdi->cwdi_rdir;
|
||||
vref(newdp);
|
||||
cwdi->cwdi_rdir = newdp;
|
||||
}
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
mutex_exit(&cwdi->cwdi_lock);
|
||||
cwdfree(cwdi);
|
||||
if (rele1 != NULL)
|
||||
vrele(rele1);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: vfs_subr.c,v 1.480 2020/02/23 15:46:41 ad Exp $ */
|
||||
/* $NetBSD: vfs_subr.c,v 1.481 2020/02/23 22:14:03 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008, 2019
|
||||
* Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008, 2019, 2020
|
||||
* The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -69,7 +69,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.480 2020/02/23 15:46:41 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.481 2020/02/23 22:14:03 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ddb.h"
|
||||
@ -1111,7 +1111,7 @@ vprint_common(struct vnode *vp, const char *prefix,
|
||||
vp->v_usecount, vp->v_writecount, vp->v_holdcnt);
|
||||
(*pr)("%ssize %" PRIx64 " writesize %" PRIx64 " numoutput %d\n",
|
||||
prefix, vp->v_size, vp->v_writesize, vp->v_numoutput);
|
||||
(*pr)("%sdata %p lock %p\n", prefix, vp->v_data, vip->vi_lock);
|
||||
(*pr)("%sdata %p lock %p\n", prefix, vp->v_data, &vip->vi_lock);
|
||||
|
||||
(*pr)("%sstate %s key(%p %zd)", prefix, vstate_name(vip->vi_state),
|
||||
vip->vi_key.vk_mount, vip->vi_key.vk_key_len);
|
||||
@ -1215,24 +1215,25 @@ set_statvfs_info(const char *onp, int ukon, const char *fromp, int ukfrom,
|
||||
size_t size;
|
||||
struct statvfs *sfs = &mp->mnt_stat;
|
||||
int (*fun)(const void *, void *, size_t, size_t *);
|
||||
struct vnode *rvp;
|
||||
|
||||
(void)strlcpy(mp->mnt_stat.f_fstypename, vfsname,
|
||||
sizeof(mp->mnt_stat.f_fstypename));
|
||||
|
||||
if (onp) {
|
||||
struct cwdinfo *cwdi = l->l_proc->p_cwdi;
|
||||
fun = (ukon == UIO_SYSSPACE) ? copystr : copyinstr;
|
||||
if (cwdi->cwdi_rdir != NULL) {
|
||||
KASSERT(l == curlwp);
|
||||
rvp = cwdrdir();
|
||||
if (rvp != NULL) {
|
||||
size_t len;
|
||||
char *bp;
|
||||
char *path = PNBUF_GET();
|
||||
|
||||
bp = path + MAXPATHLEN;
|
||||
*--bp = '\0';
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp,
|
||||
error = getcwd_common(rvp, rootvnode, &bp,
|
||||
path, MAXPATHLEN / 2, 0, l);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
vrele(rvp);
|
||||
if (error) {
|
||||
PNBUF_PUT(path);
|
||||
return error;
|
||||
@ -1544,7 +1545,7 @@ vfs_vnode_lock_print(void *vlock, int full, void (*pr)(const char *, ...))
|
||||
|
||||
for (mp = _mountlist_next(NULL); mp; mp = _mountlist_next(mp)) {
|
||||
TAILQ_FOREACH(vip, &mp->mnt_vnodelist, vi_mntvnodes) {
|
||||
if (vip->vi_lock == vlock ||
|
||||
if (&vip->vi_lock == vlock ||
|
||||
VIMPL_TO_VNODE(vip)->v_interlock == vlock)
|
||||
vfs_vnode_print(VIMPL_TO_VNODE(vip), full, pr);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.541 2020/02/22 08:58:39 maxv Exp $ */
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.542 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009, 2019 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -70,7 +70,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.541 2020/02/22 08:58:39 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.542 2020/02/23 22:14:04 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_fileassoc.h"
|
||||
@ -1100,7 +1100,7 @@ int
|
||||
dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags,
|
||||
int root)
|
||||
{
|
||||
struct cwdinfo *cwdi = l->l_proc->p_cwdi;
|
||||
struct vnode *rvp;
|
||||
int error = 0;
|
||||
|
||||
/*
|
||||
@ -1111,19 +1111,20 @@ dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags,
|
||||
if (flags == MNT_NOWAIT || flags == MNT_LAZY ||
|
||||
(flags != MNT_WAIT && flags != 0)) {
|
||||
memcpy(sp, &mp->mnt_stat, sizeof(*sp));
|
||||
goto done;
|
||||
rvp = NULL;
|
||||
} else {
|
||||
/* Get the filesystem stats now */
|
||||
memset(sp, 0, sizeof(*sp));
|
||||
if ((error = VFS_STATVFS(mp, sp)) != 0) {
|
||||
return error;
|
||||
}
|
||||
KASSERT(l == curlwp);
|
||||
rvp = cwdrdir();
|
||||
if (rvp == NULL)
|
||||
(void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat));
|
||||
}
|
||||
|
||||
/* Get the filesystem stats now */
|
||||
memset(sp, 0, sizeof(*sp));
|
||||
if ((error = VFS_STATVFS(mp, sp)) != 0) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (cwdi->cwdi_rdir == NULL)
|
||||
(void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat));
|
||||
done:
|
||||
if (cwdi->cwdi_rdir != NULL) {
|
||||
if (rvp != NULL) {
|
||||
size_t len;
|
||||
char *bp;
|
||||
char c;
|
||||
@ -1131,12 +1132,11 @@ done:
|
||||
|
||||
bp = path + MAXPATHLEN;
|
||||
*--bp = '\0';
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path,
|
||||
error = getcwd_common(rvp, rootvnode, &bp, path,
|
||||
MAXPATHLEN / 2, 0, l);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
if (error) {
|
||||
PNBUF_PUT(path);
|
||||
vrele(rvp);
|
||||
return error;
|
||||
}
|
||||
len = strlen(bp);
|
||||
@ -1161,6 +1161,7 @@ done:
|
||||
}
|
||||
}
|
||||
PNBUF_PUT(path);
|
||||
vrele(rvp);
|
||||
}
|
||||
sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
|
||||
return error;
|
||||
@ -1330,7 +1331,6 @@ sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval)
|
||||
/* {
|
||||
syscallarg(int) fd;
|
||||
} */
|
||||
struct proc *p = l->l_proc;
|
||||
struct cwdinfo *cwdi;
|
||||
struct vnode *vp, *tdp;
|
||||
struct mount *mp;
|
||||
@ -1370,8 +1370,7 @@ sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval)
|
||||
* Disallow changing to a directory not under the process's
|
||||
* current root directory (if there is one).
|
||||
*/
|
||||
cwdi = p->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_WRITER);
|
||||
cwdi = cwdenter(RW_WRITER);
|
||||
if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, l)) {
|
||||
vrele(vp);
|
||||
error = EPERM; /* operation not permitted */
|
||||
@ -1379,7 +1378,7 @@ sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval)
|
||||
vrele(cwdi->cwdi_cdir);
|
||||
cwdi->cwdi_cdir = vp;
|
||||
}
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
cwdexit(cwdi);
|
||||
|
||||
out:
|
||||
fd_putfile(fd);
|
||||
@ -1393,7 +1392,6 @@ sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval)
|
||||
int
|
||||
sys_fchroot(struct lwp *l, const struct sys_fchroot_args *uap, register_t *retval)
|
||||
{
|
||||
struct proc *p = l->l_proc;
|
||||
struct vnode *vp;
|
||||
file_t *fp;
|
||||
int error, fd = SCARG(uap, fd);
|
||||
@ -1414,8 +1412,7 @@ sys_fchroot(struct lwp *l, const struct sys_fchroot_args *uap, register_t *retva
|
||||
if (error)
|
||||
goto out;
|
||||
vref(vp);
|
||||
|
||||
change_root(p->p_cwdi, vp, l);
|
||||
change_root(vp);
|
||||
|
||||
out:
|
||||
fd_putfile(fd);
|
||||
@ -1432,19 +1429,19 @@ sys_chdir(struct lwp *l, const struct sys_chdir_args *uap, register_t *retval)
|
||||
/* {
|
||||
syscallarg(const char *) path;
|
||||
} */
|
||||
struct proc *p = l->l_proc;
|
||||
struct cwdinfo *cwdi;
|
||||
int error;
|
||||
struct vnode *vp;
|
||||
struct vnode *vp, *ovp;
|
||||
|
||||
if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE,
|
||||
&vp, l)) != 0)
|
||||
error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE, &vp, l);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
cwdi = p->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_WRITER);
|
||||
vrele(cwdi->cwdi_cdir);
|
||||
|
||||
cwdi = cwdenter(RW_WRITER);
|
||||
ovp = cwdi->cwdi_cdir;
|
||||
cwdi->cwdi_cdir = vp;
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
cwdexit(cwdi);
|
||||
vrele(ovp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1458,20 +1455,17 @@ sys_chroot(struct lwp *l, const struct sys_chroot_args *uap, register_t *retval)
|
||||
/* {
|
||||
syscallarg(const char *) path;
|
||||
} */
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
struct vnode *vp;
|
||||
|
||||
if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT,
|
||||
KAUTH_REQ_SYSTEM_CHROOT_CHROOT, NULL, NULL, NULL)) != 0)
|
||||
return (error);
|
||||
if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE,
|
||||
&vp, l)) != 0)
|
||||
return (error);
|
||||
|
||||
change_root(p->p_cwdi, vp, l);
|
||||
|
||||
return (0);
|
||||
error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE, &vp, l);
|
||||
if (error == 0)
|
||||
change_root(vp);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1479,14 +1473,16 @@ sys_chroot(struct lwp *l, const struct sys_chroot_args *uap, register_t *retval)
|
||||
* NB: callers need to properly authorize the change root operation.
|
||||
*/
|
||||
void
|
||||
change_root(struct cwdinfo *cwdi, struct vnode *vp, struct lwp *l)
|
||||
change_root(struct vnode *vp)
|
||||
{
|
||||
struct proc *p = l->l_proc;
|
||||
struct cwdinfo *cwdi;
|
||||
kauth_cred_t ncred;
|
||||
struct lwp *l = curlwp;
|
||||
struct proc *p = l->l_proc;
|
||||
|
||||
ncred = kauth_cred_alloc();
|
||||
|
||||
rw_enter(&cwdi->cwdi_lock, RW_WRITER);
|
||||
cwdi = cwdenter(RW_WRITER);
|
||||
if (cwdi->cwdi_rdir != NULL)
|
||||
vrele(cwdi->cwdi_rdir);
|
||||
cwdi->cwdi_rdir = vp;
|
||||
@ -1505,7 +1501,7 @@ change_root(struct cwdinfo *cwdi, struct vnode *vp, struct lwp *l)
|
||||
vref(vp);
|
||||
cwdi->cwdi_cdir = vp;
|
||||
}
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
cwdexit(cwdi);
|
||||
|
||||
/* Get a write lock on the process credential. */
|
||||
proc_crmod_enter();
|
||||
@ -4676,21 +4672,15 @@ sys_umask(struct lwp *l, const struct sys_umask_args *uap, register_t *retval)
|
||||
/* {
|
||||
syscallarg(mode_t) newmask;
|
||||
} */
|
||||
struct proc *p = l->l_proc;
|
||||
struct cwdinfo *cwdi;
|
||||
|
||||
/*
|
||||
* cwdi->cwdi_cmask will be read unlocked elsewhere. What's
|
||||
* important is that we serialize changes to the mask. The
|
||||
* rw_exit() will issue a write memory barrier on our behalf,
|
||||
* and force the changes out to other CPUs (as it must use an
|
||||
* atomic operation, draining the local CPU's store buffers).
|
||||
* cwdi->cwdi_cmask will be read unlocked elsewhere, and no kind of
|
||||
* serialization with those reads is required. It's important to
|
||||
* return a coherent answer for the caller of umask() though, and
|
||||
* the atomic operation accomplishes that.
|
||||
*/
|
||||
cwdi = p->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_WRITER);
|
||||
*retval = cwdi->cwdi_cmask;
|
||||
cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
*retval = atomic_swap_uint(&curproc->p_cwdi->cwdi_cmask,
|
||||
SCARG(uap, newmask) & ALLPERMS);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_vnode.c,v 1.111 2020/02/23 15:46:41 ad Exp $ */
|
||||
/* $NetBSD: vfs_vnode.c,v 1.112 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2011, 2019, 2020 The NetBSD Foundation, Inc.
|
||||
@ -143,10 +143,19 @@
|
||||
* as vput(9), routines. Common points holding references are e.g.
|
||||
* file openings, current working directory, mount points, etc.
|
||||
*
|
||||
* Note on v_usecount and its locking
|
||||
*
|
||||
* At nearly all points it is known that v_usecount could be zero,
|
||||
* the vnode_t::v_interlock will be held. To change the count away
|
||||
* from zero, the interlock must be held. To change from a non-zero
|
||||
* value to zero, again the interlock must be held.
|
||||
*
|
||||
* Changing the usecount from a non-zero value to a non-zero value can
|
||||
* safely be done using atomic operations, without the interlock held.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.111 2020/02/23 15:46:41 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.112 2020/02/23 22:14:04 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_pax.h"
|
||||
@ -676,6 +685,27 @@ vdrain_thread(void *cookie)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to drop reference on a vnode. Abort if we are releasing the
|
||||
* last reference. Note: this _must_ succeed if not the last reference.
|
||||
*/
|
||||
static bool
|
||||
vtryrele(vnode_t *vp)
|
||||
{
|
||||
u_int use, next;
|
||||
|
||||
for (use = atomic_load_relaxed(&vp->v_usecount);; use = next) {
|
||||
if (__predict_false(use == 1)) {
|
||||
return false;
|
||||
}
|
||||
KASSERT(use > 1);
|
||||
next = atomic_cas_uint(&vp->v_usecount, use, use - 1);
|
||||
if (__predict_true(next == use)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* vput: unlock and release the reference.
|
||||
*/
|
||||
@ -684,7 +714,20 @@ vput(vnode_t *vp)
|
||||
{
|
||||
int lktype;
|
||||
|
||||
if ((vp->v_vflag & VV_LOCKSWORK) == 0) {
|
||||
/*
|
||||
* Do an unlocked check of v_usecount. If it looks like we're not
|
||||
* about to drop the last reference, then unlock the vnode and try
|
||||
* to drop the reference. If it ends up being the last reference
|
||||
* after all, vrelel() can fix it all up. Most of the time this
|
||||
* will all go to plan.
|
||||
*/
|
||||
if (atomic_load_relaxed(&vp->v_usecount) > 1) {
|
||||
VOP_UNLOCK(vp);
|
||||
if (vtryrele(vp)) {
|
||||
return;
|
||||
}
|
||||
lktype = LK_NONE;
|
||||
} else if ((vp->v_vflag & VV_LOCKSWORK) == 0) {
|
||||
lktype = LK_EXCLUSIVE;
|
||||
} else {
|
||||
lktype = VOP_ISLOCKED(vp);
|
||||
@ -713,14 +756,15 @@ vrelel(vnode_t *vp, int flags, int lktype)
|
||||
}
|
||||
|
||||
/*
|
||||
* If not the last reference, just drop the reference count
|
||||
* and unlock.
|
||||
* If not the last reference, just drop the reference count and
|
||||
* unlock. VOP_UNLOCK() is called here without a vnode reference
|
||||
* held, but is ok as the hold of v_interlock will stop the vnode
|
||||
* from disappearing.
|
||||
*/
|
||||
if (vp->v_usecount > 1) {
|
||||
if (vtryrele(vp)) {
|
||||
if (lktype != LK_NONE) {
|
||||
VOP_UNLOCK(vp);
|
||||
}
|
||||
vp->v_usecount--;
|
||||
mutex_exit(vp->v_interlock);
|
||||
return;
|
||||
}
|
||||
@ -802,8 +846,7 @@ vrelel(vnode_t *vp, int flags, int lktype)
|
||||
mutex_enter(vp->v_interlock);
|
||||
VSTATE_CHANGE(vp, VS_BLOCKED, VS_LOADED);
|
||||
if (!recycle) {
|
||||
if (vp->v_usecount > 1) {
|
||||
vp->v_usecount--;
|
||||
if (vtryrele(vp)) {
|
||||
mutex_exit(vp->v_interlock);
|
||||
return;
|
||||
}
|
||||
@ -834,8 +877,7 @@ vrelel(vnode_t *vp, int flags, int lktype)
|
||||
KASSERT(vp->v_usecount > 0);
|
||||
}
|
||||
|
||||
vp->v_usecount--;
|
||||
if (vp->v_usecount != 0) {
|
||||
if (atomic_dec_uint_nv(&vp->v_usecount) != 0) {
|
||||
/* Gained another reference while being reclaimed. */
|
||||
mutex_exit(vp->v_interlock);
|
||||
return;
|
||||
@ -862,6 +904,9 @@ void
|
||||
vrele(vnode_t *vp)
|
||||
{
|
||||
|
||||
if (vtryrele(vp)) {
|
||||
return;
|
||||
}
|
||||
mutex_enter(vp->v_interlock);
|
||||
vrelel(vp, 0, LK_NONE);
|
||||
}
|
||||
@ -873,6 +918,9 @@ void
|
||||
vrele_async(vnode_t *vp)
|
||||
{
|
||||
|
||||
if (vtryrele(vp)) {
|
||||
return;
|
||||
}
|
||||
mutex_enter(vp->v_interlock);
|
||||
vrelel(vp, VRELEL_ASYNC, LK_NONE);
|
||||
}
|
||||
@ -880,16 +928,16 @@ vrele_async(vnode_t *vp)
|
||||
/*
|
||||
* Vnode reference, where a reference is already held by some other
|
||||
* object (for example, a file structure).
|
||||
*
|
||||
* NB: we have lockless code sequences that rely on this not blocking.
|
||||
*/
|
||||
void
|
||||
vref(vnode_t *vp)
|
||||
{
|
||||
|
||||
KASSERT(vp->v_usecount != 0);
|
||||
KASSERT(atomic_load_relaxed(&vp->v_usecount) != 0);
|
||||
|
||||
mutex_enter(vp->v_interlock);
|
||||
vp->v_usecount++;
|
||||
mutex_exit(vp->v_interlock);
|
||||
atomic_inc_uint(&vp->v_usecount);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -906,6 +954,18 @@ vholdl(vnode_t *vp)
|
||||
lru_requeue(vp, lru_which(vp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Page or buffer structure gets a reference.
|
||||
*/
|
||||
void
|
||||
vhold(vnode_t *vp)
|
||||
{
|
||||
|
||||
mutex_enter(vp->v_interlock);
|
||||
vholdl(vp);
|
||||
mutex_exit(vp->v_interlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Page or buffer structure frees a reference.
|
||||
* Called with v_interlock held.
|
||||
@ -925,6 +985,18 @@ holdrelel(vnode_t *vp)
|
||||
lru_requeue(vp, lru_which(vp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Page or buffer structure frees a reference.
|
||||
*/
|
||||
void
|
||||
holdrele(vnode_t *vp)
|
||||
{
|
||||
|
||||
mutex_enter(vp->v_interlock);
|
||||
holdrelel(vp);
|
||||
mutex_exit(vp->v_interlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Recycle an unused vnode if caller holds the last reference.
|
||||
*/
|
||||
@ -1027,7 +1099,7 @@ vrevoke(vnode_t *vp)
|
||||
if (VSTATE_GET(vp) == VS_RECLAIMED) {
|
||||
mutex_exit(vp->v_interlock);
|
||||
} else if (vp->v_type != VBLK && vp->v_type != VCHR) {
|
||||
vp->v_usecount++;
|
||||
atomic_inc_uint(&vp->v_usecount);
|
||||
mutex_exit(vp->v_interlock);
|
||||
vgone(vp);
|
||||
} else {
|
||||
@ -1082,8 +1154,8 @@ static void
|
||||
vcache_init(void)
|
||||
{
|
||||
|
||||
vcache_pool = pool_cache_init(sizeof(vnode_impl_t), 0, 0, 0,
|
||||
"vcachepl", NULL, IPL_NONE, NULL, NULL, NULL);
|
||||
vcache_pool = pool_cache_init(sizeof(vnode_impl_t), coherency_unit,
|
||||
0, 0, "vcachepl", NULL, IPL_NONE, NULL, NULL, NULL);
|
||||
KASSERT(vcache_pool != NULL);
|
||||
mutex_init(&vcache_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
cv_init(&vcache_cv, "vcache");
|
||||
@ -1154,7 +1226,7 @@ vcache_alloc(void)
|
||||
vp = VIMPL_TO_VNODE(vip);
|
||||
memset(vip, 0, sizeof(*vip));
|
||||
|
||||
vip->vi_lock = rw_obj_alloc();
|
||||
rw_init(&vip->vi_lock);
|
||||
vp->v_interlock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
/* SLIST_INIT(&vip->vi_hash); */
|
||||
@ -1220,7 +1292,7 @@ vcache_free(vnode_impl_t *vip)
|
||||
spec_node_destroy(vp);
|
||||
|
||||
mutex_obj_free(vp->v_interlock);
|
||||
rw_obj_free(vip->vi_lock);
|
||||
rw_destroy(&vip->vi_lock);
|
||||
uvm_obj_destroy(&vp->v_uobj, true);
|
||||
cv_destroy(&vp->v_cv);
|
||||
pool_cache_put(vcache_pool, vip);
|
||||
@ -1244,8 +1316,10 @@ vcache_tryvget(vnode_t *vp)
|
||||
error = ENOENT;
|
||||
else if (__predict_false(VSTATE_GET(vp) != VS_LOADED))
|
||||
error = EBUSY;
|
||||
else if (vp->v_usecount == 0)
|
||||
vp->v_usecount = 1;
|
||||
else
|
||||
vp->v_usecount++;
|
||||
atomic_inc_uint(&vp->v_usecount);
|
||||
|
||||
mutex_exit(vp->v_interlock);
|
||||
|
||||
@ -1279,7 +1353,10 @@ vcache_vget(vnode_t *vp)
|
||||
return ENOENT;
|
||||
}
|
||||
VSTATE_ASSERT(vp, VS_LOADED);
|
||||
vp->v_usecount++;
|
||||
if (vp->v_usecount == 0)
|
||||
vp->v_usecount = 1;
|
||||
else
|
||||
atomic_inc_uint(&vp->v_usecount);
|
||||
mutex_exit(vp->v_interlock);
|
||||
|
||||
return 0;
|
||||
|
@ -29,7 +29,7 @@ copyright="\
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
"
|
||||
SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.68 2019/12/01 13:56:29 ad Exp $'
|
||||
SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.69 2020/02/23 22:14:04 ad Exp $'
|
||||
|
||||
# Script to produce VFS front-end sugar.
|
||||
#
|
||||
@ -481,7 +481,7 @@ function bodynorm() {
|
||||
}
|
||||
if (fstrans == "LOCK")
|
||||
printf("\terror = vop_pre(%s, &mp, &mpsafe, %s);\n",
|
||||
argname[0], "(flags & (LK_UPGRADE|LK_DOWNGRADE) ? FST_NO : (flags & LK_NOWAIT ? FST_TRY : FST_YES))");
|
||||
argname[0], "(!(flags & (LK_SHARED|LK_EXCLUSIVE)) ? FST_NO : (flags & LK_NOWAIT ? FST_TRY : FST_YES))");
|
||||
else if (fstrans == "UNLOCK")
|
||||
printf("\terror = vop_pre(%s, &mp, &mpsafe, FST_%s);\n",
|
||||
argname[0], "NO");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: genfs_vnops.c,v 1.201 2020/02/23 15:46:41 ad Exp $ */
|
||||
/* $NetBSD: genfs_vnops.c,v 1.202 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -57,7 +57,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.201 2020/02/23 15:46:41 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.202 2020/02/23 22:14:04 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -293,21 +293,19 @@ genfs_deadlock(void *v)
|
||||
return ENOENT;
|
||||
|
||||
if (ISSET(flags, LK_DOWNGRADE)) {
|
||||
rw_downgrade(vip->vi_lock);
|
||||
rw_downgrade(&vip->vi_lock);
|
||||
} else if (ISSET(flags, LK_UPGRADE)) {
|
||||
if (!rw_tryupgrade(vip->vi_lock)) {
|
||||
if (ISSET(flags, LK_NOWAIT))
|
||||
return EBUSY;
|
||||
rw_exit(vip->vi_lock);
|
||||
rw_enter(vip->vi_lock, RW_WRITER);
|
||||
KASSERT(ISSET(flags, LK_NOWAIT));
|
||||
if (!rw_tryupgrade(&vip->vi_lock)) {
|
||||
return EBUSY;
|
||||
}
|
||||
} else {
|
||||
} else if ((flags & (LK_EXCLUSIVE | LK_SHARED)) != 0) {
|
||||
op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
|
||||
if (ISSET(flags, LK_NOWAIT)) {
|
||||
if (!rw_tryenter(vip->vi_lock, op))
|
||||
if (!rw_tryenter(&vip->vi_lock, op))
|
||||
return EBUSY;
|
||||
} else {
|
||||
rw_enter(vip->vi_lock, op);
|
||||
rw_enter(&vip->vi_lock, op);
|
||||
}
|
||||
}
|
||||
VSTATE_ASSERT_UNLOCKED(vp, VS_RECLAIMED);
|
||||
@ -326,7 +324,7 @@ genfs_deadunlock(void *v)
|
||||
vnode_t *vp = ap->a_vp;
|
||||
vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
|
||||
|
||||
rw_exit(vip->vi_lock);
|
||||
rw_exit(&vip->vi_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -347,21 +345,19 @@ genfs_lock(void *v)
|
||||
krw_t op;
|
||||
|
||||
if (ISSET(flags, LK_DOWNGRADE)) {
|
||||
rw_downgrade(vip->vi_lock);
|
||||
rw_downgrade(&vip->vi_lock);
|
||||
} else if (ISSET(flags, LK_UPGRADE)) {
|
||||
if (!rw_tryupgrade(vip->vi_lock)) {
|
||||
if (ISSET(flags, LK_NOWAIT))
|
||||
return EBUSY;
|
||||
rw_exit(vip->vi_lock);
|
||||
rw_enter(vip->vi_lock, RW_WRITER);
|
||||
KASSERT(ISSET(flags, LK_NOWAIT));
|
||||
if (!rw_tryupgrade(&vip->vi_lock)) {
|
||||
return EBUSY;
|
||||
}
|
||||
} else {
|
||||
} else if ((flags & (LK_EXCLUSIVE | LK_SHARED)) != 0) {
|
||||
op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
|
||||
if (ISSET(flags, LK_NOWAIT)) {
|
||||
if (!rw_tryenter(vip->vi_lock, op))
|
||||
if (!rw_tryenter(&vip->vi_lock, op))
|
||||
return EBUSY;
|
||||
} else {
|
||||
rw_enter(vip->vi_lock, op);
|
||||
rw_enter(&vip->vi_lock, op);
|
||||
}
|
||||
}
|
||||
VSTATE_ASSERT_UNLOCKED(vp, VS_ACTIVE);
|
||||
@ -380,7 +376,7 @@ genfs_unlock(void *v)
|
||||
vnode_t *vp = ap->a_vp;
|
||||
vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
|
||||
|
||||
rw_exit(vip->vi_lock);
|
||||
rw_exit(&vip->vi_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -397,10 +393,10 @@ genfs_islocked(void *v)
|
||||
vnode_t *vp = ap->a_vp;
|
||||
vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
|
||||
|
||||
if (rw_write_held(vip->vi_lock))
|
||||
if (rw_write_held(&vip->vi_lock))
|
||||
return LK_EXCLUSIVE;
|
||||
|
||||
if (rw_read_held(vip->vi_lock))
|
||||
if (rw_read_held(&vip->vi_lock))
|
||||
return LK_SHARED;
|
||||
|
||||
return 0;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: procfs_vnops.c,v 1.208 2020/02/01 02:23:04 riastradh Exp $ */
|
||||
/* $NetBSD: procfs_vnops.c,v 1.209 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -105,7 +105,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.208 2020/02/01 02:23:04 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.209 2020/02/23 22:14:04 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/atomic.h>
|
||||
@ -558,7 +558,7 @@ static void
|
||||
procfs_dir(pfstype t, struct lwp *caller, struct proc *target, char **bpp,
|
||||
char *path, size_t len)
|
||||
{
|
||||
struct cwdinfo *cwdi;
|
||||
const struct cwdinfo *cwdi;
|
||||
struct vnode *vp, *rvp;
|
||||
char *bp;
|
||||
|
||||
@ -567,26 +567,25 @@ procfs_dir(pfstype t, struct lwp *caller, struct proc *target, char **bpp,
|
||||
* we are interested in to prevent it from disappearing
|
||||
* before getcwd_common() below.
|
||||
*/
|
||||
rw_enter(&target->p_cwdi->cwdi_lock, RW_READER);
|
||||
cwdi = cwdlock(target);
|
||||
switch (t) {
|
||||
case PFScwd:
|
||||
vp = target->p_cwdi->cwdi_cdir;
|
||||
vp = cwdi->cwdi_cdir;
|
||||
break;
|
||||
case PFSchroot:
|
||||
vp = target->p_cwdi->cwdi_rdir;
|
||||
vp = cwdi->cwdi_rdir;
|
||||
break;
|
||||
default:
|
||||
rw_exit(&target->p_cwdi->cwdi_lock);
|
||||
cwdunlock(target);
|
||||
return;
|
||||
}
|
||||
if (vp != NULL)
|
||||
vref(vp);
|
||||
rw_exit(&target->p_cwdi->cwdi_lock);
|
||||
cwdunlock(target);
|
||||
|
||||
cwdi = caller->l_proc->p_cwdi;
|
||||
rw_enter(&cwdi->cwdi_lock, RW_READER);
|
||||
KASSERT(caller == curlwp);
|
||||
|
||||
rvp = cwdi->cwdi_rdir;
|
||||
rvp = cwdrdir();
|
||||
bp = bpp ? *bpp : NULL;
|
||||
|
||||
/*
|
||||
@ -599,12 +598,15 @@ procfs_dir(pfstype t, struct lwp *caller, struct proc *target, char **bpp,
|
||||
*bpp = bp;
|
||||
}
|
||||
vrele(vp);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
if (rvp != NULL)
|
||||
vrele(rvp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rvp == NULL)
|
||||
if (rvp == NULL) {
|
||||
rvp = rootvnode;
|
||||
vref(rvp);
|
||||
}
|
||||
if (vp == NULL || getcwd_common(vp, rvp, bp ? &bp : NULL, path,
|
||||
len / 2, 0, caller) != 0) {
|
||||
if (bpp) {
|
||||
@ -618,7 +620,8 @@ procfs_dir(pfstype t, struct lwp *caller, struct proc *target, char **bpp,
|
||||
|
||||
if (vp != NULL)
|
||||
vrele(vp);
|
||||
rw_exit(&cwdi->cwdi_lock);
|
||||
if (rvp != NULL)
|
||||
vrele(rvp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1647,7 +1650,7 @@ procfs_readlink(void *v)
|
||||
len = strlen(bp);
|
||||
} else {
|
||||
file_t *fp;
|
||||
struct vnode *vxp, *vp;
|
||||
struct vnode *vxp, *rvp;
|
||||
|
||||
if ((error = procfs_proc_lock(pfs->pfs_pid, &pown, ESRCH)) != 0)
|
||||
return error;
|
||||
@ -1680,14 +1683,13 @@ procfs_readlink(void *v)
|
||||
if (vxp->v_tag == VT_PROCFS) {
|
||||
*--bp = '/';
|
||||
} else {
|
||||
rw_enter(&curproc->p_cwdi->cwdi_lock,
|
||||
RW_READER);
|
||||
vp = curproc->p_cwdi->cwdi_rdir;
|
||||
if (vp == NULL)
|
||||
vp = rootvnode;
|
||||
error = getcwd_common(vxp, vp, &bp, path,
|
||||
if ((rvp = cwdrdir()) == NULL) {
|
||||
rvp = rootvnode;
|
||||
vref(rvp);
|
||||
}
|
||||
error = getcwd_common(vxp, rvp, &bp, path,
|
||||
MAXPATHLEN / 2, 0, curlwp);
|
||||
rw_exit(&curproc->p_cwdi->cwdi_lock);
|
||||
vrele(rvp);
|
||||
}
|
||||
if (error)
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: filedesc.h,v 1.65 2019/10/06 07:15:34 mlelstv Exp $ */
|
||||
/* $NetBSD: filedesc.h,v 1.66 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -168,8 +168,8 @@ typedef struct cwdinfo {
|
||||
struct vnode *cwdi_cdir; /* current directory */
|
||||
struct vnode *cwdi_rdir; /* root directory */
|
||||
struct vnode *cwdi_edir; /* emulation root (if known) */
|
||||
krwlock_t cwdi_lock; /* lock on entire struct */
|
||||
u_short cwdi_cmask; /* mask for file creation */
|
||||
kmutex_t cwdi_lock; /* lock on entire struct */
|
||||
u_int cwdi_cmask; /* mask for file creation */
|
||||
u_int cwdi_refcnt; /* reference count */
|
||||
} cwdinfo_t;
|
||||
|
||||
@ -215,11 +215,17 @@ int pipe1(struct lwp *, int *, int);
|
||||
int dodup(struct lwp *, int, int, int, register_t *);
|
||||
|
||||
void cwd_sys_init(void);
|
||||
struct cwdinfo *cwdinit(void);
|
||||
struct cwdinfo *cwdinit(void);
|
||||
void cwdshare(proc_t *);
|
||||
void cwdunshare(proc_t *);
|
||||
void cwdfree(struct cwdinfo *);
|
||||
void cwdexec(struct proc *);
|
||||
struct cwdinfo *cwdenter(krw_t);
|
||||
void cwdexit(struct cwdinfo *);
|
||||
const struct cwdinfo *cwdlock(struct proc *);
|
||||
void cwdunlock(struct proc *);
|
||||
struct vnode *cwdcdir(void);
|
||||
struct vnode *cwdrdir(void);
|
||||
|
||||
#define GETCWD_CHECK_ACCESS 0x0001
|
||||
int getcwd_common(struct vnode *, struct vnode *, char **, char *, int,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_syscalls.h,v 1.26 2019/09/26 01:34:16 christos Exp $ */
|
||||
/* $NetBSD: vfs_syscalls.h,v 1.27 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
|
||||
@ -82,7 +82,7 @@ int do_sys_quotactl(const char *, const struct quotactl_args *);
|
||||
void do_sys_sync(struct lwp *);
|
||||
|
||||
int chdir_lookup(const char *, int, struct vnode **, struct lwp *);
|
||||
void change_root(struct cwdinfo *, struct vnode *, struct lwp *);
|
||||
void change_root(struct vnode *);
|
||||
|
||||
extern const char *const mountcompatnames[];
|
||||
extern const u_int nmountcompatnames;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vnode.h,v 1.288 2020/02/23 15:46:42 ad Exp $ */
|
||||
/* $NetBSD: vnode.h,v 1.289 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -138,22 +138,36 @@ LIST_HEAD(buflists, buf);
|
||||
* it from v_data.
|
||||
*/
|
||||
struct vnode {
|
||||
struct uvm_object v_uobj; /* i the VM object */
|
||||
kmutex_t *v_interlock; /* - vnode interlock */
|
||||
kcondvar_t v_cv; /* i synchronization */
|
||||
/*
|
||||
* VM system related items.
|
||||
*/
|
||||
struct uvm_object v_uobj; /* u the VM object */
|
||||
voff_t v_size; /* i+u size of file */
|
||||
voff_t v_writesize; /* i+u new size after write */
|
||||
int v_iflag; /* i VI_* flags */
|
||||
int v_vflag; /* v VV_* flags */
|
||||
|
||||
/*
|
||||
* Unstable items get their own cache line.
|
||||
* On _LP64 this fills the space nicely.
|
||||
*/
|
||||
kcondvar_t v_cv /* i synchronization */
|
||||
__aligned(COHERENCY_UNIT);
|
||||
int v_iflag; /* i+u VI_* flags */
|
||||
int v_uflag; /* k VU_* flags */
|
||||
int v_usecount; /* i reference count */
|
||||
int v_numoutput; /* i # of pending writes */
|
||||
int v_writecount; /* i ref count of writers */
|
||||
int v_holdcnt; /* i page & buffer refs */
|
||||
struct mount *v_mount; /* v ptr to vfs we are in */
|
||||
int (**v_op)(void *); /* - vnode operations vector */
|
||||
struct buflists v_cleanblkhd; /* i+b clean blocklist head */
|
||||
struct buflists v_dirtyblkhd; /* i+b dirty blocklist head */
|
||||
|
||||
/*
|
||||
* The remaining items are largely stable.
|
||||
*/
|
||||
int v_vflag /* v VV_* flags */
|
||||
__aligned(COHERENCY_UNIT);
|
||||
kmutex_t *v_interlock; /* - vnode interlock */
|
||||
struct mount *v_mount; /* v ptr to vfs we are in */
|
||||
int (**v_op)(void *); /* : vnode operations vector */
|
||||
union {
|
||||
struct mount *vu_mountedhere;/* v ptr to vfs (VDIR) */
|
||||
struct socket *vu_socket; /* v unix ipc (VSOCK) */
|
||||
@ -327,36 +341,11 @@ extern const int vttoif_tab[];
|
||||
#define VDEAD_NOWAIT 0x0001 /* vdead_check: do not sleep */
|
||||
|
||||
void holdrelel(struct vnode *);
|
||||
void holdrele(struct vnode *);
|
||||
void vholdl(struct vnode *);
|
||||
void vhold(struct vnode *);
|
||||
void vref(struct vnode *);
|
||||
|
||||
static __inline void holdrele(struct vnode *) __unused;
|
||||
static __inline void vhold(struct vnode *) __unused;
|
||||
|
||||
/*
|
||||
* decrease buf or page ref
|
||||
*/
|
||||
static __inline void
|
||||
holdrele(struct vnode *vp)
|
||||
{
|
||||
|
||||
mutex_enter(vp->v_interlock);
|
||||
holdrelel(vp);
|
||||
mutex_exit(vp->v_interlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* increase buf or page ref
|
||||
*/
|
||||
static __inline void
|
||||
vhold(struct vnode *vp)
|
||||
{
|
||||
|
||||
mutex_enter(vp->v_interlock);
|
||||
vholdl(vp);
|
||||
mutex_exit(vp->v_interlock);
|
||||
}
|
||||
|
||||
#define NULLVP ((struct vnode *)NULL)
|
||||
|
||||
static __inline void
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: vnode_impl.h,v 1.20 2020/01/08 12:04:56 ad Exp $ */
|
||||
/* $NetBSD: vnode_impl.h,v 1.21 2020/02/23 22:14:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016, 2019 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2016, 2019, 2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -32,6 +32,7 @@
|
||||
#include <sys/vnode.h>
|
||||
|
||||
struct namecache;
|
||||
struct nchnode;
|
||||
|
||||
enum vnode_state {
|
||||
VS_ACTIVE, /* Assert only, fs node attached and usecount > 0. */
|
||||
@ -56,27 +57,53 @@ struct vcache_key {
|
||||
* Reading or writing any of these items requires holding the appropriate
|
||||
* lock. Field markings and the corresponding locks:
|
||||
*
|
||||
* - stable throughout the life of the vnode
|
||||
* c vcache_lock
|
||||
* d vdrain_lock
|
||||
* i v_interlock
|
||||
* l vi_nc_listlock
|
||||
* m mnt_vnodelock
|
||||
* n namecache_lock
|
||||
* s syncer_data_lock
|
||||
*/
|
||||
struct vnode_impl {
|
||||
struct vnode vi_vnode;
|
||||
enum vnode_state vi_state; /* i: current state */
|
||||
struct vnodelst *vi_lrulisthd; /* d: current lru list head */
|
||||
TAILQ_ENTRY(vnode_impl) vi_lrulist; /* d: lru list */
|
||||
LIST_HEAD(, namecache) vi_dnclist; /* n: namecaches (children) */
|
||||
|
||||
/*
|
||||
* Largely stable data.
|
||||
*/
|
||||
struct vcache_key vi_key; /* c vnode cache key */
|
||||
|
||||
/*
|
||||
* Namecache. Give it a separate line so activity doesn't impinge
|
||||
* on the stable stuff (pending merge of ad-namecache branch).
|
||||
*/
|
||||
LIST_HEAD(, namecache) vi_dnclist /* n: namecaches (children) */
|
||||
__aligned(COHERENCY_UNIT);
|
||||
TAILQ_HEAD(, namecache) vi_nclist; /* n: namecaches (parent) */
|
||||
int vi_synclist_slot; /* s: synclist slot index */
|
||||
int vi_lrulisttm; /* i: time of lru enqueue */
|
||||
TAILQ_ENTRY(vnode_impl) vi_synclist; /* s: vnodes with dirty bufs */
|
||||
TAILQ_ENTRY(vnode_impl) vi_mntvnodes; /* m: vnodes for mount point */
|
||||
SLIST_ENTRY(vnode_impl) vi_hash; /* c: vnode cache list */
|
||||
krwlock_t *vi_lock; /* -: lock for this vnode */
|
||||
struct vcache_key vi_key; /* c: vnode cache key */
|
||||
|
||||
/*
|
||||
* vnode cache, LRU and syncer. This all changes with some
|
||||
* regularity so keep it together.
|
||||
*/
|
||||
struct vnodelst *vi_lrulisthd /* d current lru list head */
|
||||
__aligned(COHERENCY_UNIT);
|
||||
TAILQ_ENTRY(vnode_impl) vi_lrulist; /* d lru list */
|
||||
int vi_synclist_slot; /* s synclist slot index */
|
||||
int vi_lrulisttm; /* i time of lru enqueue */
|
||||
TAILQ_ENTRY(vnode_impl) vi_synclist; /* s vnodes with dirty bufs */
|
||||
SLIST_ENTRY(vnode_impl) vi_hash; /* c vnode cache list */
|
||||
enum vnode_state vi_state; /* i current state */
|
||||
|
||||
/*
|
||||
* Locks and expensive to access items which can be expected to
|
||||
* generate a cache miss.
|
||||
*/
|
||||
krwlock_t vi_lock /* - lock for this vnode */
|
||||
__aligned(COHERENCY_UNIT);
|
||||
krwlock_t vi_nc_lock; /* - lock on node */
|
||||
krwlock_t vi_nc_listlock; /* - lock on nn_list */
|
||||
TAILQ_ENTRY(vnode_impl) vi_mntvnodes; /* m vnodes for mount point */
|
||||
};
|
||||
typedef struct vnode_impl vnode_impl_t;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user