From: Masatake YAMATO Date: Sun, 9 May 2021 01:41:34 +0000 (+0900) Subject: lsfd: add a function to get the name of filesystem from a given minor number X-Git-Tag: v2.38-rc1~144^2~134 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=269c425f5b4b4ccb13c8773bbe7d3853d9d5a46b;p=thirdparty%2Futil-linux.git lsfd: add a function to get the name of filesystem from a given minor number Signed-off-by: Masatake YAMATO --- diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index 8204ca486b..65aff806c4 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -74,6 +74,15 @@ struct map { unsigned int read:1, write:1, exec:1, shared:1; }; +/* + * /proc/$pid/mountinfo entries + */ +struct nodev { + struct list_head nodevs; + unsigned long minor; + char *filesystem; +}; + /* * Column related stuffs */ @@ -230,11 +239,34 @@ static void free_file(struct file *file) free(file); } +static struct nodev* make_nodev(unsigned long minor, const char *filesystem) +{ + struct nodev *nodev = xcalloc(1, sizeof(*nodev)); + + INIT_LIST_HEAD(&nodev->nodevs); + nodev->minor = minor; + nodev->filesystem = xstrdup(filesystem); + + return nodev; +} + +static void free_nodev(struct nodev *nodev) +{ + free(nodev->filesystem); + free(nodev); +} + +static void free_nodevs(struct list_head *nodevs) +{ + list_free(nodevs, struct nodev, nodevs, free_nodev); +} + static void free_proc(struct proc *proc) { list_free(&proc->files, struct file, files, free_file); free(proc->command); + free_nodevs(&proc->nodevs); free(proc); } @@ -715,9 +747,43 @@ static void collect_namespace_files(struct proc *proc) ARRAY_SIZE(namespace_assocs)); } +static FILE *open_mountinfo(pid_t pid, pid_t tid) +{ + return fopenf("r", "/proc/%d/task/%d/mountinfo", pid, tid); +} + +static void read_nodevs(struct list_head *nodevs_list, FILE *mountinfo_fp) +{ + /* This can be very long. + A line in mountinfo can have more than 3 paths. */ + char line[PATH_MAX * 3 + 256]; + while (fgets(line, sizeof(line), mountinfo_fp)) { + struct nodev *nodev; + unsigned long major, minor; + char filesystem[256]; + + /* 23 61 0:22 / /sys rw,nosuid,nodev,noexec,relatime shared:2 - sysfs sysfs rw,seclabel */ + if(sscanf(line, "%*d %*d %lu:%lu %*s %*s %*s %*[^-] - %s %*[^\n]", + &major, &minor, filesystem) != 3) + /* 1600 1458 0:55 / / rw,nodev,relatime - overlay overlay rw,context="s... */ + if (sscanf(line, "%*d %*d %lu:%lu %*s %*s %*s - %s %*[^\n]", + &major, &minor, filesystem) != 3) + continue; + + if (major != 0) + continue; + + nodev = make_nodev(minor, filesystem); + list_add_tail(&nodev->nodevs, nodevs_list); + } +} + static void fill_proc(struct proc *proc) { + FILE *mountinfo_fp; + INIT_LIST_HEAD(&proc->files); + INIT_LIST_HEAD(&proc->nodevs); proc->command = proc_get_command_name(proc->pid); if (!proc->command) @@ -733,6 +799,13 @@ static void fill_proc(struct proc *proc) collect_namespace_files(proc); + mountinfo_fp = open_mountinfo(proc->leader->pid, + proc->pid); + if (mountinfo_fp) { + read_nodevs(&proc->nodevs, mountinfo_fp); + fclose(mountinfo_fp); + } + /* If kcmp is not available, * there is no way to no whether threads share resources. * In such cases, we must pay the costs: call collect_mem_files() @@ -1080,6 +1153,17 @@ unsigned long add_name(struct name_manager *nm, const char *name) return e->id; } +const char *get_nodev_filesystem(struct proc *proc, unsigned long minor) +{ + struct list_head *n; + list_for_each (n, &proc->nodevs) { + struct nodev *nodev = list_entry(n, struct nodev, nodevs); + if (nodev->minor == minor) + return nodev->filesystem; + } + return NULL; +} + DIR *opendirf(const char *format, ...) { va_list ap; diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index 6f4e5d840d..a274ad9c70 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -106,6 +106,7 @@ struct proc { uid_t uid; struct list_head procs; struct list_head files; + struct list_head nodevs; }; /* @@ -166,5 +167,6 @@ unsigned long add_name(struct name_manager *nm, const char *name); const char *get_partition(dev_t dev); const char *get_chrdrv(unsigned long major); const char *get_miscdev(unsigned long minor); +const char *get_nodev_filesystem(struct proc *proc, unsigned long minor); #endif /* UTIL_LINUX_LSFD_H */