]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount; fix and improve read+poll mountinfo
authorKarel Zak <kzak@redhat.com>
Thu, 29 Aug 2019 13:50:58 +0000 (15:50 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 29 Aug 2019 13:50:58 +0000 (15:50 +0200)
* fix read() buffer size (stupid bug...)

* split read() EINTR and poll() based attempts

* use 100 attempts

* wait 10000 usec between attempts, but first 10 attempts are without
  this delay. It makes the function usable for usual use-cases as well
  as on very busy systems (successfully tested with 300 concurrent
  mount/umount processes)

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/utils.c

index 5b30f2ac0756e58a11093f71362da3aaa4c50fe1..356174244c272f3542a4a419c63f80a878796529 100644 (file)
@@ -1162,22 +1162,22 @@ done:
 static int read_procfs_file(int fd, char **buf, size_t *bufsiz)
 {
        size_t bufmax = 0;
 static int read_procfs_file(int fd, char **buf, size_t *bufsiz)
 {
        size_t bufmax = 0;
-       int rc = 0, tries = 0;
-       char *bufptr;
+       int rc = 0, tries = 0, ninters = 0;
+       char *bufptr = NULL;;
 
        assert(buf);
        assert(bufsiz);
 
        *bufsiz = 0;
 
        assert(buf);
        assert(bufsiz);
 
        *bufsiz = 0;
+       *buf = NULL;
 
        do {
                ssize_t ret;
 
 
        do {
                ssize_t ret;
 
-               if (bufmax == *bufsiz) {
+               if (!bufptr || bufmax == *bufsiz) {
                        char *tmp;
 
                        bufmax = bufmax ? bufmax * 2 : (16 * 1024);
                        char *tmp;
 
                        bufmax = bufmax ? bufmax * 2 : (16 * 1024);
-
                        tmp = realloc(*buf, bufmax);
                        if (!tmp)
                                break;
                        tmp = realloc(*buf, bufmax);
                        if (!tmp)
                                break;
@@ -1186,13 +1186,12 @@ static int read_procfs_file(int fd, char **buf, size_t *bufsiz)
                }
 
                errno = 0;
                }
 
                errno = 0;
-               ret = read(fd, bufptr, bufmax);
+               ret = read(fd, bufptr, bufmax - *bufsiz);
 
                if (ret < 0) {
                        /* error */
 
                if (ret < 0) {
                        /* error */
-                       if (errno == EAGAIN || errno == EINTR) {
-                               xusleep(250000);
-                               tries++;
+                       if ((errno == EAGAIN || errno == EINTR) && (ninters++ < 5)) {
+                               xusleep(200000);
                                continue;
                        }
                        break;
                                continue;
                        }
                        break;
@@ -1213,18 +1212,22 @@ static int read_procfs_file(int fd, char **buf, size_t *bufsiz)
                                *bufsiz = 0;
                                bufptr = *buf;
                                tries++;
                                *bufsiz = 0;
                                bufptr = *buf;
                                tries++;
+
+                               if (tries > 10)
+                                       /* busy system? -- wait */
+                                       xusleep(10000);
                                continue;
                        }
 
                        /* successful read() without active poll() */
                                continue;
                        }
 
                        /* successful read() without active poll() */
-                       *bufsiz += (size_t) ret;
+                       (*bufsiz) += (size_t) ret;
                        bufptr += ret;
                        bufptr += ret;
-                       tries = 0;
+                       tries = ninters = 0;
                } else {
                        /* end-of-file */
                        goto success;
                }
                } else {
                        /* end-of-file */
                        goto success;
                }
-       } while (tries <= 5);
+       } while (tries <= 100);
 
        rc = errno ? -errno : 1;
        free(*buf);
 
        rc = errno ? -errno : 1;
        free(*buf);