}
LIST_INSERT_HEAD(&allprison, pr, pr_list);
- prisoncount++;
+ atomic_add_int(&prisoncount, 1);
error = kern_jail_attach(pr->pr_id);
if (error) {
SYSCTL_OID(_jail, OID_AUTO, list, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
sysctl_jail_list, "A", "List of active jails");
+/*
+ * MPSAFE
+ */
void
prison_hold(struct prison *pr)
{
- pr->pr_ref++;
+ atomic_add_int(&pr->pr_ref, 1);
}
+/*
+ * MPALMOSTSAFE
+ */
void
prison_free(struct prison *pr)
{
struct jail_ip_storage *jls;
- KKASSERT(pr->pr_ref >= 1);
- if (--pr->pr_ref > 0)
+ KKASSERT(pr->pr_ref > 0);
+ if (atomic_fetchadd_int(&pr->pr_ref, -1) != 1)
return;
- /* Delete all ips */
+ /*
+ * The MP lock is needed on the last ref to adjust
+ * the list.
+ */
+ get_mplock();
+ if (pr->pr_ref) {
+ rel_mplock();
+ return;
+ }
+ LIST_REMOVE(pr, pr_list);
+ atomic_add_int(&prisoncount, -1);
+ rel_mplock();
+
+ /*
+ * Clean up
+ */
while (!SLIST_EMPTY(&pr->pr_ips)) {
jls = SLIST_FIRST(&pr->pr_ips);
SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
kfree(jls, M_PRISON);
}
- LIST_REMOVE(pr, pr_list);
- prisoncount--;
if (pr->pr_linux != NULL)
kfree(pr->pr_linux, M_PRISON);
_crinit(struct ucred *cr)
{
cr->cr_ref = 1;
- spin_init(&cr->cr_spin);
}
/*
* must also use atomic_subtract_int() below. A spinlock is required
* in crfree() to handle multiple callers racing the refcount to 0.
*
- * MPALMOSTSAFE - acquires mplock on 1->0 transition of ref count
+ * MPSAFE
*/
void
crfree(struct ucred *cr)
{
if (cr->cr_ref <= 0)
panic("Freeing already free credential! %p", cr);
- spin_lock_wr(&cr->cr_spin);
- atomic_subtract_int(&cr->cr_ref, 1);
- if (cr->cr_ref == 0) {
- spin_unlock_wr(&cr->cr_spin);
+ if (atomic_fetchadd_int(&cr->cr_ref, -1) == 1) {
/*
* Some callers of crget(), such as nfs_statfs(),
* allocate a temporary credential, but don't
* allocate a uidinfo structure.
*/
- get_mplock();
if (cr->cr_uidinfo != NULL) {
uidrop(cr->cr_uidinfo);
cr->cr_uidinfo = NULL;
cr->cr_prison = NULL; /* safety */
FREE((caddr_t)cr, M_CRED);
- rel_mplock();
- } else {
- spin_unlock_wr(&cr->cr_spin);
}
}
/*
* Atomize a cred structure so it can be modified without polluting
* other references to it.
+ *
+ * MPSAFE (however, *pcr must be stable)
*/
struct ucred *
cratom(struct ucred **pcr)
#if 0 /* no longer used but keep around for a little while */
/*
* Copy cred structure to a new one and free the old one.
+ *
+ * MPSAFE (*cr must be stable)
*/
struct ucred *
crcopy(struct ucred *cr)
uihold(struct uidinfo *uip)
{
atomic_add_int(&uip->ui_ref, 1);
- KKASSERT(uip->ui_ref > 0);
+ KKASSERT(uip->ui_ref >= 0);
}
/*
void
uidrop(struct uidinfo *uip)
{
+ KKASSERT(uip->ui_ref > 0);
if (atomic_fetchadd_int(&uip->ui_ref, -1) == 1) {
uifree(uip);
- } else {
- KKASSERT(uip->ui_ref > 0);
}
}
*
* This is a rare case where callers are allowed to hold a spinlock,
* so we can't ourselves.
+ *
+ * MPSAFE
*/
static __inline
struct namecache *
_cache_drop(struct namecache *ncp)
{
KKASSERT(ncp->nc_refs > 0);
- if (ncp->nc_refs == 1 &&
- (ncp->nc_flag & NCF_UNRESOLVED) &&
+ if (ncp->nc_refs == 1 &&
+ (ncp->nc_flag & NCF_UNRESOLVED) &&
TAILQ_EMPTY(&ncp->nc_list)
) {
KKASSERT(ncp->nc_exlocks == 0);
*
* Warning: caller may hold an unrelated read spinlock, which means we can't
* use read spinlocks here.
+ *
+ * MPSAFE if nch is
*/
struct nchandle *
cache_hold(struct nchandle *nch)
{
_cache_hold(nch->ncp);
- ++nch->mount->mnt_refs;
+ atomic_add_int(&nch->mount->mnt_refs, 1);
return(nch);
}
+/*
+ * Create a copy of a namecache handle for an already-referenced
+ * entry.
+ *
+ * MPSAFE if nch is
+ */
void
cache_copy(struct nchandle *nch, struct nchandle *target)
{
*target = *nch;
_cache_hold(target->ncp);
- ++nch->mount->mnt_refs;
+ atomic_add_int(&nch->mount->mnt_refs, 1);
}
+/*
+ * MPSAFE if nch is
+ */
void
cache_changemount(struct nchandle *nch, struct mount *mp)
{
- --nch->mount->mnt_refs;
+ atomic_add_int(&nch->mount->mnt_refs, -1);
nch->mount = mp;
- ++nch->mount->mnt_refs;
+ atomic_add_int(&nch->mount->mnt_refs, 1);
}
void
cache_drop(struct nchandle *nch)
{
- --nch->mount->mnt_refs;
+ atomic_add_int(&nch->mount->mnt_refs, -1);
_cache_drop(nch->ncp);
nch->ncp = NULL;
nch->mount = NULL;
{
target->mount = nch->mount;
target->ncp = _cache_get(nch->ncp);
- ++target->mount->mnt_refs;
+ atomic_add_int(&target->mount->mnt_refs, 1);
}
static int
int error;
if ((error = _cache_get_nonblock(nch->ncp)) == 0)
- ++nch->mount->mnt_refs;
+ atomic_add_int(&nch->mount->mnt_refs, 1);
return (error);
}
void
cache_put(struct nchandle *nch)
{
- --nch->mount->mnt_refs;
+ atomic_add_int(&nch->mount->mnt_refs, -1);
_cache_put(nch->ncp);
nch->ncp = NULL;
nch->mount = NULL;
cache_hysteresis();
nch.mount = mp;
nch.ncp = ncp;
- ++nch.mount->mnt_refs;
+ atomic_add_int(&nch.mount->mnt_refs, 1);
return(nch);
}
{
nch->ncp = cache_alloc(0);
nch->mount = mp;
- ++mp->mnt_refs;
+ atomic_add_int(&mp->mnt_refs, 1);
if (vp)
_cache_setvp(nch->mount, nch->ncp, vp);
}
*
* The first process proc0's credentials are used if the calling thread
* is not associated with a process context.
+ *
+ * MPSAFE
*/
int
nlookup_init(struct nlookupdata *nd,
uid_t cr_svuid; /* Saved effective user id. */
gid_t cr_rgid; /* Real group id. */
gid_t cr_svgid; /* Saved effective group id. */
- struct spinlock cr_spin;
};
#define cr_gid cr_groups[0]
#define NOCRED ((struct ucred *)0) /* no credential available */