Commit 942eaabd5d77522223a311ed9bddaaa3cefde27d
Committed by
Linus Torvalds
1 parent
ae6aa2ea89
Exists in
master
and in
4 other branches
[PATCH] s390: debug feature changes
debug feature changes/bug fixes: - Use get_clock() function instead of private inline assembly. - Use 'struct timeval' instead of 'struct timespec' for call to tod_to_timeval(). Now the microsecond part of the timestamp is correct again. - Fix a locking problem: when creating a snapshot of the current content of the debug areas, lock the entire debug_info object. Signed-off-by: Michael Holzheu <holzheu@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 2 changed files with 32 additions and 22 deletions Side-by-side Diff
arch/s390/kernel/debug.c
| ... | ... | @@ -62,7 +62,7 @@ |
| 62 | 62 | } debug_sprintf_entry_t; |
| 63 | 63 | |
| 64 | 64 | |
| 65 | -extern void tod_to_timeval(uint64_t todval, struct timeval *xtime); | |
| 65 | +extern void tod_to_timeval(uint64_t todval, struct timespec *xtime); | |
| 66 | 66 | |
| 67 | 67 | /* internal function prototyes */ |
| 68 | 68 | |
| 69 | 69 | |
| ... | ... | @@ -374,9 +374,24 @@ |
| 374 | 374 | { |
| 375 | 375 | int i,j; |
| 376 | 376 | debug_info_t* rc; |
| 377 | + unsigned long flags; | |
| 377 | 378 | |
| 378 | - rc = debug_info_alloc(in->name, in->pages_per_area, in->nr_areas, | |
| 379 | - in->buf_size, in->level, mode); | |
| 379 | + /* get a consistent copy of the debug areas */ | |
| 380 | + do { | |
| 381 | + rc = debug_info_alloc(in->name, in->pages_per_area, | |
| 382 | + in->nr_areas, in->buf_size, in->level, mode); | |
| 383 | + spin_lock_irqsave(&in->lock, flags); | |
| 384 | + if(!rc) | |
| 385 | + goto out; | |
| 386 | + /* has something changed in the meantime ? */ | |
| 387 | + if((rc->pages_per_area == in->pages_per_area) && | |
| 388 | + (rc->nr_areas == in->nr_areas)) { | |
| 389 | + break; | |
| 390 | + } | |
| 391 | + spin_unlock_irqrestore(&in->lock, flags); | |
| 392 | + debug_info_free(rc); | |
| 393 | + } while (1); | |
| 394 | + | |
| 380 | 395 | if(!rc || (mode == NO_AREAS)) |
| 381 | 396 | goto out; |
| 382 | 397 | |
| ... | ... | @@ -386,6 +401,7 @@ |
| 386 | 401 | } |
| 387 | 402 | } |
| 388 | 403 | out: |
| 404 | + spin_unlock_irqrestore(&in->lock, flags); | |
| 389 | 405 | return rc; |
| 390 | 406 | } |
| 391 | 407 | |
| 392 | 408 | |
| ... | ... | @@ -593,19 +609,15 @@ |
| 593 | 609 | debug_info_t *debug_info, *debug_info_snapshot; |
| 594 | 610 | |
| 595 | 611 | down(&debug_lock); |
| 596 | - | |
| 597 | - /* find debug log and view */ | |
| 598 | - debug_info = debug_area_first; | |
| 599 | - while(debug_info != NULL){ | |
| 600 | - for (i = 0; i < DEBUG_MAX_VIEWS; i++) { | |
| 601 | - if (!debug_info->views[i]) | |
| 602 | - continue; | |
| 603 | - else if (debug_info->debugfs_entries[i] == | |
| 604 | - file->f_dentry) { | |
| 605 | - goto found; /* found view ! */ | |
| 606 | - } | |
| 612 | + debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip; | |
| 613 | + /* find debug view */ | |
| 614 | + for (i = 0; i < DEBUG_MAX_VIEWS; i++) { | |
| 615 | + if (!debug_info->views[i]) | |
| 616 | + continue; | |
| 617 | + else if (debug_info->debugfs_entries[i] == | |
| 618 | + file->f_dentry) { | |
| 619 | + goto found; /* found view ! */ | |
| 607 | 620 | } |
| 608 | - debug_info = debug_info->next; | |
| 609 | 621 | } |
| 610 | 622 | /* no entry found */ |
| 611 | 623 | rc = -EINVAL; |
| ... | ... | @@ -833,7 +845,7 @@ |
| 833 | 845 | debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level, |
| 834 | 846 | int exception) |
| 835 | 847 | { |
| 836 | - STCK(active->id.stck); | |
| 848 | + active->id.stck = get_clock(); | |
| 837 | 849 | active->id.fields.cpuid = smp_processor_id(); |
| 838 | 850 | active->caller = __builtin_return_address(0); |
| 839 | 851 | active->id.fields.exception = exception; |
| ... | ... | @@ -1078,7 +1090,7 @@ |
| 1078 | 1090 | if (view->input_proc) |
| 1079 | 1091 | mode |= S_IWUSR; |
| 1080 | 1092 | pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry, |
| 1081 | - NULL, &debug_file_ops); | |
| 1093 | + id , &debug_file_ops); | |
| 1082 | 1094 | if (!pde){ |
| 1083 | 1095 | printk(KERN_WARNING "debug: debugfs_create_file() failed!"\ |
| 1084 | 1096 | " Cannot register view %s/%s\n", id->name,view->name); |
| ... | ... | @@ -1432,7 +1444,7 @@ |
| 1432 | 1444 | debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, |
| 1433 | 1445 | int area, debug_entry_t * entry, char *out_buf) |
| 1434 | 1446 | { |
| 1435 | - struct timeval time_val; | |
| 1447 | + struct timespec time_spec; | |
| 1436 | 1448 | unsigned long long time; |
| 1437 | 1449 | char *except_str; |
| 1438 | 1450 | unsigned long caller; |
| ... | ... | @@ -1443,7 +1455,7 @@ |
| 1443 | 1455 | time = entry->id.stck; |
| 1444 | 1456 | /* adjust todclock to 1970 */ |
| 1445 | 1457 | time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); |
| 1446 | - tod_to_timeval(time, &time_val); | |
| 1458 | + tod_to_timeval(time, &time_spec); | |
| 1447 | 1459 | |
| 1448 | 1460 | if (entry->id.fields.exception) |
| 1449 | 1461 | except_str = "*"; |
| ... | ... | @@ -1451,7 +1463,7 @@ |
| 1451 | 1463 | except_str = "-"; |
| 1452 | 1464 | caller = ((unsigned long) entry->caller) & PSW_ADDR_INSN; |
| 1453 | 1465 | rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %p ", |
| 1454 | - area, time_val.tv_sec, time_val.tv_usec, level, | |
| 1466 | + area, time_spec.tv_sec, time_spec.tv_nsec / 1000, level, | |
| 1455 | 1467 | except_str, entry->id.fields.cpuid, (void *) caller); |
| 1456 | 1468 | return rc; |
| 1457 | 1469 | } |
include/asm-s390/debug.h
| ... | ... | @@ -52,8 +52,6 @@ |
| 52 | 52 | #define DEBUG_DATA(entry) (char*)(entry + 1) /* data is stored behind */ |
| 53 | 53 | /* the entry information */ |
| 54 | 54 | |
| 55 | -#define STCK(x) asm volatile ("STCK 0(%1)" : "=m" (x) : "a" (&(x)) : "cc") | |
| 56 | - | |
| 57 | 55 | typedef struct __debug_entry debug_entry_t; |
| 58 | 56 | |
| 59 | 57 | struct debug_view; |