Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Feb 2019 16:38:31 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r343914 - stable/12/sys/kern
Message-ID:  <201902081638.x18GcVZ7088559@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Fri Feb  8 16:38:30 2019
New Revision: 343914
URL: https://svnweb.freebsd.org/changeset/base/343914

Log:
  MFC r343626:
  Prevent some kobj memory allocation failures from panicking the system.

Modified:
  stable/12/sys/kern/subr_kobj.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/kern/subr_kobj.c
==============================================================================
--- stable/12/sys/kern/subr_kobj.c	Fri Feb  8 16:18:17 2019	(r343913)
+++ stable/12/sys/kern/subr_kobj.c	Fri Feb  8 16:38:30 2019	(r343914)
@@ -125,38 +125,43 @@ kobj_class_compile_common(kobj_class_t cls, kobj_ops_t
 	cls->ops = ops;
 }
 
-void
-kobj_class_compile(kobj_class_t cls)
+static int
+kobj_class_compile1(kobj_class_t cls, int mflags)
 {
 	kobj_ops_t ops;
 
 	KOBJ_ASSERT(MA_NOTOWNED);
 
-	/*
-	 * Allocate space for the compiled ops table.
-	 */
-	ops = malloc(sizeof(struct kobj_ops), M_KOBJ, M_NOWAIT);
-	if (!ops)
-		panic("%s: out of memory", __func__);
+	ops = malloc(sizeof(struct kobj_ops), M_KOBJ, mflags);
+	if (ops == NULL)
+		return (ENOMEM);
 
-	KOBJ_LOCK();
-	
 	/*
 	 * We may have lost a race for kobj_class_compile here - check
 	 * to make sure someone else hasn't already compiled this
 	 * class.
 	 */
+	KOBJ_LOCK();
 	if (cls->ops) {
 		KOBJ_UNLOCK();
 		free(ops, M_KOBJ);
-		return;
+		return (0);
 	}
-
 	kobj_class_compile_common(cls, ops);
 	KOBJ_UNLOCK();
+	return (0);
 }
 
 void
+kobj_class_compile(kobj_class_t cls)
+{
+	int error;
+
+	error = kobj_class_compile1(cls, M_WAITOK);
+	KASSERT(error == 0, ("kobj_class_compile1 returned %d", error));
+}
+
+void
 kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops)
 {
 
@@ -254,24 +259,6 @@ kobj_class_free(kobj_class_t cls)
 		free(ops, M_KOBJ);
 }
 
-kobj_t
-kobj_create(kobj_class_t cls,
-	    struct malloc_type *mtype,
-	    int mflags)
-{
-	kobj_t obj;
-
-	/*
-	 * Allocate and initialise the new object.
-	 */
-	obj = malloc(cls->size, mtype, mflags | M_ZERO);
-	if (!obj)
-		return NULL;
-	kobj_init(obj, cls);
-
-	return obj;
-}
-
 static void
 kobj_init_common(kobj_t obj, kobj_class_t cls)
 {
@@ -280,30 +267,52 @@ kobj_init_common(kobj_t obj, kobj_class_t cls)
 	cls->refs++;
 }
 
-void
-kobj_init(kobj_t obj, kobj_class_t cls)
+static int
+kobj_init1(kobj_t obj, kobj_class_t cls, int mflags)
 {
-	KOBJ_ASSERT(MA_NOTOWNED);
-  retry:
-	KOBJ_LOCK();
+	int error;
 
-	/*
-	 * Consider compiling the class' method table.
-	 */
-	if (!cls->ops) {
+	KOBJ_LOCK();
+	while (cls->ops == NULL) {
 		/*
 		 * kobj_class_compile doesn't want the lock held
 		 * because of the call to malloc - we drop the lock
 		 * and re-try.
 		 */
 		KOBJ_UNLOCK();
-		kobj_class_compile(cls);
-		goto retry;
+		error = kobj_class_compile1(cls, mflags);
+		if (error != 0)
+			return (error);
+		KOBJ_LOCK();
 	}
-
 	kobj_init_common(obj, cls);
-
 	KOBJ_UNLOCK();
+	return (0);
+}
+
+kobj_t
+kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags)
+{
+	kobj_t obj;
+
+	obj = malloc(cls->size, mtype, mflags | M_ZERO);
+	if (obj == NULL)
+		return (NULL);
+	if (kobj_init1(obj, cls, mflags) != 0) {
+		free(obj, mtype);
+		return (NULL);
+	}
+	return (obj);
+}
+
+void
+kobj_init(kobj_t obj, kobj_class_t cls)
+{
+	int error;
+
+	error = kobj_init1(obj, cls, M_NOWAIT);
+	if (error != 0)
+		panic("kobj_init1 failed: error %d", error);
 }
 
 void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902081638.x18GcVZ7088559>