summaryrefslogtreecommitdiffstats
path: root/sys-utils/lsns.c
diff options
context:
space:
mode:
authorMasatake YAMATO2017-11-24 11:31:06 +0100
committerKarel Zak2017-11-27 15:54:55 +0100
commit74d2056ae85f256ed35cbc55771887f5e28a6060 (patch)
treeb7f5ec18a190ad70fce43af7a8a98aad54741592 /sys-utils/lsns.c
parentlsns: add a case for testing netnsid column (diff)
downloadkernel-qcow2-util-linux-74d2056ae85f256ed35cbc55771887f5e28a6060.tar.gz
kernel-qcow2-util-linux-74d2056ae85f256ed35cbc55771887f5e28a6060.tar.xz
kernel-qcow2-util-linux-74d2056ae85f256ed35cbc55771887f5e28a6060.zip
lsns: add nsfs column
nsfs provides kernel level interface for assigning logical name to a namespace. Following message is quoted from git log of linux kernel: commit 0226f4923f6c9b40cfa1c1c1b19a6ac6b3924ead Author: Al Viro <viro@zeniv.linux.org.uk> Date: Tue Dec 6 12:21:54 2011 -0500 vfs: take /proc/*/mounts and friends to fs/proc_namespace.c rationale: that stuff is far tighter bound to fs/namespace.c than to the guts of procfs proper. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> /proc/self/mountinfo lists the logical names for namespaces: ... 652 81 0:3 net:[4026532579] /tmp/XYZ rw shared:192 - nsfs nsfs rw,seclabel ... In the lines /tmp/XYZ is a logical name for 4026532579 of net namespace. This patch adds nsfs column. It seems that the logical name is used only in "ip netns" now. So the column is disabled by default. Use '--type=net' or '-o NSFS' options to enable it. This feature and the way to implementation using multi lines in a column is Suggested by Karel Zak. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Diffstat (limited to 'sys-utils/lsns.c')
-rw-r--r--sys-utils/lsns.c108
1 files changed, 104 insertions, 4 deletions
diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c
index bb7d3956d..c4d806e24 100644
--- a/sys-utils/lsns.c
+++ b/sys-utils/lsns.c
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <wchar.h>
#include <libsmartcols.h>
+#include <libmount.h>
#ifdef HAVE_LINUX_NET_NAMESPACE_H
#include <stdbool.h>
@@ -78,7 +79,8 @@ enum {
COL_COMMAND,
COL_UID,
COL_USER,
- COL_NETNSID
+ COL_NETNSID,
+ COL_NSFS,
};
/* column names */
@@ -100,7 +102,8 @@ static const struct colinfo infos[] = {
[COL_COMMAND] = { "COMMAND", 0, SCOLS_FL_TRUNC, N_("command line of the PID")},
[COL_UID] = { "UID", 0, SCOLS_FL_RIGHT, N_("UID of the PID")},
[COL_USER] = { "USER", 0, 0, N_("username of the PID")},
- [COL_NETNSID] = { "NETNSID", 0, SCOLS_FL_RIGHT, N_("Net namespace ID")}
+ [COL_NETNSID] = { "NETNSID", 0, SCOLS_FL_RIGHT, N_("Net namespace ID")},
+ [COL_NSFS] = { "NSFS", 0, SCOLS_FL_WRAP, N_("Logical name established by nsfs")}
};
static int columns[ARRAY_SIZE(infos) * 2];
@@ -171,6 +174,8 @@ struct lsns {
list : 1,
notrunc : 1,
no_headings: 1;
+
+ struct libmnt_table *tab;
};
struct netnsid_cache {
@@ -612,6 +617,80 @@ static int read_namespaces(struct lsns *ls)
return 0;
}
+static int find_nsfs_in_tab(struct libmnt_fs *fs, void *data)
+{
+ return (mnt_fs_match_fstype(fs, "nsfs") &&
+ (strcmp(mnt_fs_get_root(fs), (char *)data) == 0));
+}
+
+static bool str_includes_path(const char *path_set, const char *elt,
+ const char sep)
+{
+ size_t elt_len;
+ size_t path_set_len;
+ char *tmp;
+
+
+ tmp = strstr(path_set, elt);
+ if (!tmp)
+ return false;
+
+ elt_len = strlen(elt);
+ path_set_len = strlen(path_set);
+
+ /* path_set includes only elt or
+ * path_set includes elt as the first element.
+ */
+ if (tmp == path_set
+ && ((path_set_len == elt_len)
+ || (path_set[elt_len] == sep)))
+ return true;
+ /* path_set includes elt at the middle
+ * or as the last element.
+ */
+ if ((*(tmp - 1) == sep)
+ && ((*(tmp + elt_len) == sep)
+ || (*(tmp + elt_len) == '\0')))
+ return true;
+
+ return false;
+}
+
+static int nsfs_xasputs(char **str,
+ struct lsns_namespace *ns,
+ struct libmnt_table *tab,
+ char sep)
+{
+ struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_FORWARD);
+ char *expected_root;
+ char *tmp;
+
+ xasprintf(&expected_root, "%s:[%lu]", ns_names[ns->type], ns->id);
+
+ tmp = NULL;
+ while (1) {
+ struct libmnt_fs *fs = NULL;
+
+ if (mnt_table_find_next_fs(tab, itr, find_nsfs_in_tab,
+ expected_root, &fs) != 0)
+ break;
+ if (tmp == NULL) {
+ xasprintf(str, "%s", mnt_fs_get_target(fs));
+ tmp = *str;
+ } else if (!str_includes_path(*str, mnt_fs_get_target(fs),
+ sep)) {
+ *str = NULL;
+ xasprintf(str, "%s%c%s",
+ tmp, sep, mnt_fs_get_target(fs));
+ free(tmp);
+ tmp = *str;
+ }
+ }
+ free(expected_root);
+ mnt_free_iter(itr);
+
+ return 1;
+}
static void add_scols_line(struct lsns *ls, struct libscols_table *table,
struct lsns_namespace *ns, struct lsns_process *proc)
{
@@ -665,6 +744,10 @@ static void add_scols_line(struct lsns *ls, struct libscols_table *table,
if (ns->type == LSNS_ID_NET)
netnsid_xasputs(&str, proc->netnsid);
break;
+ case COL_NSFS:
+ nsfs_xasputs(&str, ns, ls->tab,
+ ls->raw ? ',' : '\n');
+ break;
default:
break;
}
@@ -697,16 +780,25 @@ static struct libscols_table *init_scols_table(struct lsns *ls)
for (i = 0; i < ncolumns; i++) {
const struct colinfo *col = get_column_info(i);
int flags = col->flags;
+ struct libscols_column *cl;
if (ls->notrunc)
flags &= ~SCOLS_FL_TRUNC;
if (ls->tree && get_column_id(i) == COL_COMMAND)
flags |= SCOLS_FL_TREE;
- if (!scols_table_new_column(tab, col->name, col->whint, flags)) {
+ cl = scols_table_new_column(tab, col->name, col->whint, flags);
+ if (cl == NULL) {
warnx(_("failed to initialize output column"));
goto err;
}
+ if (get_column_id(i) == COL_NSFS) {
+ scols_column_set_wrapfunc(cl,
+ scols_wrapnl_chunksize,
+ scols_wrapnl_nextchunk,
+ NULL);
+ scols_column_set_safechars(cl, "\n");
+ }
}
return tab;
@@ -928,8 +1020,10 @@ int main(int argc, char *argv[])
columns[ncolumns++] = COL_NPROCS;
columns[ncolumns++] = COL_PID;
columns[ncolumns++] = COL_USER;
- if (enabling_netnsid)
+ if (enabling_netnsid) {
columns[ncolumns++] = COL_NETNSID;
+ columns[ncolumns++] = COL_NSFS;
+ }
columns[ncolumns++] = COL_COMMAND;
}
@@ -956,6 +1050,11 @@ int main(int argc, char *argv[])
if (enabling_netnsid)
netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
#endif
+
+ ls.tab = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);
+ if (!ls.tab)
+ err(MNT_EX_FAIL, _("failed to parse %s"), _PATH_PROC_MOUNTINFO);
+
r = read_processes(&ls);
if (!r)
r = read_namespaces(&ls);
@@ -970,6 +1069,7 @@ int main(int argc, char *argv[])
r = show_namespaces(&ls);
}
+ mnt_free_table(ls.tab);
if (netlink_fd >= 0)
close(netlink_fd);
free_idcache(uid_cache);