aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 20:15:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 20:15:20 -0400
commit31453a9764f7e2a72a6e2c502ace586e2663a68c (patch)
tree5d4db63de5b4b85d1ffdab4e95a75175a784a10a /lib
parentf9ba5375a8aae4aeea6be15df77e24707a429812 (diff)
parent93ed0e2d07b25aff4db1d61bfbcd1e82074c0ad5 (diff)
Merge branch 'akpm-incoming-1'
* akpm-incoming-1: (176 commits) scripts/checkpatch.pl: add check for declaration of pci_device_id scripts/checkpatch.pl: add warnings for static char that could be static const char checkpatch: version 0.31 checkpatch: statement/block context analyser should look at sanitised lines checkpatch: handle EXPORT_SYMBOL for DEVICE_ATTR and similar checkpatch: clean up structure definition macro handline checkpatch: update copyright dates checkpatch: Add additional attribute #defines checkpatch: check for incorrect permissions checkpatch: ensure kconfig help checks only apply when we are adding help checkpatch: simplify and consolidate "missing space after" checks checkpatch: add check for space after struct, union, and enum checkpatch: returning errno typically should be negative checkpatch: handle casts better fixing false categorisation of : as binary checkpatch: ensure we do not collapse bracketed sections into constants checkpatch: suggest cleanpatch and cleanfile when appropriate checkpatch: types may sit on a line on their own checkpatch: fix regressions in "fix handling of leading spaces" div64_u64(): improve precision on 32bit platforms lib/parser: cleanup match_number() ...
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug17
-rw-r--r--lib/bitmap.c3
-rw-r--r--lib/div64.c52
-rw-r--r--lib/idr.c24
-rw-r--r--lib/list_sort.c172
-rw-r--r--lib/parser.c7
-rw-r--r--lib/percpu_counter.c55
-rw-r--r--lib/vsprintf.c19
8 files changed, 267 insertions, 82 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 69a32664c289..95bda87a3e84 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -317,6 +317,14 @@ config DEBUG_OBJECTS_RCU_HEAD
317 help 317 help
318 Enable this to turn on debugging of RCU list heads (call_rcu() usage). 318 Enable this to turn on debugging of RCU list heads (call_rcu() usage).
319 319
320config DEBUG_OBJECTS_PERCPU_COUNTER
321 bool "Debug percpu counter objects"
322 depends on DEBUG_OBJECTS
323 help
324 If you say Y here, additional code will be inserted into the
325 percpu counter routines to track the life time of percpu counter
326 objects and validate the percpu counter operations.
327
320config DEBUG_OBJECTS_ENABLE_DEFAULT 328config DEBUG_OBJECTS_ENABLE_DEFAULT
321 int "debug_objects bootup default value (0-1)" 329 int "debug_objects bootup default value (0-1)"
322 range 0 1 330 range 0 1
@@ -740,6 +748,15 @@ config DEBUG_LIST
740 748
741 If unsure, say N. 749 If unsure, say N.
742 750
751config TEST_LIST_SORT
752 bool "Linked list sorting test"
753 depends on DEBUG_KERNEL
754 help
755 Enable this to turn on 'list_sort()' function test. This test is
756 executed only once during system boot, so affects only boot time.
757
758 If unsure, say N.
759
743config DEBUG_SG 760config DEBUG_SG
744 bool "Debug SG table operations" 761 bool "Debug SG table operations"
745 depends on DEBUG_KERNEL 762 depends on DEBUG_KERNEL
diff --git a/lib/bitmap.c b/lib/bitmap.c
index ffb78c916ccd..741fae905ae3 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -359,7 +359,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area);
359 359
360#define CHUNKSZ 32 360#define CHUNKSZ 32
361#define nbits_to_hold_value(val) fls(val) 361#define nbits_to_hold_value(val) fls(val)
362#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
363#define BASEDEC 10 /* fancier cpuset lists input in decimal */ 362#define BASEDEC 10 /* fancier cpuset lists input in decimal */
364 363
365/** 364/**
@@ -466,7 +465,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen,
466 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) 465 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
467 return -EOVERFLOW; 466 return -EOVERFLOW;
468 467
469 chunk = (chunk << 4) | unhex(c); 468 chunk = (chunk << 4) | hex_to_bin(c);
470 ndigits++; totaldigits++; 469 ndigits++; totaldigits++;
471 } 470 }
472 if (ndigits == 0) 471 if (ndigits == 0)
diff --git a/lib/div64.c b/lib/div64.c
index a111eb8de9cf..5b4919191778 100644
--- a/lib/div64.c
+++ b/lib/div64.c
@@ -77,26 +77,58 @@ s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
77EXPORT_SYMBOL(div_s64_rem); 77EXPORT_SYMBOL(div_s64_rem);
78#endif 78#endif
79 79
80/* 64bit divisor, dividend and result. dynamic precision */ 80/**
81 * div64_u64 - unsigned 64bit divide with 64bit divisor
82 * @dividend: 64bit dividend
83 * @divisor: 64bit divisor
84 *
85 * This implementation is a modified version of the algorithm proposed
86 * by the book 'Hacker's Delight'. The original source and full proof
87 * can be found here and is available for use without restriction.
88 *
89 * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c'
90 */
81#ifndef div64_u64 91#ifndef div64_u64
82u64 div64_u64(u64 dividend, u64 divisor) 92u64 div64_u64(u64 dividend, u64 divisor)
83{ 93{
84 u32 high, d; 94 u32 high = divisor >> 32;
95 u64 quot;
85 96
86 high = divisor >> 32; 97 if (high == 0) {
87 if (high) { 98 quot = div_u64(dividend, divisor);
88 unsigned int shift = fls(high); 99 } else {
100 int n = 1 + fls(high);
101 quot = div_u64(dividend >> n, divisor >> n);
89 102
90 d = divisor >> shift; 103 if (quot != 0)
91 dividend >>= shift; 104 quot--;
92 } else 105 if ((dividend - quot * divisor) >= divisor)
93 d = divisor; 106 quot++;
107 }
94 108
95 return div_u64(dividend, d); 109 return quot;
96} 110}
97EXPORT_SYMBOL(div64_u64); 111EXPORT_SYMBOL(div64_u64);
98#endif 112#endif
99 113
114/**
115 * div64_s64 - signed 64bit divide with 64bit divisor
116 * @dividend: 64bit dividend
117 * @divisor: 64bit divisor
118 */
119#ifndef div64_s64
120s64 div64_s64(s64 dividend, s64 divisor)
121{
122 s64 quot, t;
123
124 quot = div64_u64(abs64(dividend), abs64(divisor));
125 t = (dividend ^ divisor) >> 63;
126
127 return (quot ^ t) - t;
128}
129EXPORT_SYMBOL(div64_s64);
130#endif
131
100#endif /* BITS_PER_LONG == 32 */ 132#endif /* BITS_PER_LONG == 32 */
101 133
102/* 134/*
diff --git a/lib/idr.c b/lib/idr.c
index 5e0966be0f7c..e35850d3004a 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -110,9 +110,10 @@ static void idr_mark_full(struct idr_layer **pa, int id)
110 * @idp: idr handle 110 * @idp: idr handle
111 * @gfp_mask: memory allocation flags 111 * @gfp_mask: memory allocation flags
112 * 112 *
113 * This function should be called prior to locking and calling the 113 * This function should be called prior to calling the idr_get_new* functions.
114 * idr_get_new* functions. It preallocates enough memory to satisfy 114 * It preallocates enough memory to satisfy the worst possible allocation. The
115 * the worst possible allocation. 115 * caller should pass in GFP_KERNEL if possible. This of course requires that
116 * no spinning locks be held.
116 * 117 *
117 * If the system is REALLY out of memory this function returns 0, 118 * If the system is REALLY out of memory this function returns 0,
118 * otherwise 1. 119 * otherwise 1.
@@ -290,9 +291,11 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
290 * This is the allocate id function. It should be called with any 291 * This is the allocate id function. It should be called with any
291 * required locks. 292 * required locks.
292 * 293 *
293 * If memory is required, it will return -EAGAIN, you should unlock 294 * If allocation from IDR's private freelist fails, idr_get_new_above() will
294 * and go back to the idr_pre_get() call. If the idr is full, it will 295 * return -EAGAIN. The caller should retry the idr_pre_get() call to refill
295 * return -ENOSPC. 296 * IDR's preallocation and then retry the idr_get_new_above() call.
297 *
298 * If the idr is full idr_get_new_above() will return -ENOSPC.
296 * 299 *
297 * @id returns a value in the range @starting_id ... 0x7fffffff 300 * @id returns a value in the range @starting_id ... 0x7fffffff
298 */ 301 */
@@ -318,12 +321,11 @@ EXPORT_SYMBOL(idr_get_new_above);
318 * @ptr: pointer you want associated with the id 321 * @ptr: pointer you want associated with the id
319 * @id: pointer to the allocated handle 322 * @id: pointer to the allocated handle
320 * 323 *
321 * This is the allocate id function. It should be called with any 324 * If allocation from IDR's private freelist fails, idr_get_new_above() will
322 * required locks. 325 * return -EAGAIN. The caller should retry the idr_pre_get() call to refill
326 * IDR's preallocation and then retry the idr_get_new_above() call.
323 * 327 *
324 * If memory is required, it will return -EAGAIN, you should unlock 328 * If the idr is full idr_get_new_above() will return -ENOSPC.
325 * and go back to the idr_pre_get() call. If the idr is full, it will
326 * return -ENOSPC.
327 * 329 *
328 * @id returns a value in the range 0 ... 0x7fffffff 330 * @id returns a value in the range 0 ... 0x7fffffff
329 */ 331 */
diff --git a/lib/list_sort.c b/lib/list_sort.c
index a7616fa3162e..d7325c6b103f 100644
--- a/lib/list_sort.c
+++ b/lib/list_sort.c
@@ -141,77 +141,151 @@ void list_sort(void *priv, struct list_head *head,
141} 141}
142EXPORT_SYMBOL(list_sort); 142EXPORT_SYMBOL(list_sort);
143 143
144#ifdef DEBUG_LIST_SORT 144#ifdef CONFIG_TEST_LIST_SORT
145
146#include <linux/random.h>
147
148/*
149 * The pattern of set bits in the list length determines which cases
150 * are hit in list_sort().
151 */
152#define TEST_LIST_LEN (512+128+2) /* not including head */
153
154#define TEST_POISON1 0xDEADBEEF
155#define TEST_POISON2 0xA324354C
156
145struct debug_el { 157struct debug_el {
146 struct list_head l_h; 158 unsigned int poison1;
159 struct list_head list;
160 unsigned int poison2;
147 int value; 161 int value;
148 unsigned serial; 162 unsigned serial;
149}; 163};
150 164
151static int cmp(void *priv, struct list_head *a, struct list_head *b) 165/* Array, containing pointers to all elements in the test list */
166static struct debug_el **elts __initdata;
167
168static int __init check(struct debug_el *ela, struct debug_el *elb)
152{ 169{
153 return container_of(a, struct debug_el, l_h)->value 170 if (ela->serial >= TEST_LIST_LEN) {
154 - container_of(b, struct debug_el, l_h)->value; 171 printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
172 ela->serial);
173 return -EINVAL;
174 }
175 if (elb->serial >= TEST_LIST_LEN) {
176 printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
177 elb->serial);
178 return -EINVAL;
179 }
180 if (elts[ela->serial] != ela || elts[elb->serial] != elb) {
181 printk(KERN_ERR "list_sort_test: error: phantom element\n");
182 return -EINVAL;
183 }
184 if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) {
185 printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
186 ela->poison1, ela->poison2);
187 return -EINVAL;
188 }
189 if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) {
190 printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
191 elb->poison1, elb->poison2);
192 return -EINVAL;
193 }
194 return 0;
155} 195}
156 196
157/* 197static int __init cmp(void *priv, struct list_head *a, struct list_head *b)
158 * The pattern of set bits in the list length determines which cases 198{
159 * are hit in list_sort(). 199 struct debug_el *ela, *elb;
160 */ 200
161#define LIST_SORT_TEST_LENGTH (512+128+2) /* not including head */ 201 ela = container_of(a, struct debug_el, list);
202 elb = container_of(b, struct debug_el, list);
203
204 check(ela, elb);
205 return ela->value - elb->value;
206}
162 207
163static int __init list_sort_test(void) 208static int __init list_sort_test(void)
164{ 209{
165 int i, r = 1, count; 210 int i, count = 1, err = -EINVAL;
166 struct list_head *head = kmalloc(sizeof(*head), GFP_KERNEL); 211 struct debug_el *el;
167 struct list_head *cur; 212 struct list_head *cur, *tmp;
213 LIST_HEAD(head);
214
215 printk(KERN_DEBUG "list_sort_test: start testing list_sort()\n");
168 216
169 printk(KERN_WARNING "testing list_sort()\n"); 217 elts = kmalloc(sizeof(void *) * TEST_LIST_LEN, GFP_KERNEL);
218 if (!elts) {
219 printk(KERN_ERR "list_sort_test: error: cannot allocate "
220 "memory\n");
221 goto exit;
222 }
170 223
171 cur = head; 224 for (i = 0; i < TEST_LIST_LEN; i++) {
172 for (i = 0; i < LIST_SORT_TEST_LENGTH; i++) { 225 el = kmalloc(sizeof(*el), GFP_KERNEL);
173 struct debug_el *el = kmalloc(sizeof(*el), GFP_KERNEL); 226 if (!el) {
174 BUG_ON(!el); 227 printk(KERN_ERR "list_sort_test: error: cannot "
228 "allocate memory\n");
229 goto exit;
230 }
175 /* force some equivalencies */ 231 /* force some equivalencies */
176 el->value = (r = (r * 725861) % 6599) % (LIST_SORT_TEST_LENGTH/3); 232 el->value = random32() % (TEST_LIST_LEN/3);
177 el->serial = i; 233 el->serial = i;
178 234 el->poison1 = TEST_POISON1;
179 el->l_h.prev = cur; 235 el->poison2 = TEST_POISON2;
180 cur->next = &el->l_h; 236 elts[i] = el;
181 cur = cur->next; 237 list_add_tail(&el->list, &head);
182 } 238 }
183 head->prev = cur;
184 239
185 list_sort(NULL, head, cmp); 240 list_sort(NULL, &head, cmp);
241
242 for (cur = head.next; cur->next != &head; cur = cur->next) {
243 struct debug_el *el1;
244 int cmp_result;
186 245
187 count = 1;
188 for (cur = head->next; cur->next != head; cur = cur->next) {
189 struct debug_el *el = container_of(cur, struct debug_el, l_h);
190 int cmp_result = cmp(NULL, cur, cur->next);
191 if (cur->next->prev != cur) { 246 if (cur->next->prev != cur) {
192 printk(KERN_EMERG "list_sort() returned " 247 printk(KERN_ERR "list_sort_test: error: list is "
193 "a corrupted list!\n"); 248 "corrupted\n");
194 return 1; 249 goto exit;
195 } else if (cmp_result > 0) { 250 }
196 printk(KERN_EMERG "list_sort() failed to sort!\n"); 251
197 return 1; 252 cmp_result = cmp(NULL, cur, cur->next);
198 } else if (cmp_result == 0 && 253 if (cmp_result > 0) {
199 el->serial >= container_of(cur->next, 254 printk(KERN_ERR "list_sort_test: error: list is not "
200 struct debug_el, l_h)->serial) { 255 "sorted\n");
201 printk(KERN_EMERG "list_sort() failed to preserve order" 256 goto exit;
202 " of equivalent elements!\n"); 257 }
203 return 1; 258
259 el = container_of(cur, struct debug_el, list);
260 el1 = container_of(cur->next, struct debug_el, list);
261 if (cmp_result == 0 && el->serial >= el1->serial) {
262 printk(KERN_ERR "list_sort_test: error: order of "
263 "equivalent elements not preserved\n");
264 goto exit;
265 }
266
267 if (check(el, el1)) {
268 printk(KERN_ERR "list_sort_test: error: element check "
269 "failed\n");
270 goto exit;
204 } 271 }
205 kfree(cur->prev);
206 count++; 272 count++;
207 } 273 }
208 kfree(cur); 274
209 if (count != LIST_SORT_TEST_LENGTH) { 275 if (count != TEST_LIST_LEN) {
210 printk(KERN_EMERG "list_sort() returned list of" 276 printk(KERN_ERR "list_sort_test: error: bad list length %d",
211 "different length!\n"); 277 count);
212 return 1; 278 goto exit;
213 } 279 }
214 return 0; 280
281 err = 0;
282exit:
283 kfree(elts);
284 list_for_each_safe(cur, tmp, &head) {
285 list_del(cur);
286 kfree(container_of(cur, struct debug_el, list));
287 }
288 return err;
215} 289}
216module_init(list_sort_test); 290module_init(list_sort_test);
217#endif 291#endif /* CONFIG_TEST_LIST_SORT */
diff --git a/lib/parser.c b/lib/parser.c
index fb34977246bb..6e89eca5cca0 100644
--- a/lib/parser.c
+++ b/lib/parser.c
@@ -128,12 +128,13 @@ static int match_number(substring_t *s, int *result, int base)
128 char *endp; 128 char *endp;
129 char *buf; 129 char *buf;
130 int ret; 130 int ret;
131 size_t len = s->to - s->from;
131 132
132 buf = kmalloc(s->to - s->from + 1, GFP_KERNEL); 133 buf = kmalloc(len + 1, GFP_KERNEL);
133 if (!buf) 134 if (!buf)
134 return -ENOMEM; 135 return -ENOMEM;
135 memcpy(buf, s->from, s->to - s->from); 136 memcpy(buf, s->from, len);
136 buf[s->to - s->from] = '\0'; 137 buf[len] = '\0';
137 *result = simple_strtol(buf, &endp, base); 138 *result = simple_strtol(buf, &endp, base);
138 ret = 0; 139 ret = 0;
139 if (endp == buf) 140 if (endp == buf)
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index ec9048e74f44..604678d7d06d 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -8,10 +8,53 @@
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/cpu.h> 9#include <linux/cpu.h>
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/debugobjects.h>
11 12
12static LIST_HEAD(percpu_counters); 13static LIST_HEAD(percpu_counters);
13static DEFINE_MUTEX(percpu_counters_lock); 14static DEFINE_MUTEX(percpu_counters_lock);
14 15
16#ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER
17
18static struct debug_obj_descr percpu_counter_debug_descr;
19
20static int percpu_counter_fixup_free(void *addr, enum debug_obj_state state)
21{
22 struct percpu_counter *fbc = addr;
23
24 switch (state) {
25 case ODEBUG_STATE_ACTIVE:
26 percpu_counter_destroy(fbc);
27 debug_object_free(fbc, &percpu_counter_debug_descr);
28 return 1;
29 default:
30 return 0;
31 }
32}
33
34static struct debug_obj_descr percpu_counter_debug_descr = {
35 .name = "percpu_counter",
36 .fixup_free = percpu_counter_fixup_free,
37};
38
39static inline void debug_percpu_counter_activate(struct percpu_counter *fbc)
40{
41 debug_object_init(fbc, &percpu_counter_debug_descr);
42 debug_object_activate(fbc, &percpu_counter_debug_descr);
43}
44
45static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc)
46{
47 debug_object_deactivate(fbc, &percpu_counter_debug_descr);
48 debug_object_free(fbc, &percpu_counter_debug_descr);
49}
50
51#else /* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */
52static inline void debug_percpu_counter_activate(struct percpu_counter *fbc)
53{ }
54static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc)
55{ }
56#endif /* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */
57
15void percpu_counter_set(struct percpu_counter *fbc, s64 amount) 58void percpu_counter_set(struct percpu_counter *fbc, s64 amount)
16{ 59{
17 int cpu; 60 int cpu;
@@ -30,9 +73,9 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
30{ 73{
31 s64 count; 74 s64 count;
32 s32 *pcount; 75 s32 *pcount;
33 int cpu = get_cpu();
34 76
35 pcount = per_cpu_ptr(fbc->counters, cpu); 77 preempt_disable();
78 pcount = this_cpu_ptr(fbc->counters);
36 count = *pcount + amount; 79 count = *pcount + amount;
37 if (count >= batch || count <= -batch) { 80 if (count >= batch || count <= -batch) {
38 spin_lock(&fbc->lock); 81 spin_lock(&fbc->lock);
@@ -42,7 +85,7 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
42 } else { 85 } else {
43 *pcount = count; 86 *pcount = count;
44 } 87 }
45 put_cpu(); 88 preempt_enable();
46} 89}
47EXPORT_SYMBOL(__percpu_counter_add); 90EXPORT_SYMBOL(__percpu_counter_add);
48 91
@@ -75,7 +118,11 @@ int __percpu_counter_init(struct percpu_counter *fbc, s64 amount,
75 fbc->counters = alloc_percpu(s32); 118 fbc->counters = alloc_percpu(s32);
76 if (!fbc->counters) 119 if (!fbc->counters)
77 return -ENOMEM; 120 return -ENOMEM;
121
122 debug_percpu_counter_activate(fbc);
123
78#ifdef CONFIG_HOTPLUG_CPU 124#ifdef CONFIG_HOTPLUG_CPU
125 INIT_LIST_HEAD(&fbc->list);
79 mutex_lock(&percpu_counters_lock); 126 mutex_lock(&percpu_counters_lock);
80 list_add(&fbc->list, &percpu_counters); 127 list_add(&fbc->list, &percpu_counters);
81 mutex_unlock(&percpu_counters_lock); 128 mutex_unlock(&percpu_counters_lock);
@@ -89,6 +136,8 @@ void percpu_counter_destroy(struct percpu_counter *fbc)
89 if (!fbc->counters) 136 if (!fbc->counters)
90 return; 137 return;
91 138
139 debug_percpu_counter_deactivate(fbc);
140
92#ifdef CONFIG_HOTPLUG_CPU 141#ifdef CONFIG_HOTPLUG_CPU
93 mutex_lock(&percpu_counters_lock); 142 mutex_lock(&percpu_counters_lock);
94 list_del(&fbc->list); 143 list_del(&fbc->list);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 7af9d841c43b..c150d3dafff4 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -988,8 +988,15 @@ static noinline_for_stack
988char *pointer(const char *fmt, char *buf, char *end, void *ptr, 988char *pointer(const char *fmt, char *buf, char *end, void *ptr,
989 struct printf_spec spec) 989 struct printf_spec spec)
990{ 990{
991 if (!ptr) 991 if (!ptr) {
992 /*
993 * Print (null) with the same width as a pointer so it makes
994 * tabular output look nice.
995 */
996 if (spec.field_width == -1)
997 spec.field_width = 2 * sizeof(void *);
992 return string(buf, end, "(null)", spec); 998 return string(buf, end, "(null)", spec);
999 }
993 1000
994 switch (*fmt) { 1001 switch (*fmt) {
995 case 'F': 1002 case 'F':
@@ -1031,7 +1038,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1031 } 1038 }
1032 spec.flags |= SMALL; 1039 spec.flags |= SMALL;
1033 if (spec.field_width == -1) { 1040 if (spec.field_width == -1) {
1034 spec.field_width = 2*sizeof(void *); 1041 spec.field_width = 2 * sizeof(void *);
1035 spec.flags |= ZEROPAD; 1042 spec.flags |= ZEROPAD;
1036 } 1043 }
1037 spec.base = 16; 1044 spec.base = 16;
@@ -1497,7 +1504,7 @@ EXPORT_SYMBOL(snprintf);
1497 * @...: Arguments for the format string 1504 * @...: Arguments for the format string
1498 * 1505 *
1499 * The return value is the number of characters written into @buf not including 1506 * The return value is the number of characters written into @buf not including
1500 * the trailing '\0'. If @size is <= 0 the function returns 0. 1507 * the trailing '\0'. If @size is == 0 the function returns 0.
1501 */ 1508 */
1502 1509
1503int scnprintf(char *buf, size_t size, const char *fmt, ...) 1510int scnprintf(char *buf, size_t size, const char *fmt, ...)
@@ -1509,7 +1516,11 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...)
1509 i = vsnprintf(buf, size, fmt, args); 1516 i = vsnprintf(buf, size, fmt, args);
1510 va_end(args); 1517 va_end(args);
1511 1518
1512 return (i >= size) ? (size - 1) : i; 1519 if (likely(i < size))
1520 return i;
1521 if (size != 0)
1522 return size - 1;
1523 return 0;
1513} 1524}
1514EXPORT_SYMBOL(scnprintf); 1525EXPORT_SYMBOL(scnprintf);
1515 1526