Browse Source

lsfd: add KTHREAD column

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
pull/1487/head
Masatake YAMATO 10 months ago
parent
commit
f26ddd080d
  1. 1
      include/procfs.h
  2. 22
      lib/procfs.c
  3. 3
      misc-utils/lsfd-file.c
  4. 3
      misc-utils/lsfd.1.adoc
  5. 36
      misc-utils/lsfd.c
  6. 2
      misc-utils/lsfd.h
  7. 6
      tests/expected/lsfd/column-kthread
  8. 42
      tests/ts/lsfd/column-kthread

1
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)

22
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)

3
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;

3
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.

36
misc-utils/lsfd.c

@ -30,6 +30,7 @@
#include <unistd.h>
#include <getopt.h>
#include <linux/sched.h>
#include <sys/syscall.h>
#include <linux/kcmp.h>
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'};

2
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;
};
/*

6
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

42
tests/ts/lsfd/column-kthread

@ -0,0 +1,42 @@
#!/bin/bash
#
# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
#
# 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
Loading…
Cancel
Save