Patrick McHardy | eecc545 | 2010-10-04 23:24:21 +0200 | [diff] [blame] | 1 | #define S_SIZE (1024 - (sizeof(unsigned int) + 1)) |
| 2 | |
| 3 | struct sbuff { |
| 4 | unsigned int count; |
| 5 | char buf[S_SIZE + 1]; |
| 6 | }; |
| 7 | static struct sbuff emergency, *emergency_ptr = &emergency; |
| 8 | |
Eric Dumazet | ace30d7 | 2012-03-01 02:56:59 +0000 | [diff] [blame] | 9 | static __printf(2, 3) int sb_add(struct sbuff *m, const char *f, ...) |
Patrick McHardy | eecc545 | 2010-10-04 23:24:21 +0200 | [diff] [blame] | 10 | { |
| 11 | va_list args; |
| 12 | int len; |
| 13 | |
| 14 | if (likely(m->count < S_SIZE)) { |
| 15 | va_start(args, f); |
| 16 | len = vsnprintf(m->buf + m->count, S_SIZE - m->count, f, args); |
| 17 | va_end(args); |
| 18 | if (likely(m->count + len < S_SIZE)) { |
| 19 | m->count += len; |
| 20 | return 0; |
| 21 | } |
| 22 | } |
| 23 | m->count = S_SIZE; |
| 24 | printk_once(KERN_ERR KBUILD_MODNAME " please increase S_SIZE\n"); |
| 25 | return -1; |
| 26 | } |
| 27 | |
| 28 | static struct sbuff *sb_open(void) |
| 29 | { |
| 30 | struct sbuff *m = kmalloc(sizeof(*m), GFP_ATOMIC); |
| 31 | |
| 32 | if (unlikely(!m)) { |
| 33 | local_bh_disable(); |
| 34 | do { |
| 35 | m = xchg(&emergency_ptr, NULL); |
| 36 | } while (!m); |
| 37 | } |
| 38 | m->count = 0; |
| 39 | return m; |
| 40 | } |
| 41 | |
| 42 | static void sb_close(struct sbuff *m) |
| 43 | { |
| 44 | m->buf[m->count] = 0; |
| 45 | printk("%s\n", m->buf); |
| 46 | |
| 47 | if (likely(m != &emergency)) |
| 48 | kfree(m); |
| 49 | else { |
| 50 | xchg(&emergency_ptr, m); |
| 51 | local_bh_enable(); |
| 52 | } |
| 53 | } |
| 54 | |