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
next prev 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).