svn commit: r367695 - in head/sys: kern sys

Mateusz Guzik mjg at FreeBSD.org
Sat Nov 14 19:22:03 UTC 2020


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);


More information about the svn-src-head mailing list