]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: read /proc/$pid/ns/mnt earlier
authorMasatake YAMATO <yamato@redhat.com>
Wed, 3 Jan 2024 07:33:19 +0000 (16:33 +0900)
committerKarel Zak <kzak@redhat.com>
Thu, 29 Feb 2024 18:52:10 +0000 (19:52 +0100)
The change fba9898fd5b1d20a2ed350b7b542d9f8a3597a0c I introduced
unexpectedly canceled the optimization technique introduced in
a7f70ce17a925f1085bfa4b292427f8741d7e2a2 that reduced the number of
times reading /proc/$pid/mountinfo.

This change reenables the technique.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
(cherry picked from commit a99427e9c4e4b1ab57df1f94f6addc1769426f5a)

misc-utils/lsfd.c

index ac7b37843f7f949ac3139054cd5a1032b4dad814..771daef1521097ed216a937b622040b1f9f00de4 100644 (file)
@@ -1006,12 +1006,26 @@ static void collect_fs_files(struct path_cxt *pc, struct proc *proc,
                               sockets_only);
 }
 
-static void collect_namespace_files(struct path_cxt *pc, struct proc *proc)
+static void collect_namespace_files_tophalf(struct path_cxt *pc, struct proc *proc)
 {
        enum association assocs[] = {
                ASSOC_NS_CGROUP,
                ASSOC_NS_IPC,
                ASSOC_NS_MNT,
+       };
+       const char *names[] = {
+               [ASSOC_NS_CGROUP] = "ns/cgroup",
+               [ASSOC_NS_IPC]    = "ns/ipc",
+               [ASSOC_NS_MNT]    = "ns/mnt",
+       };
+       collect_outofbox_files(pc, proc, assocs, names, ARRAY_SIZE(assocs),
+                              /* Namespace information is alwasys needed. */
+                              false);
+}
+
+static void collect_namespace_files_bottomhalf(struct path_cxt *pc, struct proc *proc)
+{
+       enum association assocs[] = {
                ASSOC_NS_NET,
                ASSOC_NS_PID,
                ASSOC_NS_PID4C,
@@ -1021,9 +1035,6 @@ static void collect_namespace_files(struct path_cxt *pc, struct proc *proc)
                ASSOC_NS_UTS,
        };
        const char *names[] = {
-               [ASSOC_NS_CGROUP] = "ns/cgroup",
-               [ASSOC_NS_IPC]    = "ns/ipc",
-               [ASSOC_NS_MNT]    = "ns/mnt",
                [ASSOC_NS_NET]    = "ns/net",
                [ASSOC_NS_PID]    = "ns/pid",
                [ASSOC_NS_PID4C]  = "ns/pid_for_children",
@@ -1698,6 +1709,28 @@ static void read_process(struct lsfd_control *ctl, struct path_cxt *pc,
            || kcmp(proc->leader->pid, proc->pid, KCMP_FS, 0, 0) != 0)
                collect_fs_files(pc, proc, ctl->sockets_only);
 
+       /* Reading /proc/$pid/mountinfo is expensive.
+        * mnt_namespaces is a table for avoiding reading mountinfo files
+        * for an identical mnt namespace.
+        *
+        * After reading a mountinfo file for a mnt namespace, we store $mnt_id
+        * identifying the mnt namespace to mnt_namespaces.
+        *
+        * Before reading a mountinfo, we look up the mnt_namespaces with $mnt_id
+        * as a key. If we find the key, we can skip the reading.
+        *
+        * To utilize mnt_namespaces, we need $mnt_id.
+        * So we read /proc/$pid/ns/mnt here. However, we should not read
+        * /proc/$pid/ns/net here. When reading /proc/$pid/ns/net, we need
+        * the information about backing device of "nsfs" file system.
+        * The information is available in a mountinfo file.
+        */
+
+       /* 1/3. read /proc/$pid/ns/mnt */
+       if (proc->ns_mnt == 0)
+               collect_namespace_files_tophalf(pc, proc);
+
+       /* 2/3. read /proc/$pid/mountinfo */
        if (proc->ns_mnt == 0 || !has_mnt_ns(proc->ns_mnt)) {
                FILE *mnt = ul_path_fopen(pc, "r", "mountinfo");
                if (mnt) {
@@ -1708,7 +1741,8 @@ static void read_process(struct lsfd_control *ctl, struct path_cxt *pc,
                }
        }
 
-       collect_namespace_files(pc, proc);
+       /* 3/3. read /proc/$pid/ns/{the other than mnt} */
+       collect_namespace_files_bottomhalf(pc, proc);
 
        /* If kcmp is not available,
         * there is no way to know whether threads share resources.