5972c3
From 57898c3a7ee8fc5933cddd4526bb3980bef85a02 Mon Sep 17 00:00:00 2001
5972c3
From: Karel Zak <kzak@redhat.com>
5972c3
Date: Tue, 1 Sep 2020 10:15:14 +0200
5972c3
Subject: [PATCH] libmount: remove read-mountinfo workaround
5972c3
5972c3
This workaround has been introduced by
5972c3
http://github.com/karelzak/util-linux/commit/e4925f591c1bfb83719418b56b952830d15b77eb
5972c3
5972c3
And originally requested by https://github.com/systemd/systemd/issues/10872
5972c3
5972c3
It seems we do not need it anymore as the problem should be fixed in kernel since 5.8
5972c3
(kernel commit 9f6c61f96f2d97cbb5f7fa85607bc398f843ff0f).
5972c3
5972c3
Note that the libmount solution is very expensive as it repeats read()
5972c3
many times (until we get consistent result) if kernel is busy with
5972c3
mount table modification. This behaviour makes events management in
5972c3
systemd (or other places) pretty difficult as read mountinfo takes
5972c3
time on busy systems.
5972c3
5972c3
Addresses: https://github.com/systemd/systemd/pull/16537
5972c3
Signed-off-by: Karel Zak <kzak@redhat.com>
5972c3
---
5972c3
 configure.ac             |   1 -
5972c3
 libmount/src/mountP.h    |   2 -
5972c3
 libmount/src/tab_parse.c |  87 ++++----------------
5972c3
 libmount/src/utils.c     | 166 ---------------------------------------
5972c3
 4 files changed, 15 insertions(+), 241 deletions(-)
5972c3
5972c3
diff --git a/configure.ac b/configure.ac
5972c3
index 2d178f3af..1e31ca3e2 100644
5972c3
--- a/configure.ac
5972c3
+++ b/configure.ac
5972c3
@@ -504,7 +504,6 @@ AC_CHECK_FUNCS([ \
5972c3
 	err \
5972c3
 	errx \
5972c3
 	explicit_bzero \
5972c3
-	fmemopen \
5972c3
 	fsync \
5972c3
 	utimensat \
5972c3
 	getdomainname \
5972c3
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
5972c3
index d8ba0abad..ee97c6b4a 100644
5972c3
--- a/libmount/src/mountP.h
5972c3
+++ b/libmount/src/mountP.h
5972c3
@@ -98,7 +98,6 @@ extern int mnt_valid_tagname(const char *tagname);
5972c3
 extern int append_string(char **a, const char *b);
5972c3
 
5972c3
 extern const char *mnt_statfs_get_fstype(struct statfs *vfs);
5972c3
-extern int is_procfs_fd(int fd);
5972c3
 extern int is_file_empty(const char *name);
5972c3
 
5972c3
 extern int mnt_is_readonly(const char *path)
5972c3
@@ -124,7 +123,6 @@ extern void mnt_free_filesystems(char **filesystems);
5972c3
 extern char *mnt_get_kernel_cmdline_option(const char *name);
5972c3
 extern int mnt_stat_mountpoint(const char *target, struct stat *st);
5972c3
 extern int mnt_lstat_mountpoint(const char *target, struct stat *st);
5972c3
-extern FILE *mnt_get_procfs_memstream(int fd, char **membuf);
5972c3
 
5972c3
 /* tab.c */
5972c3
 extern int is_mountinfo(struct libmnt_table *tb);
5972c3
diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c
5972c3
index 329987bcb..ac12dce54 100644
5972c3
--- a/libmount/src/tab_parse.c
5972c3
+++ b/libmount/src/tab_parse.c
5972c3
@@ -694,7 +694,15 @@ static int kernel_fs_postparse(struct libmnt_table *tb,
5972c3
 	return rc;
5972c3
 }
5972c3
 
5972c3
-static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename)
5972c3
+/**
5972c3
+ * mnt_table_parse_stream:
5972c3
+ * @tb: tab pointer
5972c3
+ * @f: file stream
5972c3
+ * @filename: filename used for debug and error messages
5972c3
+ *
5972c3
+ * Returns: 0 on success, negative number in case of error.
5972c3
+ */
5972c3
+int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename)
5972c3
 {
5972c3
 	int rc = -1;
5972c3
 	int flags = 0;
5972c3
@@ -773,40 +781,6 @@ err:
5972c3
 	return rc;
5972c3
 }
