]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: remove read-mountinfo workaround
authorKarel Zak <kzak@redhat.com>
Tue, 1 Sep 2020 08:15:14 +0000 (10:15 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 1 Sep 2020 08:15:14 +0000 (10:15 +0200)
This workaround has been introduced by
http://github.com/karelzak/util-linux/commit/e4925f591c1bfb83719418b56b952830d15b77eb

And originally requested by https://github.com/systemd/systemd/issues/10872

It seems we do not need it anymore as the problem should be fixed in kernel since 5.8
(kernel commit 9f6c61f96f2d97cbb5f7fa85607bc398f843ff0f).

Note that the libmount solution is very expensive as it repeats read()
many times (until we get consistent result) if kernel is busy with
mount table modification. This behaviour makes events management in
systemd (or other places) pretty difficult as read mountinfo takes
time on busy systems.

Addresses: https://github.com/systemd/systemd/pull/16537
Signed-off-by: Karel Zak <kzak@redhat.com>
configure.ac
libmount/src/mountP.h
libmount/src/tab_parse.c
libmount/src/utils.c

index 2d178f3af45306d2a10ac34a484ad78d7894475a..1e31ca3e23f4fe6a90a2ef0def6ba6263296baf3 100644 (file)
@@ -504,7 +504,6 @@ AC_CHECK_FUNCS([ \
        err \
        errx \
        explicit_bzero \
-       fmemopen \
        fsync \
        utimensat \
        getdomainname \
index d8ba0abadb987d248fdff919ffbb0a8bd066fec8..ee97c6b4a387d5d443592e5dc397a5a5963b990a 100644 (file)
@@ -98,7 +98,6 @@ extern int mnt_valid_tagname(const char *tagname);
 extern int append_string(char **a, const char *b);
 
 extern const char *mnt_statfs_get_fstype(struct statfs *vfs);
-extern int is_procfs_fd(int fd);
 extern int is_file_empty(const char *name);
 
 extern int mnt_is_readonly(const char *path)
@@ -124,7 +123,6 @@ extern void mnt_free_filesystems(char **filesystems);
 extern char *mnt_get_kernel_cmdline_option(const char *name);
 extern int mnt_stat_mountpoint(const char *target, struct stat *st);
 extern int mnt_lstat_mountpoint(const char *target, struct stat *st);
-extern FILE *mnt_get_procfs_memstream(int fd, char **membuf);
 
 /* tab.c */
 extern int is_mountinfo(struct libmnt_table *tb);
index 329987bcb032c809b85608ac78d05aed5725b089..ac12dce54a4fd9a5cd56959ce17ef6afaed2619e 100644 (file)
@@ -694,7 +694,15 @@ static int kernel_fs_postparse(struct libmnt_table *tb,
        return rc;
 }
 
-static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename)
+/**
+ * mnt_table_parse_stream:
+ * @tb: tab pointer
+ * @f: file stream
+ * @filename: filename used for debug and error messages
+ *
+ * Returns: 0 on success, negative number in case of error.
+ */
+int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename)
 {
        int rc = -1;
        int flags = 0;
@@ -773,40 +781,6 @@ err:
        return rc;
 }
 
-/**
- * mnt_table_parse_stream:
- * @tb: tab pointer
- * @f: file stream
- * @filename: filename used for debug and error messages
- *
- * Returns: 0 on success, negative number in case of error.
- */
-int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename)
-{
-       int fd, rc;
-       FILE *memf = NULL;
-       char *membuf = NULL;
-
-       /*
-        * For /proc/#/{mountinfo,mount} we read all file to memory and use it
-        * as memory stream. For more details see mnt_read_procfs_file().
-        */
-       if ((fd = fileno(f)) >= 0
-           && (tb->fmt == MNT_FMT_GUESS ||
-               tb->fmt == MNT_FMT_MOUNTINFO ||
-               tb->fmt == MNT_FMT_MTAB)
-           && is_procfs_fd(fd)
-           && (memf = mnt_get_procfs_memstream(fd, &membuf))) {
-
-               rc = __table_parse_stream(tb, memf, filename);
-               fclose(memf);
-               free(membuf);
-       } else
-               rc = __table_parse_stream(tb, f, filename);
-
-       return rc;
-}
-
 /**
  * mnt_table_parse_file:
  * @tb: tab pointer
@@ -822,49 +796,18 @@ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filenam
 int mnt_table_parse_file(struct libmnt_table *tb, const char *filename)
 {
        FILE *f;
-       int rc, fd = -1;
+       int rc;
 
        if (!filename || !tb)
                return -EINVAL;
 
-       /*
-        * Try to use read()+poll() to realiably read all
-        * /proc/#/{mount,mountinfo} file to memory
-        */
-       if (tb->fmt != MNT_FMT_SWAPS
-           && strncmp(filename, "/proc/", 6) == 0) {
-
-               FILE *memf;
-               char *membuf = NULL;
-
-               fd = open(filename, O_RDONLY|O_CLOEXEC);
-               if (fd < 0) {
-                       rc = -errno;
-                       goto done;
-               }
-               memf = mnt_get_procfs_memstream(fd, &membuf);
-               if (memf) {
-                       rc = __table_parse_stream(tb, memf, filename);
-
-                       fclose(memf);
-                       free(membuf);
-                       close(fd);
-                       goto done;
-               }
-               /* else fallback to fopen/fdopen() */
-       }
-
-       if (fd >= 0)
-               f = fdopen(fd, "r" UL_CLOEXECSTR);
-       else
-               f = fopen(filename, "r" UL_CLOEXECSTR);
-
+       f = fopen(filename, "r" UL_CLOEXECSTR);
        if (f) {
-               rc = __table_parse_stream(tb, f, filename);
+               rc = mnt_table_parse_stream(tb, f, filename);
                fclose(f);
        } else
                rc = -errno;
