From: Masatake YAMATO Date: Tue, 19 Oct 2021 08:05:08 +0000 (+0900) Subject: lsfd: add KTHREAD column X-Git-Tag: v2.38-rc1~144^2~18 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f26ddd080d44e7e261fcbb7d78dc770f8c85983f;p=thirdparty%2Futil-linux.git lsfd: add KTHREAD column Signed-off-by: Masatake YAMATO --- diff --git a/include/procfs.h b/include/procfs.h index 55cebce50d..5a730c94ca 100644 --- a/include/procfs.h +++ b/include/procfs.h @@ -28,6 +28,7 @@ extern int procfs_process_init_path(struct path_cxt *pc, pid_t pid); extern int procfs_process_get_uid(struct path_cxt *pc, uid_t *uid); extern ssize_t procfs_process_get_cmdline(struct path_cxt *pc, char *buf, size_t bufsz); extern ssize_t procfs_process_get_cmdname(struct path_cxt *pc, char *buf, size_t bufsz); +extern ssize_t procfs_process_get_stat(struct path_cxt *pc, char *buf, size_t bufsz); static inline ssize_t procfs_process_get_exe(struct path_cxt *pc, char *buf, size_t bufsz) diff --git a/lib/procfs.c b/lib/procfs.c index 8173d6274c..4d6d25b6d7 100644 --- a/lib/procfs.c +++ b/lib/procfs.c @@ -138,9 +138,10 @@ static ssize_t read_procfs_file(int fd, char *buf, size_t bufsz) return sz; } -ssize_t procfs_process_get_cmdline(struct path_cxt *pc, char *buf, size_t bufsz) +static ssize_t procfs_process_get_line_for(struct path_cxt *pc, char *buf, size_t bufsz, + const char *fname) { - int fd = ul_path_open(pc, O_RDONLY|O_CLOEXEC, "cmdline"); + int fd = ul_path_open(pc, O_RDONLY|O_CLOEXEC, fname); if (fd >= 0) { ssize_t sz = read_procfs_file(fd, buf, bufsz); @@ -150,16 +151,19 @@ ssize_t procfs_process_get_cmdline(struct path_cxt *pc, char *buf, size_t bufsz) return -errno; } +ssize_t procfs_process_get_cmdline(struct path_cxt *pc, char *buf, size_t bufsz) +{ + return procfs_process_get_line_for(pc, buf, bufsz, "cmdline"); +} + ssize_t procfs_process_get_cmdname(struct path_cxt *pc, char *buf, size_t bufsz) { - int fd = ul_path_open(pc, O_RDONLY|O_CLOEXEC, "comm"); + return procfs_process_get_line_for(pc, buf, bufsz, "comm"); +} - if (fd >= 0) { - ssize_t sz = read_procfs_file(fd, buf, bufsz); - close(fd); - return sz; - } - return -errno; +ssize_t procfs_process_get_stat(struct path_cxt *pc, char *buf, size_t bufsz) +{ + return procfs_process_get_line_for(pc, buf, bufsz, "stat"); } int procfs_process_get_uid(struct path_cxt *pc, uid_t *uid) diff --git a/misc-utils/lsfd-file.c b/misc-utils/lsfd-file.c index ea1410e6af..e08b6349c4 100644 --- a/misc-utils/lsfd-file.c +++ b/misc-utils/lsfd-file.c @@ -297,6 +297,9 @@ static bool file_fill_column(struct proc *proc, case COL_DELETED: xasprintf(&str, "%d", file->stat.st_nlink == 0); break; + case COL_KTHREAD: + xasprintf(&str, "%u", proc->kthread); + break; case COL_MNT_ID: xasprintf(&str, "%d", file->association < 0? 0: file->mnt_id); break; diff --git a/misc-utils/lsfd.1.adoc b/misc-utils/lsfd.1.adoc index a81befc8c3..8549c33553 100644 --- a/misc-utils/lsfd.1.adoc +++ b/misc-utils/lsfd.1.adoc @@ -104,6 +104,9 @@ User ID number of the file's owner. INODE <__number__>:: Inode number. +KTHREAD <__boolean__>:: +Whether the process is a kernel thread or not. + MAJ:MIN <__string__>:: Device ID for special, or ID of device containing file. diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index 8c703d411e..247c678ee0 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -30,6 +30,7 @@ #include #include +#include #include #include static int kcmp(pid_t pid1, pid_t pid2, int type, @@ -38,6 +39,10 @@ static int kcmp(pid_t pid1, pid_t pid2, int type, return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2); } +/* See proc(5). + * Defined in linux/include/linux/sched.h private header file. */ +#define PF_KTHREAD 0x00200000 /* I am a kernel thread */ + #include "c.h" #include "nls.h" #include "xalloc.h" @@ -108,6 +113,8 @@ static struct colinfo infos[] = { N_("user ID number of the file's owner") }, [COL_INODE] = { "INODE", 0, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER, N_("inode number") }, + [COL_KTHREAD] = { "KTHREAD", 0, SCOLS_FL_RIGHT, SCOLS_JSON_BOOLEAN, + N_("opened by a kernel thread") }, [COL_MAJMIN] = { "MAJ:MIN", 0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING, N_("device ID for special, or ID of device containing file") }, [COL_MAPLEN] = { "MAPLEN", 0, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER, @@ -195,6 +202,9 @@ struct lsfd_control { struct lsfd_filter *filter; }; +static void xstrappend(char **a, const char *b); +static void xstrputc(char **a, char c); + static int column_name_to_id(const char *name, size_t namesz) { size_t i; @@ -381,6 +391,7 @@ static struct proc *new_process(pid_t pid, struct proc *leader) INIT_LIST_HEAD(&proc->files); INIT_LIST_HEAD(&proc->procs); + proc->kthread = 0; return proc; } @@ -867,6 +878,25 @@ static void read_process(struct lsfd_control *ctl, struct path_cxt *pc, xstrdup(buf) : xstrdup(_("(unknown)")); procfs_process_get_uid(pc, &proc->uid); + if (procfs_process_get_stat(pc, buf, sizeof(buf)) > 0) { + char *p; + unsigned int flags; + char *pat = NULL; + + /* See proc(5) about the column in the line. */ + xstrappend(&pat, "%*d ("); + for (p = proc->command; *p != '\0'; p++) { + if (*p == '%') + xstrappend(&pat, "%%"); + else + xstrputc(&pat, *p); + } + xstrappend(&pat, ") %*c %*d %*d %*d %*d %*d %u %*[^\n]"); + if (sscanf(buf, pat, &flags) == 1) + proc->kthread = !!(flags & PF_KTHREAD); + free(pat); + } + collect_execve_file(pc, proc); if (proc->pid == proc->leader->pid @@ -987,6 +1017,12 @@ static void xstrappend(char **a, const char *b) err(EXIT_FAILURE, _("failed to allocate memory for string")); } +static void xstrputc(char **a, char c) +{ + char b[] = {c, '\0'}; + xstrappend(a, b); +} + static char * quote_filter_expr(char *expr) { char c[] = {'\0', '\0'}; diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index 59cba6ea4d..9b0e3aef24 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -44,6 +44,7 @@ enum { COL_FD, COL_FLAGS, COL_INODE, + COL_KTHREAD, COL_MAJMIN, COL_MAPLEN, COL_MISCDEV, @@ -97,6 +98,7 @@ struct proc { ino_t ns_mnt; struct list_head procs; struct list_head files; + unsigned int kthread: 1; }; /* diff --git a/tests/expected/lsfd/column-kthread b/tests/expected/lsfd/column-kthread new file mode 100644 index 0000000000..98b0354763 --- /dev/null +++ b/tests/expected/lsfd/column-kthread @@ -0,0 +1,6 @@ +COMMAND PID USER MODE TYPE INODE NAME KTHREAD +systemd 1 root --- DIR 2 / 0 +systemd 1 root --- DIR 2 / 0 +kthreadd 2 root --- DIR 2 / 1 +kthreadd 2 root --- DIR 2 / 1 +0 diff --git a/tests/ts/lsfd/column-kthread b/tests/ts/lsfd/column-kthread new file mode 100755 index 0000000000..1cf8fdb8b3 --- /dev/null +++ b/tests/ts/lsfd/column-kthread @@ -0,0 +1,42 @@ +#!/bin/bash +# +# Copyright (C) 2021 Masatake YAMATO +# +# This file is part of util-linux. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +TS_TOPDIR="${0%/*}/../.." +TS_DESC="directory" + +. $TS_TOPDIR/functions.sh +ts_init "$*" + +ts_check_test_command "$TS_CMD_LSFD" +ts_check_prog "ps" + +ts_skip_nonroot + +[ "$(ps --no-headers -o comm 1)" = 'systemd' ] || ts_skip "pid 1 is not systemd" +[ "$(ps --no-headers -o comm 2)" = 'kthreadd' ] || ts_skip "pid 2 is not kthreadd" + +ts_cd "$TS_OUTDIR" + +{ + "$TS_CMD_LSFD" -o COMMAND,PID,USER,MODE,TYPE,INODE,NAME,KTHREAD \ + -Q '(PID < 3) and ((ASSOC == "cwd") or (ASSOC == "rtd"))' + echo $? +} > $TS_OUTPUT 2>&1 + +ts_finalize + +