[PATCH v2] fstools: blockd Check /tmp/run/blockd for existing mounts

David Adair djabhead at aol.com
Sun Jun 13 02:01:04 PDT 2021


Currently volume names can not match rootfs files/directories
so LV names like "home" "usr" or "www" are not allowed.

This changes the check for existing mount points to
examine /tmp/run/blockd/<newdev> instead of /<newdev>.

It also checks that a link is present at
/mnt/<newdev> and skips the request if it is missing
e.g. the "map" does not support the requested "key".

This aligns the mount logic to match the automount
daemon indirect.c logic from kernel.org.
 - If mountpoint exist and is not a zombie return success.
 - If mountpoint is a zombie delete it.
 - If map is missing or mount fails return failure.

This greatly simplifies hotplug-remove since we leave
devices alone once link is removed.  It also fixes most
instances of poision directories remaining in automount
dir and causing "too many symlinks" errors.

Signed-off-by: David Adair <djabhead at aol.com>
---
 blockd.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/blockd.c b/blockd.c
index d6dfeb8..6024c60 100644
--- a/blockd.c
+++ b/blockd.c
@@ -41,6 +41,7 @@ struct device {
 
 static struct uloop_fd fd_autofs_read;
 static int fd_autofs_write = 0;
+static struct stat autofs_mp_stat;
 static struct ubus_auto_conn conn;
 struct blob_buf bb = { 0 };
 
@@ -501,8 +502,10 @@ static void autofs_read_handler(struct uloop_fd *u, unsigned int events)
 {
 	union autofs_v5_packet_union pktu;
 	const struct autofs_v5_packet *pkt;
-	int cmd = AUTOFS_IOC_READY;
 	struct stat st;
+	struct device *device;
+	char *mnt;
+	int cmd = AUTOFS_IOC_READY;
 
 	while (read(u->fd, &pktu, sizeof(pktu)) == -1) {
 		if (errno != EINTR)
@@ -517,9 +520,24 @@ static void autofs_read_handler(struct uloop_fd *u, unsigned int events)
 
 	pkt = &pktu.missing_indirect;
         ULOG_ERR("kernel is requesting a mount -> %s\n", pkt->name);
-	if (lstat(pkt->name, &st) == -1)
-		if (block("autofs", "add", (char *)pkt->name))
+	/*
+	 * if MP exists send "ready"
+	 *   second part of check detects zombie mounts --
+	 *   valid target should have target dev not autofs.
+	 */
+	if (asprintf(&mnt, "%s%s", AUTOFS_MOUNT_PATH, pkt->name) == -1)
+		exit(ENOMEM);
+	if ((lstat(mnt, &st) == -1) ||
+	    (S_ISDIR(st.st_mode) && st.st_dev == autofs_mp_stat.st_dev)) {
+		rmdir(mnt);
+		device = vlist_find(&devices, pkt->name, device, node);
+		/* Map doesn't exist or mount fails send "fail" */
+		if (!device || !device->target ||
+		    lstat(device->target, &st) || ! S_ISLNK(st.st_mode) ||
+		    block("autofs", "add", (char *)pkt->name))
 			cmd = AUTOFS_IOC_FAIL;
+	}
+	free(mnt);
 
 	if (ioctl(fd_autofs_write, cmd, pkt->wait_queue_token) < 0)
 		ULOG_ERR("failed to report back to kernel\n");
@@ -562,6 +580,7 @@ static int autofs_mount(void)
 		return -1;
 	}
 	close(pipefd[1]);
+	stat(AUTOFS_MOUNT_PATH, &autofs_mp_stat);
 	fd_autofs_read.fd = pipefd[0];
 	fd_autofs_read.cb = autofs_read_handler;
 	uloop_fd_add(&fd_autofs_read, ULOOP_READ);
-- 
2.27.0






More information about the openwrt-devel mailing list