[PATCH 2/2] tools/vm/page_owner_sort: support for sorting by task command name

From: Jiajian Ye
Date: Sat Mar 05 2022 - 22:10:19 EST


When viewing page owner information, we may also need to the block
to be sorted by task command name. Therefore, the following adjustments
are made:

1. Add a member variable to record task command name of block.

2. Add a new -n option to sort the information of blocks by task command
name.

3. Add -n option explanation in the document.

Signed-off-by: Jiajian Ye <yejiajian2018@xxxxxxxxxxxxxxxx>
---
Documentation/vm/page_owner.rst | 1 +
tools/vm/page_owner_sort.c | 35 ++++++++++++++++++++++++++++++++-
2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/Documentation/vm/page_owner.rst b/Documentation/vm/page_owner.rst
index 941543a797fe..d658436a5e09 100644
--- a/Documentation/vm/page_owner.rst
+++ b/Documentation/vm/page_owner.rst
@@ -117,6 +117,7 @@ Usage
-m Sort by total memory.
-p Sort by pid.
-P Sort by tgid.
+ -n Sort by task command name.
-r Sort by memory release time.
-s Sort by stack trace.
-t Sort by times (default).
diff --git a/tools/vm/page_owner_sort.c b/tools/vm/page_owner_sort.c
index b8d2867b5b18..e508abd8f665 100644
--- a/tools/vm/page_owner_sort.c
+++ b/tools/vm/page_owner_sort.c
@@ -24,6 +24,7 @@

struct block_list {
char *txt;
+ char *comm; // task command name
char *stacktrace;
__u64 ts_nsec;
__u64 free_ts_nsec;
@@ -37,6 +38,7 @@ struct block_list {
static regex_t order_pattern;
static regex_t pid_pattern;
static regex_t tgid_pattern;
+static regex_t comm_pattern;
static regex_t ts_nsec_pattern;
static regex_t free_ts_nsec_pattern;
static struct block_list *list;
@@ -102,6 +104,13 @@ static int compare_tgid(const void *p1, const void *p2)
return l1->tgid - l2->tgid;
}

+static int compare_comm(const void *p1, const void *p2)
+{
+ const struct block_list *l1 = p1, *l2 = p2;
+
+ return strcmp(l1->comm, l2->comm);
+}
+
static int compare_ts(const void *p1, const void *p2)
{
const struct block_list *l1 = p1, *l2 = p2;
@@ -145,6 +154,7 @@ static void check_regcomp(regex_t *pattern, const char *regex)
}

# define FIELD_BUFF 25
+# define TASK_COMM_LEN 16

static int get_page_num(char *buf)
{
@@ -233,6 +243,22 @@ static __u64 get_free_ts_nsec(char *buf)
return free_ts_nsec;
}

+static char *get_comm(char *buf)
+{
+ char *comm_str = malloc(TASK_COMM_LEN);
+
+ memset(comm_str, 0, TASK_COMM_LEN);
+
+ search_pattern(&comm_pattern, comm_str, buf);
+ errno = 0;
+ if (errno != 0) {
+ printf("wrong comm in follow buf:\n%s\n", buf);
+ return NULL;
+ }
+
+ return comm_str;
+}
+
static void add_list(char *buf, int len)
{
if (list_size != 0 &&
@@ -266,6 +292,7 @@ static void add_list(char *buf, int len)
list[list_size].stacktrace++;
list[list_size].pid = get_pid(buf);
list[list_size].tgid = get_tgid(buf);
+ list[list_size].comm = get_comm(buf);
list[list_size].ts_nsec = get_ts_nsec(buf);
list_size++;
if (list_size % 1000 == 0) {
@@ -284,6 +311,7 @@ static void usage(void)
"-t Sort by times (default).\n"
"-p Sort by pid.\n"
"-P Sort by tgid.\n"
+ "-n Sort by task command name.\n"
"-a Sort by memory allocate time.\n"
"-r Sort by memory release time.\n"
"-c Cull by comparing stacktrace instead of total block.\n"
@@ -300,7 +328,7 @@ int main(int argc, char **argv)
struct stat st;
int opt;

- while ((opt = getopt(argc, argv, "acfmprstP")) != -1)
+ while ((opt = getopt(argc, argv, "acfmnprstP")) != -1)
switch (opt) {
case 'a':
cmp = compare_ts;
@@ -329,6 +357,9 @@ int main(int argc, char **argv)
case 'P':
cmp = compare_tgid;
break;
+ case 'n':
+ cmp = compare_comm;
+ break;
default:
usage();
exit(1);
@@ -350,6 +381,7 @@ int main(int argc, char **argv)
check_regcomp(&order_pattern, "order\\s*([0-9]*),");
check_regcomp(&pid_pattern, "pid\\s*([0-9]*),");
check_regcomp(&tgid_pattern, "tgid\\s*([0-9]*) ");
+ check_regcomp(&comm_pattern, "tgid\\s*[0-9]*\\s*\\((.*)\\),\\s*ts");
check_regcomp(&ts_nsec_pattern, "ts\\s*([0-9]*)\\s*ns,");
check_regcomp(&free_ts_nsec_pattern, "free_ts\\s*([0-9]*)\\s*ns");
fstat(fileno(fin), &st);
@@ -408,6 +440,7 @@ int main(int argc, char **argv)
regfree(&order_pattern);
regfree(&pid_pattern);
regfree(&tgid_pattern);
+ regfree(&comm_pattern);
regfree(&ts_nsec_pattern);
regfree(&free_ts_nsec_pattern);
return 0;
--
2.25.1