]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: print file descriptors targeted by eventpoll files
authorMasatake YAMATO <yamato@redhat.com>
Sat, 27 May 2023 17:49:00 +0000 (02:49 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Sun, 28 May 2023 09:01:27 +0000 (18:01 +0900)
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
misc-utils/lsfd-unkn.c
misc-utils/lsfd.1.adoc
misc-utils/lsfd.c
misc-utils/lsfd.h

index 7d025b40fc4afcda4f267c766db7b0cbcecb8b4e..6ecdc76f20db1a827f981d4edc9fbea88cf8c6c3 100644 (file)
@@ -434,6 +434,123 @@ static const struct anon_ops anon_eventfd_ops = {
        .ipc_class = &anon_eventfd_ipc_class,
 };
 
+/*
+ * eventpoll
+ */
+struct anon_eventpoll_data {
+       size_t count;
+       int *tfds;
+};
+
+
+static bool anon_eventpoll_probe(const char *str)
+{
+       return strncmp(str, "[eventpoll]", 11) == 0;
+}
+
+static void anon_eventpoll_init(struct unkn *unkn)
+{
+       unkn->anon_data = xcalloc(1, sizeof(struct anon_eventpoll_data));
+}
+
+static void anon_eventpoll_free(struct unkn *unkn)
+{
+       struct anon_eventpoll_data *data = unkn->anon_data;
+       free (data->tfds);
+       free (data);
+}
+
+static int anon_eventpoll_handle_fdinfo(struct unkn *unkn, const char *key, const char *value)
+{
+       struct anon_eventpoll_data *data;
+       if (strcmp(key, "tfd") == 0) {
+               unsigned long tfd;
+               char *end = NULL;
+
+               errno = 0;
+               tfd = strtoul(value, &end, 0);
+               if (errno != 0)
+                       return 0; /* ignore -- parse failed */
+
+               data = (struct anon_eventpoll_data *)unkn->anon_data;
+               data->tfds = xreallocarray (data->tfds, ++data->count, sizeof(int));
+               data->tfds[data->count - 1] = (int)tfd;
+               return 1;
+       }
+       return 0;
+}
+
+static int intcmp (const void *a, const void *b)
+{
+       int ai = *(int *)a;
+       int bi = *(int *)b;
+
+       return ai - bi;
+}
+
+static void anon_eventpoll_attach_xinfo(struct unkn *unkn)
+{
+       struct anon_eventpoll_data *data = (struct anon_eventpoll_data *)unkn->anon_data;
+       qsort (data->tfds, data->count, sizeof (data->tfds[0]),
+              intcmp);
+}
+
+static char *anon_eventpoll_make_tfds_string(struct anon_eventpoll_data *data,
+                                            const char *prefix)
+{
+       char *str = prefix? xstrdup(prefix): NULL;
+
+       char buf[256];
+       for (size_t i = 0; i < data->count; i++) {
+               size_t offset = 0;
+
+               if (i > 0) {
+                       buf[0] = ',';
+                       offset = 1;
+               }
+               snprintf(buf + offset, sizeof(buf) - offset, "%d", data->tfds[i]);
+               xstrappend(&str, buf);
+       }
+       return str;
+}
+
+static char *anon_eventpoll_get_name(struct unkn *unkn)
+{
+       return anon_eventpoll_make_tfds_string ((struct anon_eventpoll_data *)unkn->anon_data,
+                                               "tfds=");
+}
+
+static bool anon_eventpoll_fill_column(struct proc *proc  __attribute__((__unused__)),
+                                      struct unkn *unkn,
+                                      struct libscols_line *ln __attribute__((__unused__)),
+                                      int column_id,
+                                      size_t column_index __attribute__((__unused__)),
+                                      char **str)
+{
+       struct anon_eventpoll_data *data = (struct anon_eventpoll_data *)unkn->anon_data;
+
+       switch(column_id) {
+       case COL_EVENTPOLL_TFDS:
+               *str =anon_eventpoll_make_tfds_string (data, NULL);
+               if (*str)
+                       return true;
+               break;
+       }
+
+       return false;
+}
+
+static const struct anon_ops anon_eventpoll_ops = {
+       .class = "eventpoll",
+       .probe = anon_eventpoll_probe,
+       .get_name = anon_eventpoll_get_name,
+       .fill_column = anon_eventpoll_fill_column,
+       .init = anon_eventpoll_init,
+       .free = anon_eventpoll_free,
+       .handle_fdinfo = anon_eventpoll_handle_fdinfo,
+       .attach_xinfo = anon_eventpoll_attach_xinfo,
+};
+
 /*
  * generic (fallback implementation)
  */
@@ -449,6 +566,7 @@ static const struct anon_ops anon_generic_ops = {
 static const struct anon_ops *anon_ops[] = {
        &anon_pidfd_ops,
        &anon_eventfd_ops,
+       &anon_eventpoll_ops,
 };
 
 static const struct anon_ops *anon_probe(const char *str)
index 11e7ee7001336b4c2e096377b2d8c3d53b194d3b..04340329cbe8ddacf88134692d15bf9e8387bad1 100644 (file)
@@ -167,6 +167,9 @@ _PID_,_COMMAND_,_ASSOC_
 EVENTFD.ID <``number``>::
 Eventfd ID.
 
+EVENTPOLL.TFDS <``string``>>::
+File descriptors targeted by the eventpoll file.
+
 FD <``number``>::
 File descriptor for the file.
 
@@ -226,6 +229,9 @@ Cooked version of KNAME. It is mostly same as KNAME.
 +
 Some files have special formats and information sources:
 +
+eventpoll:::
+tfds=_EVENTPOLL.TFDS_
++
 eventfd:::
 id=_EVENTFD.ID_
 +
index d9c1a00bc209c4731d02e7471b08d9f0e294997a..9c56460e1321ce09f6fb2a1348081938cd9d909f 100644 (file)
@@ -150,18 +150,18 @@ static const struct colinfo infos[] = {
        [COL_EVENTFD_ID]       = {"EVENTFD.ID",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
                                   N_("eventfd ID") },
-       [COL_FLAGS]            = { "FLAGS",
-                                  0,   SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
-                                  N_("flags specified when opening the file") },
+       [COL_EVENTPOLL_TFDS]   = {"EVENTPOLL.TFDS",
+                                  0,   SCOLS_FL_WRAP,  SCOLS_JSON_STRING,
+                                  N_("file descriptors targeted by the eventpoll file") },
        [COL_FD]               = { "FD",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
                                   N_("file descriptor for the file") },
+       [COL_FLAGS]            = { "FLAGS",
+                                  0,   SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
+                                  N_("flags specified when opening the file") },
        [COL_FUID]             = { "FUID",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
                                   N_("user ID number of the file's owner") },
-       [COL_INODE]            = { "INODE",
-                                  0,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
-                                  N_("inode number") },
        [COL_INET_LADDR]       = { "INET.LADDR",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
                                   N_("local IP address") },
@@ -174,6 +174,9 @@ static const struct colinfo infos[] = {
        [COL_INET6_RADDR]      = { "INET6.RADDR",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
                                   N_("remote IPv6 address") },
+       [COL_INODE]            = { "INODE",
+                                  0,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
+                                  N_("inode number") },
        [COL_KNAME]            = { "KNAME",
                                   0.4, SCOLS_FL_TRUNC, SCOLS_JSON_STRING,
                                   N_("name of the file (raw)") },
index dc02e30ecb9d2a2e2c5942b74dd4b669afe509cd..5b653658b57a5140c9fd285b24b4476dd8f914e8 100644 (file)
@@ -47,13 +47,15 @@ enum {
        COL_DEVTYPE,
        COL_ENDPOINTS,
        COL_EVENTFD_ID,
+       COL_EVENTPOLL_TFDS,
        COL_FD,
        COL_FLAGS,
-       COL_INODE,
+       COL_FUID,               /* file */
        COL_INET_LADDR,
        COL_INET_RADDR,
        COL_INET6_LADDR,
        COL_INET6_RADDR,
+       COL_INODE,
        COL_KNAME,
        COL_KTHREAD,
        COL_MAJMIN,
@@ -68,6 +70,7 @@ enum {
        COL_NLINK,
        COL_NS_NAME,
        COL_NS_TYPE,
+       COL_OWNER,              /* file */
        COL_PACKET_IFACE,
        COL_PACKET_PROTOCOL,
        COL_PARTITION,
@@ -104,8 +107,6 @@ enum {
        COL_UID,                /* process */
        COL_UNIX_PATH,
        COL_USER,               /* process */
-       COL_FUID,               /* file */
-       COL_OWNER,              /* file */
        LSFD_N_COLS             /* This must be at last. */
 };