summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorns92644 <none@none>2005-11-01 07:09:19 -0800
committerns92644 <none@none>2005-11-01 07:09:19 -0800
commitcf904b458260fa01e28bbe096ba36e34b959956f (patch)
tree850de99e87fdf7136d9f65cf2d7ac07d4f9ccafc
parenta2b4fdf6f9770a7725bfd41e7b3a92253e26645c (diff)
downloadillumos-gate-cf904b458260fa01e28bbe096ba36e34b959956f.tar.gz
6266921 /dev/conslog should be clonable
-rw-r--r--usr/src/uts/common/io/log.c19
-rw-r--r--usr/src/uts/common/os/logsubr.c98
-rw-r--r--usr/src/uts/common/sys/log.h8
3 files changed, 88 insertions, 37 deletions
diff --git a/usr/src/uts/common/io/log.c b/usr/src/uts/common/io/log.c
index 8725c97ffb..cc68e13b4f 100644
--- a/usr/src/uts/common/io/log.c
+++ b/usr/src/uts/common/io/log.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -87,11 +87,10 @@ log_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
}
/*
- * log_open can be called for one of two devices, /dev/conslog or
- * /dev/log. In the case of /dev/conslog it returns the global
- * console device (i.e., multiple opens return the same device), while
- * for /dev/log a new device is created for each open (up to a limit
- * of 16 per zone). Most of the allocation details are handled in
+ * log_open can be called for either /dev/log or dev/conslog.
+ * In both cases a new minor device is created. Up to 16 /dev/log devices
+ * may be created per zone. Up to LOG_NUMCONS global /dev/conslog
+ * devices may be created. Most of the allocation details are handled in
* log_alloc.
*/
/* ARGSUSED */
@@ -105,7 +104,7 @@ log_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cr)
return (ENXIO);
switch (minor = getminor(*devp)) {
- case LOG_CONSMIN: /* normal open of /dev/conslog */
+ case LOG_CONSMIN: /* clone open of /dev/conslog */
if (flag & FREAD)
return (EINVAL); /* write-only device */
if (q->q_ptr)
@@ -143,6 +142,8 @@ log_close(queue_t *q, int flag, cred_t *cr)
log_update(lp, NULL, 0, NULL);
freemsg(lp->log_data);
lp->log_data = NULL;
+ if (lp->log_major == LOG_CONSMIN)
+ log_free(lp);
q->q_ptr = NULL;
WR(q)->q_ptr = NULL;
@@ -181,8 +182,8 @@ log_wput(queue_t *q, mblk_t *mp)
case M_IOCTL:
iocp = (struct iocblk *)mp->b_rptr;
- if (lp->log_minor <= LOG_LOGMIN) {
- /* not a cloned dev_t */
+ if (lp->log_major != LOG_LOGMIN) {
+ /* write-only device */
miocnak(q, mp, 0, EINVAL);
return (0);
}
diff --git a/usr/src/uts/common/os/logsubr.c b/usr/src/uts/common/os/logsubr.c
index 00df4a09bb..31a6663e89 100644
--- a/usr/src/uts/common/os/logsubr.c
+++ b/usr/src/uts/common/os/logsubr.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -59,7 +59,8 @@ static int log_seq_no[SL_CONSOLE + 1];
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 vmem_t *log_cons_minor_arena; /* Arena for device minors */
static queue_t *log_recentq;
static queue_t *log_freeq;
@@ -82,6 +83,8 @@ static char log_fac[LOG_NFACILITIES + 1][LOG_FACSIZE] = {
"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 +237,15 @@ log_init(void)
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 integer space for conslog's minor numbers */
+ log_cons_minor_arena = vmem_create("log_cons_minor", (void *)1,
+ LOG_NUMCONS, 1, NULL, NULL, NULL, 0,
+ VM_SLEEP | VMC_IDENTIFIER);
+
+ /* 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 +265,10 @@ log_init(void)
}
/*
- * 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, with minor numbers
+ * supplied from a vmem arena.
*/
log_t *
log_alloc(minor_t type)
@@ -270,26 +277,45 @@ log_alloc(minor_t type)
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)(uintptr_t)
+ vmem_alloc(log_cons_minor_arena, 1, VM_SLEEP);
+ 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;
+ lp->log_major = LOG_LOGMIN;
+ return (lp);
}
- if (i > LOG_LOGMAXIDX)
- lp = NULL;
- return (lp);
+}
+
+void
+log_free(log_t *lp)
+{
+ /* Return minor number to the pool */
+ vmem_free(log_cons_minor_arena, (void *)(uintptr_t)lp->log_minor, 1);
+ /* Return log to the cache */
+ kmem_cache_free(log_cons_cache, lp);
}
/*
@@ -395,7 +421,6 @@ log_update(log_t *target, queue_t *q, short flags, log_filter_t *filter)
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 +737,24 @@ log_printq(queue_t *qfirst)
}
} 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;
+ 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);
+}
diff --git a/usr/src/uts/common/sys/log.h b/usr/src/uts/common/sys/log.h
index 1ae7b71a2a..d49870d625 100644
--- a/usr/src/uts/common/sys/log.h
+++ b/usr/src/uts/common/sys/log.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,12 +41,13 @@ extern "C" {
#endif
#define LOG_CONSMIN 0 /* /dev/conslog minor */
-#define LOG_LOGMIN 5 /* /dev/log clone-open minor */
+#define LOG_LOGMIN 5 /* /dev/log minor */
#define LOG_BACKLOG LOG_LOGMIN /* console backlog queue */
#define LOG_LOGMINIDX 0 /* index of smallest /dev/log clone */
#define LOG_LOGMAXIDX 15 /* up to 16 /dev/log clones */
#define LOG_NUMCLONES (LOG_LOGMAXIDX - LOG_LOGMINIDX + 1)
+#define LOG_NUMCONS 1024 /* up to 1024 /dev/conslog clones */
#define LOG_MID 44 /* module ID */
#define LOG_MINPS 0 /* min packet size */
@@ -70,9 +71,11 @@ struct log {
short log_inuse; /* is this log device open? */
int log_overflow; /* messages lost due to QFULL */
zoneid_t log_zoneid; /* zone id of log */
+ major_t log_major; /* major number of associated device */
minor_t log_minor; /* minor number of associated device */
};
+/* Array of /dev/log minor devices */
typedef struct log_zone {
log_t lz_clones[LOG_NUMCLONES];
uint16_t lz_active; /* active types (OR of all log_flags fields) */
@@ -112,6 +115,7 @@ extern void log_sendmsg(mblk_t *, zoneid_t);
extern void log_flushq(queue_t *);
extern void log_printq(queue_t *);
extern log_t *log_alloc(minor_t);
+extern void log_free(log_t *);
#endif /* _KERNEL */