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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to