netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Toke Høiland-Jørgensen" <toke@redhat.com>
To: David Ahern <dsahern@gmail.com>,
	Stephen Hemminger <stephen@networkplumber.org>
Cc: netdev@vger.kernel.org,
	"Toke Høiland-Jørgensen" <toke@redhat.com>,
	"Nicolas Dichtel" <nicolas.dichtel@6wind.com>,
	"Christian Brauner" <brauner@kernel.org>,
	"Eric W . Biederman" <ebiederm@xmission.com>,
	"David Laight" <David.Laight@ACULAB.COM>
Subject: [RFC PATCH iproute2-next 2/5] ip: Split out code creating namespace mount dir so it can be reused
Date: Mon,  9 Oct 2023 20:27:50 +0200	[thread overview]
Message-ID: <20231009182753.851551-3-toke@redhat.com> (raw)
In-Reply-To: <20231009182753.851551-1-toke@redhat.com>

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@redhat.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


  parent reply	other threads:[~2023-10-09 18:28 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-09 18:27 [RFC PATCH iproute2-next 0/5] Persisting of mount namespaces along with network namespaces Toke Høiland-Jørgensen
2023-10-09 18:27 ` [RFC PATCH iproute2-next 1/5] ip: Mount netns in child process instead of from inside the new namespace Toke Høiland-Jørgensen
2023-10-09 18:27 ` Toke Høiland-Jørgensen [this message]
2023-10-09 18:27 ` [RFC PATCH iproute2-next 3/5] lib/namespace: Factor out code for reuse Toke Høiland-Jørgensen
2023-10-09 18:27 ` [RFC PATCH iproute2-next 4/5] ip: Also create and persist mount namespace when creating netns Toke Høiland-Jørgensen
2023-10-09 18:27 ` [RFC PATCH iproute2-next 5/5] lib/namespace: Also mount a bpffs instance inside new mount namespaces Toke Høiland-Jørgensen
2023-10-09 20:32 ` [RFC PATCH iproute2-next 0/5] Persisting of mount namespaces along with network namespaces Eric W. Biederman
2023-10-09 22:03   ` Toke Høiland-Jørgensen
2023-10-10  0:14     ` Eric W. Biederman
2023-10-10 13:38       ` Toke Høiland-Jørgensen
2023-10-10 19:19         ` Eric W. Biederman
2023-10-11 13:49           ` Toke Høiland-Jørgensen
2023-10-11 14:55             ` Eric W. Biederman
2023-10-11 15:03               ` Toke Høiland-Jørgensen
2023-10-10  8:42   ` David Laight
2023-10-10 19:32     ` Eric W. Biederman
2023-10-10 21:51       ` David Laight

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231009182753.851551-3-toke@redhat.com \
    --to=toke@redhat.com \
    --cc=David.Laight@ACULAB.COM \
    --cc=brauner@kernel.org \
    --cc=dsahern@gmail.com \
    --cc=ebiederm@xmission.com \
    --cc=netdev@vger.kernel.org \
    --cc=nicolas.dichtel@6wind.com \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).