aboutsummaryrefslogtreecommitdiffstats
path: root/lib/list_sort.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/list_sort.c')
-rw-r--r--lib/list_sort.c71
1 files changed, 35 insertions, 36 deletions
diff --git a/lib/list_sort.c b/lib/list_sort.c
index 1183fa70a44d..12bcba1c8612 100644
--- a/lib/list_sort.c
+++ b/lib/list_sort.c
@@ -1,3 +1,6 @@
1
2#define pr_fmt(fmt) "list_sort_test: " fmt
3
1#include <linux/kernel.h> 4#include <linux/kernel.h>
2#include <linux/module.h> 5#include <linux/module.h>
3#include <linux/list_sort.h> 6#include <linux/list_sort.h>
@@ -47,6 +50,7 @@ static void merge_and_restore_back_links(void *priv,
47 struct list_head *a, struct list_head *b) 50 struct list_head *a, struct list_head *b)
48{ 51{
49 struct list_head *tail = head; 52 struct list_head *tail = head;
53 u8 count = 0;
50 54
51 while (a && b) { 55 while (a && b) {
52 /* if equal, take 'a' -- important for sort stability */ 56 /* if equal, take 'a' -- important for sort stability */
@@ -70,7 +74,8 @@ static void merge_and_restore_back_links(void *priv,
70 * element comparison is needed, so the client's cmp() 74 * element comparison is needed, so the client's cmp()
71 * routine can invoke cond_resched() periodically. 75 * routine can invoke cond_resched() periodically.
72 */ 76 */
73 (*cmp)(priv, tail->next, tail->next); 77 if (unlikely(!(++count)))
78 (*cmp)(priv, tail->next, tail->next);
74 79
75 tail->next->prev = tail; 80 tail->next->prev = tail;
76 tail = tail->next; 81 tail = tail->next;
@@ -123,9 +128,7 @@ void list_sort(void *priv, struct list_head *head,
123 } 128 }
124 if (lev > max_lev) { 129 if (lev > max_lev) {
125 if (unlikely(lev >= ARRAY_SIZE(part)-1)) { 130 if (unlikely(lev >= ARRAY_SIZE(part)-1)) {
126 printk_once(KERN_DEBUG "list passed to" 131 printk_once(KERN_DEBUG "list too long for efficiency\n");
127 " list_sort() too long for"
128 " efficiency\n");
129 lev--; 132 lev--;
130 } 133 }
131 max_lev = lev; 134 max_lev = lev;
@@ -168,27 +171,25 @@ static struct debug_el **elts __initdata;
168static int __init check(struct debug_el *ela, struct debug_el *elb) 171static int __init check(struct debug_el *ela, struct debug_el *elb)
169{ 172{
170 if (ela->serial >= TEST_LIST_LEN) { 173 if (ela->serial >= TEST_LIST_LEN) {
171 printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n", 174 pr_err("error: incorrect serial %d\n", ela->serial);
172 ela->serial);
173 return -EINVAL; 175 return -EINVAL;
174 } 176 }
175 if (elb->serial >= TEST_LIST_LEN) { 177 if (elb->serial >= TEST_LIST_LEN) {
176 printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n", 178 pr_err("error: incorrect serial %d\n", elb->serial);
177 elb->serial);
178 return -EINVAL; 179 return -EINVAL;
179 } 180 }
180 if (elts[ela->serial] != ela || elts[elb->serial] != elb) { 181 if (elts[ela->serial] != ela || elts[elb->serial] != elb) {
181 printk(KERN_ERR "list_sort_test: error: phantom element\n"); 182 pr_err("error: phantom element\n");
182 return -EINVAL; 183 return -EINVAL;
183 } 184 }
184 if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) { 185 if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) {
185 printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n", 186 pr_err("error: bad poison: %#x/%#x\n",
186 ela->poison1, ela->poison2); 187 ela->poison1, ela->poison2);
187 return -EINVAL; 188 return -EINVAL;
188 } 189 }
189 if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) { 190 if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) {
190 printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n", 191 pr_err("error: bad poison: %#x/%#x\n",
191 elb->poison1, elb->poison2); 192 elb->poison1, elb->poison2);
192 return -EINVAL; 193 return -EINVAL;
193 } 194 }
194 return 0; 195 return 0;
@@ -207,25 +208,23 @@ static int __init cmp(void *priv, struct list_head *a, struct list_head *b)
207 208
208static int __init list_sort_test(void) 209static int __init list_sort_test(void)
209{ 210{
210 int i, count = 1, err = -EINVAL; 211 int i, count = 1, err = -ENOMEM;
211 struct debug_el *el; 212 struct debug_el *el;
212 struct list_head *cur, *tmp; 213 struct list_head *cur;
213 LIST_HEAD(head); 214 LIST_HEAD(head);
214 215
215 printk(KERN_DEBUG "list_sort_test: start testing list_sort()\n"); 216 pr_debug("start testing list_sort()\n");
216 217
217 elts = kmalloc(sizeof(void *) * TEST_LIST_LEN, GFP_KERNEL); 218 elts = kcalloc(TEST_LIST_LEN, sizeof(*elts), GFP_KERNEL);
218 if (!elts) { 219 if (!elts) {
219 printk(KERN_ERR "list_sort_test: error: cannot allocate " 220 pr_err("error: cannot allocate memory\n");
220 "memory\n"); 221 return err;
221 goto exit;
222 } 222 }
223 223
224 for (i = 0; i < TEST_LIST_LEN; i++) { 224 for (i = 0; i < TEST_LIST_LEN; i++) {
225 el = kmalloc(sizeof(*el), GFP_KERNEL); 225 el = kmalloc(sizeof(*el), GFP_KERNEL);
226 if (!el) { 226 if (!el) {
227 printk(KERN_ERR "list_sort_test: error: cannot " 227 pr_err("error: cannot allocate memory\n");
228 "allocate memory\n");
229 goto exit; 228 goto exit;
230 } 229 }
231 /* force some equivalencies */ 230 /* force some equivalencies */
@@ -239,52 +238,52 @@ static int __init list_sort_test(void)
239 238
240 list_sort(NULL, &head, cmp); 239 list_sort(NULL, &head, cmp);
241 240
241 err = -EINVAL;
242 for (cur = head.next; cur->next != &head; cur = cur->next) { 242 for (cur = head.next; cur->next != &head; cur = cur->next) {
243 struct debug_el *el1; 243 struct debug_el *el1;
244 int cmp_result; 244 int cmp_result;
245 245
246 if (cur->next->prev != cur) { 246 if (cur->next->prev != cur) {
247 printk(KERN_ERR "list_sort_test: error: list is " 247 pr_err("error: list is corrupted\n");
248 "corrupted\n");
249 goto exit; 248 goto exit;
250 } 249 }
251 250
252 cmp_result = cmp(NULL, cur, cur->next); 251 cmp_result = cmp(NULL, cur, cur->next);
253 if (cmp_result > 0) { 252 if (cmp_result > 0) {
254 printk(KERN_ERR "list_sort_test: error: list is not " 253 pr_err("error: list is not sorted\n");
255 "sorted\n");
256 goto exit; 254 goto exit;
257 } 255 }
258 256
259 el = container_of(cur, struct debug_el, list); 257 el = container_of(cur, struct debug_el, list);
260 el1 = container_of(cur->next, struct debug_el, list); 258 el1 = container_of(cur->next, struct debug_el, list);
261 if (cmp_result == 0 && el->serial >= el1->serial) { 259 if (cmp_result == 0 && el->serial >= el1->serial) {
262 printk(KERN_ERR "list_sort_test: error: order of " 260 pr_err("error: order of equivalent elements not "
263 "equivalent elements not preserved\n"); 261 "preserved\n");
264 goto exit; 262 goto exit;
265 } 263 }
266 264
267 if (check(el, el1)) { 265 if (check(el, el1)) {
268 printk(KERN_ERR "list_sort_test: error: element check " 266 pr_err("error: element check failed\n");
269 "failed\n");
270 goto exit; 267 goto exit;
271 } 268 }
272 count++; 269 count++;
273 } 270 }
271 if (head.prev != cur) {
272 pr_err("error: list is corrupted\n");
273 goto exit;
274 }
275
274 276
275 if (count != TEST_LIST_LEN) { 277 if (count != TEST_LIST_LEN) {
276 printk(KERN_ERR "list_sort_test: error: bad list length %d", 278 pr_err("error: bad list length %d", count);
277 count);
278 goto exit; 279 goto exit;
279 } 280 }
280 281
281 err = 0; 282 err = 0;
282exit: 283exit:
284 for (i = 0; i < TEST_LIST_LEN; i++)
285 kfree(elts[i]);
283 kfree(elts); 286 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; 287 return err;
289} 288}
290module_init(list_sort_test); 289module_init(list_sort_test);