X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=support%2Fnfs%2Fcacheio.c;h=9d271cd4733d77328a6f2b3e5ec8a80b5da8a73b;hb=12e990f4b07172c693203ffd1e12d0518cacb9e6;hp=2af4fa3e3e8ce58b319c06cbb0253f2aca792221;hpb=1275be70ca6cd6c4bec07a3381f7b510086c5526;p=nfs-utils.git diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c index 2af4fa3..9d271cd 100644 --- a/support/nfs/cacheio.c +++ b/support/nfs/cacheio.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -109,10 +110,21 @@ 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"); - fflush(f); + err = fflush(f); + /* + * 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: + */ + __fpurge(f); + return fflush(f); } @@ -205,16 +217,17 @@ int readline(int fd, char **buf, int *lenp) */ char *new; int nl; - *lenp += 128; + *lenp *= 2; 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; } @@ -227,6 +240,53 @@ int check_new_cache(void) { struct stat stb; - return (stat("/proc/fs/nfs/filehandle", &stb) == 0); + return (stat("/proc/fs/nfs/filehandle", &stb) == 0) || + (stat("/proc/fs/nfsd/filehandle", &stb) == 0); } + +/* flush the kNFSd caches. + * Set the flush time to the mtime of _PATH_ETAB or + * if force, to now. + * the caches to flush are: + * auth.unix.ip nfsd.export nfsd.fh + */ + +void +cache_flush(int force) +{ + struct stat stb; + 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", + "auth.unix.gid", + "nfsd.fh", + "nfsd.export", + NULL + }; + 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++) { + int fd; + sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]); + fd = open(path, O_RDWR); + if (fd >= 0) { + write(fd, stime, strlen(stime)); + close(fd); + } + } +}