diff options
author | ns92644 <none@none> | 2005-11-01 07:09:19 -0800 |
---|---|---|
committer | ns92644 <none@none> | 2005-11-01 07:09:19 -0800 |
commit | cf904b458260fa01e28bbe096ba36e34b959956f (patch) | |
tree | 850de99e87fdf7136d9f65cf2d7ac07d4f9ccafc | |
parent | a2b4fdf6f9770a7725bfd41e7b3a92253e26645c (diff) | |
download | illumos-gate-cf904b458260fa01e28bbe096ba36e34b959956f.tar.gz |
6266921 /dev/conslog should be clonable
-rw-r--r-- | usr/src/uts/common/io/log.c | 19 | ||||
-rw-r--r-- | usr/src/uts/common/os/logsubr.c | 98 | ||||
-rw-r--r-- | usr/src/uts/common/sys/log.h | 8 |
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 */ |