Skip to content

Commit dc18c81

Browse files
niklas88Alexander Gordeev
authored andcommitted
s390/debug: Add a reverse mode for debug_dump()
In this mode debug_dump() writes the debug log starting at the newest entry followed by earlier entries. To this end add a debug_prev_entry() helper analogous to debug_next_entry() a helper to get the latest entry which is one before the active entry and a helper to iterate either forward or backward. Reviewed-by: Halil Pasic <pasic@linux.ibm.com> Co-developed-by: Halil Pasic <pasic@linux.ibm.com> Signed-off-by: Halil Pasic <pasic@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
1 parent 5f952da commit dc18c81

2 files changed

Lines changed: 86 additions & 3 deletions

File tree

arch/s390/include/asm/debug.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ debug_info_t *debug_register_mode(const char *name, int pages, int nr_areas,
115115
gid_t gid);
116116

117117
ssize_t debug_dump(debug_info_t *id, struct debug_view *view,
118-
char *buf, size_t buf_size);
118+
char *buf, size_t buf_size, bool reverse);
119119

120120
void debug_unregister(debug_info_t *id);
121121

arch/s390/kernel/debug.c

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/export.h>
2525
#include <linux/init.h>
2626
#include <linux/fs.h>
27+
#include <linux/math.h>
2728
#include <linux/minmax.h>
2829
#include <linux/debugfs.h>
2930

@@ -354,7 +355,10 @@ static debug_info_t *debug_info_copy(debug_info_t *in, int mode)
354355
for (i = 0; i < in->nr_areas; i++) {
355356
for (j = 0; j < in->pages_per_area; j++)
356357
memcpy(rc->areas[i][j], in->areas[i][j], PAGE_SIZE);
358+
rc->active_pages[i] = in->active_pages[i];
359+
rc->active_entries[i] = in->active_entries[i];
357360
}
361+
rc->active_area = in->active_area;
358362
out:
359363
spin_unlock_irqrestore(&in->lock, flags);
360364
return rc;
@@ -461,6 +465,84 @@ static inline bool debug_next_entry(file_private_info_t *p_info)
461465
return true;
462466
}
463467

468+
/**
469+
* debug_to_act_entry - Go to the currently active entry
470+
* @p_info: Private info that is manipulated
471+
*
472+
* Sets the current position in @p_info to the currently active
473+
* entry of @p_info->debug_info_snap
474+
*/
475+
static void debug_to_act_entry(file_private_info_t *p_info)
476+
{
477+
debug_info_t *snap_id;
478+
479+
snap_id = p_info->debug_info_snap;
480+
p_info->act_area = snap_id->active_area;
481+
p_info->act_page = snap_id->active_pages[snap_id->active_area];
482+
p_info->act_entry = snap_id->active_entries[snap_id->active_area];
483+
}
484+
485+
/**
486+
* debug_prev_entry - Go to the previous entry
487+
* @p_info: Private info that is manipulated
488+
*
489+
* Sets the current position in @p_info to the previous entry. If no previous entry
490+
* exists the current position is set left as DEBUG_PROLOG_ENTRY and the return value
491+
* indicates that no previous entries exist.
492+
*
493+
* Return: True if there are more previous entries, false otherwise
494+
*/
495+
496+
static inline bool debug_prev_entry(file_private_info_t *p_info)
497+
{
498+
debug_info_t *id;
499+
500+
id = p_info->debug_info_snap;
501+
if (p_info->act_entry == DEBUG_PROLOG_ENTRY)
502+
debug_to_act_entry(p_info);
503+
if (!id->areas)
504+
return false;
505+
p_info->act_entry -= id->entry_size;
506+
/* switch to prev page, if we reached the beginning of the page */
507+
if (p_info->act_entry < 0) {
508+
/* end of previous page */
509+
p_info->act_entry = rounddown(PAGE_SIZE, id->entry_size) - id->entry_size;
510+
p_info->act_page--;
511+
if (p_info->act_page < 0) {
512+
/* previous area */
513+
p_info->act_area--;
514+
p_info->act_page = id->pages_per_area - 1;
515+
}
516+
if (p_info->act_area < 0)
517+
p_info->act_area = (id->nr_areas - 1) % id->nr_areas;
518+
}
519+
/* check full circle */
520+
if (id->active_area == p_info->act_area &&
521+
id->active_pages[id->active_area] == p_info->act_page &&
522+
id->active_entries[id->active_area] == p_info->act_entry)
523+
return false;
524+
return true;
525+
}
526+
527+
/**
528+
* debug_move_entry - Go to next entry in either the forward or backward direction
529+
* @p_info: Private info that is manipulated
530+
* @reverse: If true go to the next entry in reverse i.e. previous
531+
*
532+
* Sets the current position in @p_info to the next (@reverse == false) or
533+
* previous (@reverse == true) entry.
534+
*
535+
* Return: True if there are further entries in that direction,
536+
* false otherwise.
537+
*/
538+
static bool debug_move_entry(file_private_info_t *p_info, bool reverse)
539+
{
540+
if (reverse)
541+
return debug_prev_entry(p_info);
542+
else
543+
return debug_next_entry(p_info);
544+
}
545+
464546
/*
465547
* debug_output:
466548
* - called for user read()
@@ -638,6 +720,7 @@ static int debug_close(struct inode *inode, struct file *file)
638720
* @view: View with which to dump the debug information
639721
* @buf: Buffer the textual debug data representation is written to
640722
* @buf_size: Size of the buffer, including the trailing '\0' byte
723+
* @reverse: Go backwards from the last written entry
641724
*
642725
* This function may be used whenever a textual representation of the debug
643726
* information is required without using an s390dbf file.
@@ -650,7 +733,7 @@ static int debug_close(struct inode *inode, struct file *file)
650733
* On failure an error code less than 0 is returned.
651734
*/
652735
ssize_t debug_dump(debug_info_t *id, struct debug_view *view,
653-
char *buf, size_t buf_size)
736+
char *buf, size_t buf_size, bool reverse)
654737
{
655738
file_private_info_t *p_info;
656739
size_t size, offset = 0;
@@ -672,7 +755,7 @@ ssize_t debug_dump(debug_info_t *id, struct debug_view *view,
672755
offset += size;
673756
if (offset >= buf_size)
674757
break;
675-
} while (debug_next_entry(p_info));
758+
} while (debug_move_entry(p_info, reverse));
676759
debug_file_private_free(p_info);
677760
buf[offset] = '\0';
678761

0 commit comments

Comments
 (0)