usr/src/uts/common/os/logsubr.c
changeset 1259 8e7e69328588
parent 850 504be1e0fe28
child 1401 7127a4968f33
--- a/usr/src/uts/common/os/logsubr.c	Fri Jan 13 09:07:56 2006 -0800
+++ b/usr/src/uts/common/os/logsubr.c	Fri Jan 13 09:37:07 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -59,7 +59,7 @@
 static stdata_t log_fakestr;
 static id_space_t *log_minorspace;
 static log_t log_backlog;
-static log_t log_conslog;
+static struct kmem_cache *log_cons_cache;	/* log_t cache */
 
 static queue_t *log_recentq;
 static queue_t *log_freeq;
@@ -82,6 +82,8 @@
 	"local4",	"local5",	"local6",	"local7",
 	"unknown"
 };
+static int log_cons_constructor(void *, void *, int);
+static void log_cons_destructor(void *, void *);
 
 /*
  * Get exclusive access to the logging system; this includes all minor
@@ -234,11 +236,10 @@
 	log_backlog.log_zoneid = GLOBAL_ZONEID;
 	log_backlog.log_minor = LOG_BACKLOG;
 
-	/*
-	 * Initialize conslog structure.
-	 */
-	log_conslog.log_zoneid = GLOBAL_ZONEID;
-	log_conslog.log_minor = LOG_CONSMIN;
+	/* Allocate kmem cache for conslog's log structures */
+	log_cons_cache = kmem_cache_create("log_cons_cache",
+	    sizeof (struct log), 0, log_cons_constructor, log_cons_destructor,
+	    NULL, NULL, NULL, 0);
 
 	/*
 	 * Let the logging begin.
@@ -258,10 +259,9 @@
 }
 
 /*
- * Allocate a log device corresponding to supplied device type.  All
- * processes within a given zone that open /dev/conslog share the same
- * device; processes opening /dev/log get distinct devices (if
- * available).
+ * Allocate a log device corresponding to supplied device type.
+ * Both devices are clonable. /dev/log devices are allocated per zone.
+ * /dev/conslog devices are allocated from kmem cache.
  */
 log_t *
 log_alloc(minor_t type)
@@ -270,26 +270,44 @@
 	log_zone_t *lzp;
 	log_t *lp;
 	int i;
+	minor_t minor;
 
 	if (type == LOG_CONSMIN) {
-		/* return the dedicated /dev/conslog device */
-		return (&log_conslog);
-	}
 
-	ASSERT(type == LOG_LOGMIN);
+		/*
+		 * Return a write-only /dev/conslog device.
+		 * No point allocating log_t until there's a free minor number.
+		 */
+		minor = (minor_t)id_alloc(log_minorspace);
+		lp = kmem_cache_alloc(log_cons_cache, KM_SLEEP);
+		lp->log_minor = minor;
+		return (lp);
+	} else {
+		ASSERT(type == LOG_LOGMIN);
 
-	lzp = zone_getspecific(log_zone_key, zptr);
-	ASSERT(lzp != NULL);
+		lzp = zone_getspecific(log_zone_key, zptr);
+		ASSERT(lzp != NULL);
 
-	/* search for an available /dev/log device for the zone */
-	for (i = LOG_LOGMINIDX; i <= LOG_LOGMAXIDX; i++) {
-		lp = &lzp->lz_clones[i];
-		if (lp->log_inuse == 0)
-			break;
+		/* search for an available /dev/log device for the zone */
+		for (i = LOG_LOGMINIDX; i <= LOG_LOGMAXIDX; i++) {
+			lp = &lzp->lz_clones[i];
+			if (lp->log_inuse == 0)
+				break;
+		}
+		if (i > LOG_LOGMAXIDX)
+			lp = NULL;
+		else
+			/* Indicate which device type */
+			lp->log_major = LOG_LOGMIN;
+		return (lp);
 	}
-	if (i > LOG_LOGMAXIDX)
-		lp = NULL;
-	return (lp);
+}
+
+void
+log_free(log_t *lp)
+{
+	id_free(log_minorspace, lp->log_minor);
+	kmem_cache_free(log_cons_cache, lp);
 }
 
 /*
@@ -395,7 +413,6 @@
 		lzp = zone_getspecific(log_zone_key, zptr);
 	}
 	ASSERT(lzp != NULL);
-
 	for (i = LOG_LOGMAXIDX; i >= LOG_LOGMINIDX; i--) {
 		lp = &lzp->lz_clones[i];
 		if (zoneid == GLOBAL_ZONEID && (lp->log_flags & SL_CONSOLE))
@@ -712,3 +729,26 @@
 		}
 	} while ((qlast = q) != qfirst);
 }
+
+/* ARGSUSED */
+static int
+log_cons_constructor(void *buf, void *cdrarg, int kmflags)
+{
+	struct log *lp = buf;
+
+	lp->log_zoneid = GLOBAL_ZONEID;
+	lp->log_major = LOG_CONSMIN;	/* Indicate which device type */
+	lp->log_data = NULL;
+	return (0);
+}
+
+/* ARGSUSED */
+static void
+log_cons_destructor(void *buf, void *cdrarg)
+{
+	struct log *lp = buf;
+
+	ASSERT(lp->log_zoneid == GLOBAL_ZONEID);
+	ASSERT(lp->log_major == LOG_CONSMIN);
+	ASSERT(lp->log_data == NULL);
+}