* 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>
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;
- 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;
- 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);
*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;
} else {
/* end-of-file */
goto success;
}
} else {
/* end-of-file */
goto success;
}
+ } while (tries <= 100);
rc = errno ? -errno : 1;
free(*buf);
rc = errno ? -errno : 1;
free(*buf);