-done:
+
        DBG(TAB, ul_debugobj(tb, "parsing done [filename=%s, rc=%d]", filename, rc));
        return rc;
 }
@@ -921,7 +864,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname)
 
                f = fopen_at(dd, d->d_name, O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR);
                if (f) {
-                       __table_parse_stream(tb, f, d->d_name);
+                       mnt_table_parse_stream(tb, f, d->d_name);
                        fclose(f);
                }
        }
@@ -962,7 +905,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname)
                f = fopen_at(dirfd(dir), d->d_name,
                                O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR);
                if (f) {
-                       __table_parse_stream(tb, f, d->d_name);
+                       mnt_table_parse_stream(tb, f, d->d_name);
                        fclose(f);
                }
        }
index 92829ebb01f267fb70e92dc835ccf407d289f178..40b45f11d8a92060f2706dd2fc64daaf75e3cd9b 100644 (file)
@@ -19,7 +19,6 @@
 #include <fcntl.h>
 #include <pwd.h>
 #include <grp.h>
-#include <poll.h>
 #include <blkid.h>
 
 #include "strutils.h"
@@ -448,13 +447,6 @@ const char *mnt_statfs_get_fstype(struct statfs *vfs)
        return NULL;
 }
 
-int is_procfs_fd(int fd)
-{
-       struct statfs sfs;
-
-       return fstatfs(fd, &sfs) == 0 && sfs.f_type == STATFS_PROC_MAGIC;
-}
-
 /**
  * mnt_match_fstype:
  * @type: filesystem type
@@ -1174,164 +1166,7 @@ done:
        return 1;
 }
 
-#if defined(HAVE_FMEMOPEN) || defined(TEST_PROGRAM)
-
-/*
- * This function tries to minimize possible races when we read
- * /proc/#/{mountinfo,mount} files.
- *
- * The idea is to minimize number of read()s and check by poll() that during
- * the read the mount table has not been modified. If yes, than re-read it
- * (with some limitations to avoid never ending loop).
- *
- * Returns: <0 error, 0 success, 1 too many attempts
- */
-static int read_procfs_file(int fd, char **buf, size_t *bufsiz)
-{
-       size_t bufmax = 0;
-       int rc = 0, tries = 0, ninters = 0;
-       char *bufptr = NULL;
-
-       assert(buf);
-       assert(bufsiz);
-
-       *bufsiz = 0;
-       *buf = NULL;
-
-       do {
-               ssize_t ret;
-
-               if (!bufptr || bufmax == *bufsiz) {
-                       char *tmp;
-
-                       bufmax = bufmax ? bufmax * 2 : (16 * 1024);
-                       tmp = realloc(*buf, bufmax);
-                       if (!tmp)
-                               break;
-                       *buf = tmp;
-                       bufptr = tmp + *bufsiz;
-               }
-
-               errno = 0;
-               ret = read(fd, bufptr, bufmax - *bufsiz);
-
-               if (ret < 0) {
-                       /* error */
-                       if ((errno == EAGAIN || errno == EINTR) && (ninters++ < 5)) {
-                               xusleep(200000);
-                               continue;
-                       }
-                       break;
-
-               } if (ret > 0) {
-                       /* success -- verify no event during read */
-                       struct pollfd fds[] = {
-                               { .fd = fd, .events = POLLPRI }
-                       };
-
-                       rc = poll(fds, 1, 0);
-                       if (rc < 0)
-                               break;          /* poll() error */
-                       if (rc > 0) {
-                               /* event -- read all again */
-                               if (lseek(fd, 0, SEEK_SET) != 0)
-                                       break;
-                               *bufsiz = 0;
-                               bufptr = *buf;
-                               tries++;
-
-                               if (tries > 10)
-                                       /* busy system? -- wait */
-                                       xusleep(10000);
-                               continue;
-                       }
-
-                       /* successful read() without active poll() */
-                       (*bufsiz) += (size_t) ret;
-                       bufptr += ret;
-                       tries = ninters = 0;
-               } else {
-                       /* end-of-file */
-                       goto success;
-               }
-       } while (tries <= 100);
-
-       rc = errno ? -errno : 1;
-       free(*buf);
-       return rc;
-
-success:
-       return 0;
-}
-
-/*
- * Create FILE stream for data from read_procfs_file()
- */
-FILE *mnt_get_procfs_memstream(int fd, char **membuf)
-{
-       size_t sz = 0;
-       off_t cur;
-
-       *membuf = NULL;
-
-       /* in case of error, rewind to the original position */
-       cur = lseek(fd, 0, SEEK_CUR);
-
-       if (read_procfs_file(fd, membuf, &sz) == 0 && sz > 0) {
-               FILE *memf = fmemopen(*membuf, sz, "r");
-               if (memf)
-                       return memf;    /* success */
-
-               free(*membuf);
-               *membuf = NULL;
-       }
-
-       /* error */
-       if (cur != (off_t) -1)
-               lseek(fd, cur, SEEK_SET);
-       return NULL;
-}
-#else
-FILE *mnt_get_procfs_memstream(int fd __attribute((__unused__)),
-                              char **membuf __attribute((__unused__)))
-{
-       return NULL;
-}
-#endif /* HAVE_FMEMOPEN */
-
-
 #ifdef TEST_PROGRAM
-static int test_proc_read(struct libmnt_test *ts, int argc, char *argv[])
-{
-       char *buf = NULL;
-       char *filename = argv[1];
-       size_t bufsiz = 0;
-       int rc = 0, fd = open(filename, O_RDONLY);
-
-       if (fd <= 0) {
-               warn("%s: cannot open", filename);
-               return -errno;
-       }
-
-       rc = read_procfs_file(fd, &buf, &bufsiz);
-       close(fd);
-
-       switch (rc) {
-       case 0:
-               fwrite(buf, 1, bufsiz, stdout);
-               free(buf);
-               break;
-       case 1:
-               warnx("too many attempts");
-               break;
-       default:
-               warn("%s: cannot read", filename);
-               break;
-       }
-
-       return rc;
-}
-
 static int test_match_fstype(struct libmnt_test *ts, int argc, char *argv[])
 {
        char *type = argv[1];
@@ -1513,7 +1348,6 @@ int main(int argc, char *argv[])
        { "--guess-root",    test_guess_root,      "[<maj:min>]" },
        { "--mkdir",         test_mkdir,           "<path>" },
        { "--statfs-type",   test_statfs_type,     "<path>" },
-       { "--read-procfs",   test_proc_read,       "<path>" },
 
        { NULL }
        };