From: Karel Zak Date: Thu, 29 Aug 2019 13:50:58 +0000 (+0200) Subject: libmount; fix and improve read+poll mountinfo X-Git-Tag: v2.35-rc1~255 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Futil-linux.git;a=commitdiff_plain;h=ee551c909f95437fd9fcd162f398c069d0ce9720 libmount; fix and improve read+poll mountinfo * 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 --- diff --git a/libmount/src/utils.c b/libmount/src/utils.c index 5b30f2ac07..356174244c 100644 --- a/libmount/src/utils.c +++ b/libmount/src/utils.c @@ -1162,22 +1162,22 @@ done: 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; + *buf = NULL; do { ssize_t ret; - if (bufmax == *bufsiz) { + if (!bufptr || bufmax == *bufsiz) { char *tmp; bufmax = bufmax ? bufmax * 2 : (16 * 1024); - 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; - ret = read(fd, bufptr, bufmax); + ret = read(fd, bufptr, bufmax - *bufsiz); if (ret < 0) { /* error */ - if (errno == EAGAIN || errno == EINTR) { - xusleep(250000); - tries++; + if ((errno == EAGAIN || errno == EINTR) && (ninters++ < 5)) { + xusleep(200000); continue; } break; @@ -1213,18 +1212,22 @@ static int read_procfs_file(int fd, char **buf, size_t *bufsiz) *bufsiz = 0; bufptr = *buf; tries++; + + if (tries > 10) + /* busy system? -- wait */ + xusleep(10000); continue; } /* successful read() without active poll() */ - *bufsiz += (size_t) ret; + (*bufsiz) += (size_t) ret; bufptr += ret; - tries = 0; + tries = ninters = 0; } else { /* end-of-file */ goto success; } - } while (tries <= 5); + } while (tries <= 100); rc = errno ? -errno : 1; free(*buf);