5972c3
 
5972c3
-/**
5972c3
- * mnt_table_parse_stream:
5972c3
- * @tb: tab pointer
5972c3
- * @f: file stream
5972c3
- * @filename: filename used for debug and error messages
5972c3
- *
5972c3
- * Returns: 0 on success, negative number in case of error.
5972c3
- */
5972c3
-int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename)
5972c3
-{
5972c3
-	int fd, rc;
5972c3
-	FILE *memf = NULL;
5972c3
-	char *membuf = NULL;
5972c3
-
5972c3
-	/*
5972c3
-	 * For /proc/#/{mountinfo,mount} we read all file to memory and use it
5972c3
-	 * as memory stream. For more details see mnt_read_procfs_file().
5972c3
-	 */
5972c3
-	if ((fd = fileno(f)) >= 0
5972c3
-	    && (tb->fmt == MNT_FMT_GUESS ||
5972c3
-		tb->fmt == MNT_FMT_MOUNTINFO ||
5972c3
-		tb->fmt == MNT_FMT_MTAB)
5972c3
-	    && is_procfs_fd(fd)
5972c3
-	    && (memf = mnt_get_procfs_memstream(fd, &membuf))) {
5972c3
-
5972c3
-		rc = __table_parse_stream(tb, memf, filename);
5972c3
-		fclose(memf);
5972c3
-		free(membuf);
5972c3
-	} else
5972c3
-		rc = __table_parse_stream(tb, f, filename);
5972c3
-
5972c3
-	return rc;
5972c3
-}
5972c3
-
5972c3
 /**
5972c3
  * mnt_table_parse_file:
5972c3
  * @tb: tab pointer
5972c3
@@ -822,49 +796,18 @@ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filenam
5972c3
 int mnt_table_parse_file(struct libmnt_table *tb, const char *filename)
5972c3
 {
5972c3
 	FILE *f;
5972c3
-	int rc, fd = -1;
5972c3
+	int rc;
5972c3
 
5972c3
 	if (!filename || !tb)
5972c3
 		return -EINVAL;
5972c3
 
5972c3
-	/*
5972c3
-	 * Try to use read()+poll() to realiably read all
5972c3
-	 * /proc/#/{mount,mountinfo} file to memory
5972c3
-	 */
5972c3
-	if (tb->fmt != MNT_FMT_SWAPS
5972c3
-	    && strncmp(filename, "/proc/", 6) == 0) {
5972c3
-
5972c3
-		FILE *memf;
5972c3
-		char *membuf = NULL;
5972c3
-
5972c3
-		fd = open(filename, O_RDONLY|O_CLOEXEC);
5972c3
-		if (fd < 0) {
5972c3
-			rc = -errno;
5972c3
-			goto done;
5972c3
-		}
5972c3
-		memf = mnt_get_procfs_memstream(fd, &membuf);
5972c3
-		if (memf) {
5972c3
-			rc = __table_parse_stream(tb, memf, filename);
5972c3
-
5972c3
-			fclose(memf);
5972c3
-			free(membuf);
5972c3
-			close(fd);
5972c3
-			goto done;
5972c3
-		}
5972c3
-		/* else fallback to fopen/fdopen() */
5972c3
-	}
5972c3
-
5972c3
-	if (fd >= 0)
5972c3
-		f = fdopen(fd, "r" UL_CLOEXECSTR);
5972c3
-	else
5972c3
-		f = fopen(filename, "r" UL_CLOEXECSTR);
5972c3
-
5972c3
+	f = fopen(filename, "r" UL_CLOEXECSTR);
5972c3
 	if (f) {
5972c3
-		rc = __table_parse_stream(tb, f, filename);
5972c3
+		rc = mnt_table_parse_stream(tb, f, filename);
5972c3
 		fclose(f);
5972c3
 	} else
5972c3
 		rc = -errno;
5972c3
-done:
5972c3
+
5972c3
 	DBG(TAB, ul_debugobj(tb, "parsing done [filename=%s, rc=%d]", filename, rc));
5972c3
 	return rc;
5972c3
 }
5972c3
@@ -921,7 +864,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname)
5972c3
 
5972c3
 		f = fopen_at(dd, d->d_name, O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR);
5972c3
 		if (f) {
5972c3
-			__table_parse_stream(tb, f, d->d_name);
5972c3
+			mnt_table_parse_stream(tb, f, d->d_name);
5972c3
 			fclose(f);
5972c3
 		}
