X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fnfs%2Fcacheio.c;h=6a6ed5ac7f093a590e621895a03f2c9e3729683e;hp=20d195c16ca4b792fbb7b7866688e7993ab87db8;hb=965b4cf6398bed2a2c722b9d632b9674c228e36c;hpb=e09fbc8933961a0a774217ef32d73da373ddc670 diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c index 20d195c..6a6ed5a 100644 --- a/support/nfs/cacheio.c +++ b/support/nfs/cacheio.c @@ -17,12 +17,14 @@ #include #include +#include #include #include #include #include #include #include +#include void qword_add(char **bpp, int *lp, char *str) { @@ -87,13 +89,47 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen) *lp = len; } +void qword_addint(char **bpp, int *lp, int n) +{ + int len; + + len = snprintf(*bpp, *lp, "%d ", n); + if (len > *lp) + len = *lp; + *bpp += len; + *lp -= len; +} + +void qword_adduint(char **bpp, int *lp, unsigned int n) +{ + int len; + + len = snprintf(*bpp, *lp, "%u ", n); + if (len > *lp) + len = *lp; + *bpp += len; + *lp -= len; +} + +void qword_addeol(char **bpp, int *lp) +{ + if (*lp <= 0) + return; + **bpp = '\n'; + (*bpp)++; + (*lp)--; +} + static char qword_buf[8192]; void qword_print(FILE *f, char *str) { char *bp = qword_buf; int len = sizeof(qword_buf); qword_add(&bp, &len, str); - fwrite(qword_buf, bp-qword_buf, 1, f); + if (fwrite(qword_buf, bp-qword_buf, 1, f) != 1) { + xlog_warn("qword_print: fwrite failed: errno %d (%s)", + errno, strerror(errno)); + } } void qword_printhex(FILE *f, char *str, int slen) @@ -101,7 +137,10 @@ void qword_printhex(FILE *f, char *str, int slen) char *bp = qword_buf; int len = sizeof(qword_buf); qword_addhex(&bp, &len, str, slen); - fwrite(qword_buf, bp-qword_buf, 1, f); + if (fwrite(qword_buf, bp-qword_buf, 1, f) != 1) { + xlog_warn("qword_printhex: fwrite failed: errno %d (%s)", + errno, strerror(errno)); + } } void qword_printint(FILE *f, int num) @@ -109,10 +148,27 @@ void qword_printint(FILE *f, int num) fprintf(f, "%d ", num); } -void qword_eol(FILE *f) +int qword_eol(FILE *f) { + int err; + fprintf(f,"\n"); + err = fflush(f); + if (err) { + xlog_warn("qword_eol: fflush failed: errno %d (%s)", + errno, strerror(errno)); + } + /* + * We must send one line (and one line only) in a single write + * call. In case of a write error, libc may accumulate the + * unwritten data and try to write it again later, resulting in a + * multi-line write. So we must explicitly ask it to throw away + * any such cached data. But we return any original error + * indication to the caller. + */ + __fpurge(f); fflush(f); + return err; } @@ -180,23 +236,25 @@ int qword_get_int(char **bpp, int *anint) return 0; } +#define READLINE_BUFFER_INCREMENT 2048 + int readline(int fd, char **buf, int *lenp) { /* read a line into *buf, which is malloced *len long * realloc if needed until we find a \n * nul out the \n and return - * 0 of eof, 1 of success + * 0 on eof, 1 on success */ - int len = *lenp; + int len; - if (len == 0) { - char *b = malloc(128); + if (*lenp == 0) { + char *b = malloc(READLINE_BUFFER_INCREMENT); if (b == NULL) return 0; *buf = b; - *lenp = 128; + *lenp = READLINE_BUFFER_INCREMENT; } - len = read(fd, *buf, len); + len = read(fd, *buf, *lenp); if (len <= 0) return 0; while ((*buf)[len-1] != '\n') { @@ -205,16 +263,17 @@ int readline(int fd, char **buf, int *lenp) */ char *new; int nl; - *lenp += 128; + *lenp += READLINE_BUFFER_INCREMENT; new = realloc(*buf, *lenp); if (new == NULL) return 0; - nl = read(fd, *buf +len, *lenp - len); - if (nl <= 0 ) + *buf = new; + nl = read(fd, *buf + len, *lenp - len); + if (nl <= 0) return 0; - new += nl; + len += nl; } - (*buf)[len-1] = 0; + (*buf)[len-1] = '\0'; return 1; } @@ -246,15 +305,25 @@ cache_flush(int force) int c; char stime[20]; char path[200]; + time_t now; + /* Note: the order of these caches is important. + * They need to be flushed in dependancy order. So + * a cache that references items in another cache, + * as nfsd.fh entries reference items in nfsd.export, + * must be flushed before the cache that it references. + */ static char *cachelist[] = { "auth.unix.ip", - "nfsd.export", + "auth.unix.gid", "nfsd.fh", + "nfsd.export", NULL }; - stb.st_mtime = time(0); - if (!force) - stat(_PATH_ETAB, &stb); + now = time(0); + if (force || + stat(_PATH_ETAB, &stb) != 0 || + stb.st_mtime > now) + stb.st_mtime = time(0); sprintf(stime, "%ld\n", stb.st_mtime); for (c=0; cachelist[c]; c++) { @@ -262,7 +331,10 @@ cache_flush(int force) sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]); fd = open(path, O_RDWR); if (fd >= 0) { - write(fd, stime, strlen(stime)); + if (write(fd, stime, strlen(stime)) != strlen(stime)) { + xlog_warn("Writing to '%s' failed: errno %d (%s)", + path, errno, strerror(errno)); + } close(fd); } }