Date: Sat, 14 Nov 2020 19:22:02 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r367695 - in head/sys: kern sys Message-ID: <202011141922.0AEJM2ld055995@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mjg Date: Sat Nov 14 19:22:02 2020 New Revision: 367695 URL: https://svnweb.freebsd.org/changeset/base/367695 Log: thread: batch credential freeing Modified: head/sys/kern/kern_prot.c head/sys/kern/kern_thread.c head/sys/sys/ucred.h Modified: head/sys/kern/kern_prot.c ============================================================================== --- head/sys/kern/kern_prot.c Sat Nov 14 19:21:46 2020 (r367694) +++ head/sys/kern/kern_prot.c Sat Nov 14 19:22:02 2020 (r367695) @@ -86,6 +86,7 @@ static MALLOC_DEFINE(M_CRED, "cred", "credentials"); SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "BSD security policy"); +static void crfree_final(struct ucred *cr); static void crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups); @@ -1902,6 +1903,31 @@ crunuse(struct thread *td) return (crold); } +static void +crunusebatch(struct ucred *cr, int users, int ref) +{ + + KASSERT(users > 0, ("%s: passed users %d not > 0 ; cred %p", + __func__, users, cr)); + mtx_lock(&cr->cr_mtx); + KASSERT(cr->cr_users >= users, ("%s: users %d not > %d on cred %p", + __func__, cr->cr_users, users, cr)); + cr->cr_users -= users; + cr->cr_ref += ref; + cr->cr_ref -= users; + if (cr->cr_users > 0) { + mtx_unlock(&cr->cr_mtx); + return; + } + KASSERT(cr->cr_ref >= 0, ("%s: ref %d not >= 0 on cred %p", + __func__, cr->cr_ref, cr)); + if (cr->cr_ref > 0) { + mtx_unlock(&cr->cr_mtx); + return; + } + crfree_final(cr); +} + void crcowfree(struct thread *td) { @@ -1935,6 +1961,44 @@ crcowsync(void) } /* + * Batching. + */ +void +credbatch_add(struct credbatch *crb, struct thread *td) +{ + struct ucred *cr; + + MPASS(td->td_realucred != NULL); + MPASS(td->td_realucred == td->td_ucred); + MPASS(td->td_state == TDS_INACTIVE); + cr = td->td_realucred; + KASSERT(cr->cr_users > 0, ("%s: users %d not > 0 on cred %p", + __func__, cr->cr_users, cr)); + if (crb->cred != cr) { + if (crb->users > 0) { + MPASS(crb->cred != NULL); + crunusebatch(crb->cred, crb->users, crb->ref); + crb->users = 0; + crb->ref = 0; + } + } + crb->cred = cr; + crb->users++; + crb->ref += td->td_ucredref; + td->td_ucredref = 0; + td->td_realucred = NULL; +} + +void +credbatch_final(struct credbatch *crb) +{ + + MPASS(crb->cred != NULL); + MPASS(crb->users > 0); + crunusebatch(crb->cred, crb->users, crb->ref); +} + +/* * Allocate a zeroed cred structure. */ struct ucred * @@ -2007,6 +2071,17 @@ crfree(struct ucred *cr) mtx_unlock(&cr->cr_mtx); return; } + crfree_final(cr); +} + +static void +crfree_final(struct ucred *cr) +{ + + KASSERT(cr->cr_users == 0, ("%s: users %d not == 0 on cred %p", + __func__, cr->cr_users, cr)); + KASSERT(cr->cr_ref == 0, ("%s: ref %d not == 0 on cred %p", + __func__, cr->cr_ref, cr)); /* * Some callers of crget(), such as nfs_statfs(), allocate a temporary * credential, but don't allocate a uidinfo structure. Modified: head/sys/kern/kern_thread.c ============================================================================== --- head/sys/kern/kern_thread.c Sat Nov 14 19:21:46 2020 (r367694) +++ head/sys/kern/kern_thread.c Sat Nov 14 19:22:02 2020 (r367695) @@ -536,6 +536,7 @@ thread_reap(void) { struct thread *itd, *ntd; struct tidbatch tidbatch; + struct credbatch credbatch; int tdcount; struct plimit *lim; int limcount; @@ -553,6 +554,7 @@ thread_reap(void) return; tidbatch_prep(&tidbatch); + credbatch_prep(&credbatch); tdcount = 0; lim = NULL; limcount = 0; @@ -560,8 +562,7 @@ thread_reap(void) ntd = itd->td_zombie; EVENTHANDLER_DIRECT_INVOKE(thread_dtor, itd); tidbatch_add(&tidbatch, itd); - MPASS(itd->td_realucred != NULL); - crcowfree(itd); + credbatch_add(&credbatch, itd); MPASS(itd->td_limit != NULL); if (lim != itd->td_limit) { if (limcount != 0) { @@ -573,6 +574,7 @@ thread_reap(void) limcount++; thread_free_batched(itd); tidbatch_process(&tidbatch); + credbatch_process(&credbatch); tdcount++; if (tdcount == 32) { thread_count_sub(tdcount); @@ -582,6 +584,7 @@ thread_reap(void) } tidbatch_final(&tidbatch); + credbatch_final(&credbatch); if (tdcount != 0) { thread_count_sub(tdcount); } Modified: head/sys/sys/ucred.h ============================================================================== --- head/sys/sys/ucred.h Sat Nov 14 19:21:46 2020 (r367694) +++ head/sys/sys/ucred.h Sat Nov 14 19:22:02 2020 (r367695) @@ -114,6 +114,28 @@ struct xucred { struct proc; struct thread; +struct credbatch { + struct ucred *cred; + int users; + int ref; +}; + +static inline void +credbatch_prep(struct credbatch *crb) +{ + crb->cred = NULL; + crb->users = 0; + crb->ref = 0; +} +void credbatch_add(struct credbatch *crb, struct thread *td); +static inline void +credbatch_process(struct credbatch *crb) +{ + +} +void credbatch_add(struct credbatch *crb, struct thread *td); +void credbatch_final(struct credbatch *crb); + void change_egid(struct ucred *newcred, gid_t egid); void change_euid(struct ucred *newcred, struct uidinfo *euip); void change_rgid(struct ucred *newcred, gid_t rgid);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202011141922.0AEJM2ld055995>