5972c3
 	}
5972c3
@@ -962,7 +905,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname)
5972c3
 		f = fopen_at(dirfd(dir), d->d_name,
5972c3
 				O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR);
5972c3
 		if (f) {
5972c3
-			__table_parse_stream(tb, f, d->d_name);
5972c3
+			mnt_table_parse_stream(tb, f, d->d_name);
5972c3
 			fclose(f);
5972c3
 		}
5972c3
 	}
5972c3
diff --git a/libmount/src/utils.c b/libmount/src/utils.c
5972c3
index 92829ebb0..40b45f11d 100644
5972c3
--- a/libmount/src/utils.c
5972c3
+++ b/libmount/src/utils.c
5972c3
@@ -19,7 +19,6 @@
5972c3
 #include <fcntl.h>
5972c3
 #include <pwd.h>
5972c3
 #include <grp.h>
5972c3
-#include <poll.h>
5972c3
 #include <blkid.h>
5972c3
 
5972c3
 #include "strutils.h"
5972c3
@@ -448,13 +447,6 @@ const char *mnt_statfs_get_fstype(struct statfs *vfs)
5972c3
 	return NULL;
5972c3
 }
5972c3
 
5972c3
-int is_procfs_fd(int fd)
5972c3
-{
5972c3
-	struct statfs sfs;
5972c3
-
5972c3
-	return fstatfs(fd, &sfs) == 0 && sfs.f_type == STATFS_PROC_MAGIC;
5972c3
-}
5972c3
-
5972c3
 /**
5972c3
  * mnt_match_fstype:
5972c3
  * @type: filesystem type
5972c3
@@ -1174,164 +1166,7 @@ done:
5972c3
 	return 1;
5972c3
 }
5972c3
 
5972c3
-#if defined(HAVE_FMEMOPEN) || defined(TEST_PROGRAM)
5972c3
-
5972c3
-/*
5972c3
- * This function tries to minimize possible races when we read
5972c3
- * /proc/#/{mountinfo,mount} files.
5972c3
- *
5972c3
- * The idea is to minimize number of read()s and check by poll() that during
5972c3
- * the read the mount table has not been modified. If yes, than re-read it
5972c3
- * (with some limitations to avoid never ending loop).
5972c3
- *
5972c3
- * Returns: <0 error, 0 success, 1 too many attempts
5972c3
- */
5972c3
-static int read_procfs_file(int fd, char **buf, size_t *bufsiz)
5972c3
-{
5972c3
-	size_t bufmax = 0;
5972c3
-	int rc = 0, tries = 0, ninters = 0;
5972c3
-	char *bufptr = NULL;
5972c3
-
5972c3
-	assert(buf);
5972c3
-	assert(bufsiz);
5972c3
-
5972c3
-	*bufsiz = 0;
5972c3
-	*buf = NULL;
5972c3
-
5972c3
-	do {
5972c3
-		ssize_t ret;
5972c3
-
5972c3
-		if (!bufptr || bufmax == *bufsiz) {
5972c3
-			char *tmp;
5972c3
-
5972c3
-			bufmax = bufmax ? bufmax * 2 : (16 * 1024);
5972c3
-			tmp = realloc(*buf, bufmax);
5972c3
-			if (!tmp)
5972c3
-				break;
5972c3
-			*buf = tmp;
5972c3
-			bufptr = tmp + *bufsiz;
5972c3
-		}
5972c3
-
5972c3
-		errno = 0;
5972c3
-		ret = read(fd, bufptr, bufmax - *bufsiz);
5972c3
-
5972c3
-		if (ret < 0) {
5972c3
-			/* error */
5972c3
-			if ((errno == EAGAIN || errno == EINTR) && (ninters++ < 5)) {
5972c3
-				xusleep(200000);
5972c3
-				continue;
5972c3
-			}
5972c3
-			break;
5972c3
-
5972c3
-		} if (ret > 0) {
5972c3
-			/* success -- verify no event during read */
5972c3
-			struct pollfd fds[] = {
5972c3
-				{ .fd = fd, .events = POLLPRI }
5972c3
-			};
5972c3
-
5972c3
-			rc = poll(fds, 1, 0);
5972c3
-			if (rc < 0)
5972c3
-				break;		/* poll() error */
5972c3
-			if (rc > 0) {
5972c3
-				/* event -- read all again */
5972c3
-				if (lseek(fd, 0, SEEK_SET) != 0)
5972c3
-					break;
5972c3
-				*bufsiz = 0;
5972c3
-				bufptr = *buf;
5972c3
-				tries++;
5972c3
-
5972c3
-				if (tries > 10)
5972c3
-					/* busy system? -- wait */
5972c3
-					xusleep(10000);
5972c3
-				continue;
5972c3
-			}
5972c3
-
5972c3
-			/* successful read() without active poll() */
5972c3
-			(*bufsiz) += (size_t) ret;
5972c3
-			bufptr += ret;
5972c3
-			tries = ninters = 0;
5972c3
-		} else {
5972c3
-			/* end-of-file */
5972c3
-			goto success;
5972c3
-		}
5972c3
-	} while (tries <= 100);
5972c3
-
5972c3
-	rc = errno ? -errno : 1;
5972c3
-	free(*buf);
5972c3
-	return rc;
5972c3
-
5972c3
-success:
5972c3
-	return 0;
5972c3
-}
5972c3
-
5972c3
-/*
5972c3
- * Create FILE stream for data from read_procfs_file()
5972c3
- */
5972c3
-FILE *mnt_get_procfs_memstream(int fd, char **membuf)
5972c3
-{
5972c3
-	size_t sz = 0;
5972c3
-	off_t cur;
5972c3
-
5972c3
-	*membuf = NULL;
5972c3
-
5972c3
-	/* in case of error, rewind to the original position */
5972c3
-	cur = lseek(fd, 0, SEEK_CUR);
5972c3
-
5972c3
-	if (read_procfs_file(fd, membuf, &sz) == 0 && sz > 0) {
5972c3
-		FILE *memf = fmemopen(*membuf, sz, "r");
5972c3
-		if (memf)
5972c3
-			return memf;	/* success */
5972c3
-
5972c3
-		free(*membuf);
5972c3
-		*membuf = NULL;
5972c3
-	}
5972c3
-
5972c3
-	/* error */
5972c3
-	if (cur != (off_t) -1)
5972c3
-		lseek(fd, cur, SEEK_SET);
5972c3
-	return NULL;
5972c3
-}
5972c3
-#else
5972c3
-FILE *mnt_get_procfs_memstream(int fd __attribute((__unused__)),
5972c3
-		               char **membuf __attribute((__unused__)))
5972c3
-{
5972c3
-	return NULL;
5972c3
-}
5972c3
-#endif /* HAVE_FMEMOPEN */
5972c3
-
5972c3
-
5972c3
 #ifdef TEST_PROGRAM
