Print this page
11927 Log, or optionally panic, on zero-length kmem allocations
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Jason King <jason.brian.king@gmail.com>

*** 1009,1025 **** --- 1009,1034 ---- uint32_t kmem_mtbf = 0; /* mean time between failures [default: off] */ size_t kmem_transaction_log_size; /* transaction log size [2% of memory] */ size_t kmem_content_log_size; /* content log size [2% of memory] */ size_t kmem_failure_log_size; /* failure log [4 pages per CPU] */ size_t kmem_slab_log_size; /* slab create log [4 pages per CPU] */ + size_t kmem_zerosized_log_size; /* zero-sized log [4 pages per CPU] */ size_t kmem_content_maxsave = 256; /* KMF_CONTENTS max bytes to log */ size_t kmem_lite_minsize = 0; /* minimum buffer size for KMF_LITE */ size_t kmem_lite_maxalign = 1024; /* maximum buffer alignment for KMF_LITE */ int kmem_lite_pcs = 4; /* number of PCs to store in KMF_LITE mode */ size_t kmem_maxverify; /* maximum bytes to inspect in debug routines */ size_t kmem_minfirewall; /* hardware-enforced redzone threshold */ + #ifdef DEBUG + int kmem_warn_zerosized = 1; /* whether to warn on zero-sized KM_SLEEP */ + #else + int kmem_warn_zerosized = 0; /* whether to warn on zero-sized KM_SLEEP */ + #endif + + int kmem_panic_zerosized = 0; /* whether to panic on zero-sized KM_SLEEP */ + #ifdef _LP64 size_t kmem_max_cached = KMEM_BIG_MAXBUF; /* maximum kmem_alloc cache */ #else size_t kmem_max_cached = KMEM_BIG_MAXBUF_32BIT; /* maximum kmem_alloc cache */ #endif
*** 1049,1058 **** --- 1058,1069 ---- static vmem_t *kmem_va_arena; static vmem_t *kmem_default_arena; static vmem_t *kmem_firewall_va_arena; static vmem_t *kmem_firewall_arena; + static int kmem_zerosized; /* # of zero-sized allocs */ + /* * kmem slab consolidator thresholds (tunables) */ size_t kmem_frag_minslabs = 101; /* minimum total slabs */ size_t kmem_frag_numer = 1; /* free buffers (numerator) */
*** 1096,1105 **** --- 1107,1117 ---- kmem_log_header_t *kmem_transaction_log; kmem_log_header_t *kmem_content_log; kmem_log_header_t *kmem_failure_log; kmem_log_header_t *kmem_slab_log; + kmem_log_header_t *kmem_zerosized_log; static int kmem_lite_count; /* # of PCs in kmem_buftag_lite_t */ #define KMEM_BUFTAG_LITE_ENTER(bt, count, caller) \ if ((count) > 0) { \
*** 2851,2863 **** kmem_big_alloc_table_max) { cp = kmem_big_alloc_table[index]; /* fall through to kmem_cache_alloc() */ } else { ! if (size == 0) return (NULL); buf = vmem_alloc(kmem_oversize_arena, size, kmflag & KM_VMFLAGS); if (buf == NULL) kmem_log_event(kmem_failure_log, NULL, NULL, (void *)size); --- 2863,2900 ---- kmem_big_alloc_table_max) { cp = kmem_big_alloc_table[index]; /* fall through to kmem_cache_alloc() */ } else { ! if (size == 0) { ! if (kmflag != KM_SLEEP && !(kmflag & KM_PANIC)) return (NULL); + /* + * If this is a sleeping allocation or one that has + * been specified to panic on allocation failure, we + * consider it to be deprecated behavior to allocate + * 0 bytes. If we have been configured to panic under + * this condition, we panic; if to warn, we warn -- and + * regardless, we log to the kmem_zerosized_log that + * that this condition has occurred (which gives us + * enough information to be able to debug it). + */ + if (kmem_panic && kmem_panic_zerosized) + panic("attempted to kmem_alloc() size of 0"); + + if (kmem_warn_zerosized) { + cmn_err(CE_WARN, "kmem_alloc(): sleeping " + "allocation with size of 0; " + "see kmem_zerosized_log for details"); + } + + kmem_log_event(kmem_zerosized_log, NULL, NULL, NULL); + + return (NULL); + } + buf = vmem_alloc(kmem_oversize_arena, size, kmflag & KM_VMFLAGS); if (buf == NULL) kmem_log_event(kmem_failure_log, NULL, NULL, (void *)size);
*** 4395,4406 **** kmem_content_log_size = kmem_maxavail() / 50; kmem_content_log = kmem_log_init(kmem_content_log_size); } kmem_failure_log = kmem_log_init(kmem_failure_log_size); - kmem_slab_log = kmem_log_init(kmem_slab_log_size); /* * Initialize STREAMS message caches so allocb() is available. * This allows us to initialize the logging framework (cmn_err(9F), * strlog(9F), etc) so we can start recording messages. --- 4432,4443 ---- kmem_content_log_size = kmem_maxavail() / 50; kmem_content_log = kmem_log_init(kmem_content_log_size); } kmem_failure_log = kmem_log_init(kmem_failure_log_size); kmem_slab_log = kmem_log_init(kmem_slab_log_size); + kmem_zerosized_log = kmem_log_init(kmem_zerosized_log_size); /* * Initialize STREAMS message caches so allocb() is available. * This allows us to initialize the logging framework (cmn_err(9F), * strlog(9F), etc) so we can start recording messages.