[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20231009182753.851551-3-toke@redhat.com>
Date: Mon, 9 Oct 2023 20:27:50 +0200
From: Toke Høiland-Jørgensen <toke@...hat.com>
To: David Ahern <dsahern@...il.com>,
Stephen Hemminger <stephen@...workplumber.org>
Cc: netdev@...r.kernel.org,
Toke Høiland-Jørgensen <toke@...hat.com>,
Nicolas Dichtel <nicolas.dichtel@...nd.com>,
Christian Brauner <brauner@...nel.org>,
"Eric W . Biederman" <ebiederm@...ssion.com>,
David Laight <David.Laight@...LAB.COM>
Subject: [RFC PATCH iproute2-next 2/5] ip: Split out code creating namespace mount dir so it can be reused
Move the code creating the parent directory for namespace references into its
own function, so it can be reused for creating a separate directory to contain
mount namespace references.
No functional change is intended with this patch.
Signed-off-by: Toke Høiland-Jørgensen <toke@...hat.com>
---
ip/ipnetns.c | 127 ++++++++++++++++++++++++++++-----------------------
1 file changed, 69 insertions(+), 58 deletions(-)
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index a05d84514326..529790482683 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -758,13 +758,13 @@ static int netns_delete(int argc, char **argv)
return on_netns_del(argv[0], NULL);
}
-static int create_netns_dir(void)
+static int ensure_dir(const char *path)
{
/* Create the base netns directory if it doesn't exist */
- if (mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
+ if (mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
if (errno != EEXIST) {
fprintf(stderr, "mkdir %s failed: %s\n",
- NETNS_RUN_DIR, strerror(errno));
+ path, strerror(errno));
return -1;
}
}
@@ -899,53 +899,15 @@ static pid_t bind_ns_files_from_child(const char *ns_name, pid_t target_pid,
exit(EXIT_SUCCESS);
}
-static int netns_add(int argc, char **argv, bool create)
+static int prepare_ns_mount_dir(const char *target_dir, int mount_flag)
{
- /* This function creates a new network namespace and
- * a new mount namespace and bind them into a well known
- * location in the filesystem based on the name provided.
- *
- * If create is true, a new namespace will be created,
- * otherwise an existing one will be attached to the file.
- *
- * The mount namespace is created so that any necessary
- * userspace tweaks like remounting /sys, or bind mounting
- * a new /etc/resolv.conf can be shared between users.
- */
- const char *name;
- pid_t pid, child;
- int event_fd;
+ int made_dir_mount = 0;
int lock;
- int made_netns_run_dir_mount = 0;
- if (create) {
- if (argc < 1) {
- fprintf(stderr, "No netns name specified\n");
- return -1;
- }
- pid = getpid();
- } else {
- if (argc < 2) {
- fprintf(stderr, "No netns name and PID specified\n");
- return -1;
- }
-
- if (get_s32(&pid, argv[1], 0) || !pid) {
- fprintf(stderr, "Invalid PID: %s\n", argv[1]);
- return -1;
- }
- }
- name = argv[0];
-
- if (create_netns_dir())
+ if (ensure_dir(target_dir))
return -1;
- /* Make it possible for network namespace mounts to propagate between
- * mount namespaces. This makes it likely that a unmounting a network
- * namespace file in one namespace will unmount the network namespace
- * file in all namespaces allowing the network namespace to be freed
- * sooner.
- * These setup steps need to happen only once, as if multiple ip processes
+ /* These setup steps need to happen only once, as if multiple ip processes
* try to attempt the same operation at the same time, the mountpoints will
* be recursively created multiple times, eventually causing the system
* to lock up. For example, this has been observed when multiple netns
@@ -955,23 +917,23 @@ static int netns_add(int argc, char **argv, bool create)
* this cannot happen, but proceed nonetheless if it cannot happen for any
* reason.
*/
- lock = open(NETNS_RUN_DIR, O_RDONLY|O_DIRECTORY, 0);
+ lock = open(target_dir, O_RDONLY|O_DIRECTORY, 0);
if (lock < 0) {
- fprintf(stderr, "Cannot open netns runtime directory \"%s\": %s\n",
- NETNS_RUN_DIR, strerror(errno));
+ fprintf(stderr, "Cannot open ns runtime directory \"%s\": %s\n",
+ target_dir, strerror(errno));
return -1;
}
if (flock(lock, LOCK_EX) < 0) {
- fprintf(stderr, "Warning: could not flock netns runtime directory \"%s\": %s\n",
- NETNS_RUN_DIR, strerror(errno));
+ fprintf(stderr, "Warning: could not flock ns runtime directory \"%s\": %s\n",
+ target_dir, strerror(errno));
close(lock);
lock = -1;
}
- while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
+ while (mount("", target_dir, "none", mount_flag | MS_REC, NULL)) {
/* Fail unless we need to make the mount point */
- if (errno != EINVAL || made_netns_run_dir_mount) {
+ if (errno != EINVAL || made_dir_mount) {
fprintf(stderr, "mount --make-shared %s failed: %s\n",
- NETNS_RUN_DIR, strerror(errno));
+ target_dir, strerror(errno));
if (lock != -1) {
flock(lock, LOCK_UN);
close(lock);
@@ -979,23 +941,72 @@ static int netns_add(int argc, char **argv, bool create)
return -1;
}
- /* Upgrade NETNS_RUN_DIR to a mount point */
- if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND | MS_REC, NULL)) {
+ /* Upgrade target directory to a mount point */
+ if (mount(target_dir, target_dir, "none", MS_BIND | MS_REC, NULL)) {
fprintf(stderr, "mount --bind %s %s failed: %s\n",
- NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
+ target_dir, target_dir, strerror(errno));
if (lock != -1) {
flock(lock, LOCK_UN);
close(lock);
}
return -1;
}
- made_netns_run_dir_mount = 1;
+ made_dir_mount = 1;
}
if (lock != -1) {
flock(lock, LOCK_UN);
close(lock);
}
+ return 0;
+}
+
+static int netns_add(int argc, char **argv, bool create)
+{
+ /* This function creates a new network namespace and
+ * a new mount namespace and bind them into a well known
+ * location in the filesystem based on the name provided.
+ *
+ * If create is true, a new namespace will be created,
+ * otherwise an existing one will be attached to the file.
+ *
+ * The mount namespace is created so that any necessary
+ * userspace tweaks like remounting /sys, or bind mounting
+ * a new /etc/resolv.conf can be shared between users.
+ */
+ const char *name;
+ pid_t pid, child;
+ int event_fd;
+
+ if (create) {
+ if (argc < 1) {
+ fprintf(stderr, "No netns name specified\n");
+ return -1;
+ }
+ pid = getpid();
+ } else {
+ if (argc < 2) {
+ fprintf(stderr, "No netns name and PID specified\n");
+ return -1;
+ }
+
+ if (get_s32(&pid, argv[1], 0) || !pid) {
+ fprintf(stderr, "Invalid PID: %s\n", argv[1]);
+ return -1;
+ }
+ }
+ name = argv[0];
+
+ /* Pass the MS_SHARED flag to the mount of the network namespace
+ * directory to make it possible for network namespace mounts to
+ * propagate between mount namespaces. This makes it likely that a
+ * unmounting a network namespace file in one namespace will unmount the
+ * network namespace file in all namespaces allowing the network
+ * namespace to be freed sooner.
+ */
+ if (prepare_ns_mount_dir(NETNS_RUN_DIR, MS_SHARED))
+ return -1;
+
child = bind_ns_files_from_child(name, pid, &event_fd);
if (child < 0)
exit(EXIT_FAILURE);
@@ -1079,7 +1090,7 @@ static int netns_monitor(int argc, char **argv)
return -1;
}
- if (create_netns_dir())
+ if (ensure_dir(NETNS_RUN_DIR))
return -1;
if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
--
2.42.0
Powered by blists - more mailing lists