5972c3
-static int test_proc_read(struct libmnt_test *ts, int argc, char *argv[])
5972c3
-{
5972c3
-	char *buf = NULL;
5972c3
-	char *filename = argv[1];
5972c3
-	size_t bufsiz = 0;
5972c3
-	int rc = 0, fd = open(filename, O_RDONLY);
5972c3
-
5972c3
-	if (fd <= 0) {
5972c3
-		warn("%s: cannot open", filename);
5972c3
-		return -errno;
5972c3
-	}
5972c3
-
5972c3
-	rc = read_procfs_file(fd, &buf, &bufsiz);
5972c3
-	close(fd);
5972c3
-
5972c3
-	switch (rc) {
5972c3
-	case 0:
5972c3
-		fwrite(buf, 1, bufsiz, stdout);
5972c3
-		free(buf);
5972c3
-		break;
5972c3
-	case 1:
5972c3
-		warnx("too many attempts");
5972c3
-		break;
5972c3
-	default:
5972c3
-		warn("%s: cannot read", filename);
5972c3
-		break;
5972c3
-	}
5972c3
-
5972c3
-	return rc;
5972c3
-}
5972c3
-
5972c3
 static int test_match_fstype(struct libmnt_test *ts, int argc, char *argv[])
5972c3
 {
5972c3
 	char *type = argv[1];
5972c3
@@ -1513,7 +1348,6 @@ int main(int argc, char *argv[])
5972c3
 	{ "--guess-root",    test_guess_root,      "[<maj:min>]" },
5972c3
 	{ "--mkdir",         test_mkdir,           "<path>" },
5972c3
 	{ "--statfs-type",   test_statfs_type,     "<path>" },
5972c3
-	{ "--read-procfs",   test_proc_read,       "<path>" },
5972c3
 
5972c3
 	{ NULL }
5972c3
 	};
5972c3
-- 
5972c3
2.25.4
5972c3