+2003-05-21 NeilBrown <neilb@cse.unsw.edu.au>
+
+ * utils/exportfs/exportfs.c: Use check_new_cache and cache_flush
+ Don't actually talk to kernel when new cache is in effect, except
+ to flush
+ * utils/exportfs/exportfs.c: add -f option to fully flush cache.
+ * support/export/xtab.c: Only rename new xtab into place if it has
+ changed, thus preserving modify date for exportfs to use when
+ flushing.
+ * support/nfs/cacheio.c: Add cache_flush
+ * support/export/xtab.c: Only rename new xtab into place if it has
+ changed, thus preserving modify date for exportfs to use when
+ flushing.
+
2003-05-21 NeilBrown <neilb@cse.unsw.edu.au>
* support/export/client.c: Add client_compose, client_member to
#include "xio.h"
#include "xlog.h"
+static void cond_rename(char *newfile, char *oldfile);
+
static int
xtab_read(char *xtab, int is_export)
{
}
endexportent();
- rename(xtabtmp, xtab);
+ cond_rename(xtabtmp, xtab);
xfunlock(lockid);
exp->m_xtabent = 1;
}
+/*
+ * rename newfile onto oldfile unless
+ * they are identical
+ */
+static void cond_rename(char *newfile, char *oldfile)
+{
+ int nfd, ofd;
+ char nbuf[4096], obuf[4096];
+ int ncnt, ocnt;
+
+ nfd = open(newfile, 0);
+ if (nfd < 0)
+ return;
+ ofd = open(oldfile, 0);
+ if (ofd < 0) {
+ close(nfd);
+ rename(newfile, oldfile);
+ return;
+ }
+
+ do {
+ ncnt = read(nfd, nbuf, sizeof(nbuf));
+ if (ncnt < 0)
+ break;
+ ocnt = read(ofd, obuf, sizeof(obuf));
+ if (ocnt < 0)
+ break;
+ if (ncnt != ocnt)
+ break;
+ if (ncnt == 0) {
+ close(nfd);
+ close(ofd);
+ unlink(newfile);
+ return;
+ }
+ } while (memcmp(obuf, nbuf, ncnt) == 0);
+
+ /* some mis-match */
+ close(nfd);
+ close(ofd);
+ rename(newfile, oldfile);
+ return;
+}
int readline(int fd, char **buf, int *lenp);
int qword_get(char **bpp, char *dest, int bufsize);
int qword_get_int(char **bpp, int *anint);
+void cache_flush(int force);
int check_new_cache(void);
/* lockd. */
return (stat("/proc/fs/nfs/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];
+ static char *cachelist[] = {
+ "auth.unix.ip",
+ "nfsd.export",
+ "nfsd.fh",
+ NULL
+ };
+ stb.st_mtime = time(0);
+ if (!force)
+ stat(_PATH_ETAB, &stb);
+
+ 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) {
+ write(fd, stime, strlen(stime));
+ close(fd);
+ }
+ }
+}
int f_reexport = 0;
int f_ignore = 0;
int i, c;
+ int new_cache = 0;
+ int force_flush = 0;
xlog_open("exportfs");
export_errno = 0;
- while ((c = getopt(argc, argv, "aio:ruv")) != EOF) {
+ while ((c = getopt(argc, argv, "aio:ruvf")) != EOF) {
switch(c) {
case 'a':
f_all = 1;
case 'v':
f_verbose = 1;
break;
+ case 'f':
+ force_flush = 1;
+ break;
default:
usage();
break;
return 0;
}
+ new_cache = check_new_cache();
+
if (f_export && ! f_ignore)
export_read(_PATH_EXPORTS);
if (f_export) {
unexportfs(argv[i], f_verbose);
rmtab_read();
}
- xtab_mount_read();
- exports_update(f_verbose);
+ if (!new_cache) {
+ xtab_mount_read();
+ exports_update(f_verbose);
+ }
xtab_export_write();
- xtab_mount_write();
+ if (new_cache)
+ cache_flush(force_flush);
+ if (!new_cache)
+ xtab_mount_write();
return export_errno;
}
hname)))
continue;
if (verbose) {
+#if 0
if (exp->m_exported) {
printf("unexporting %s:%s from kernel\n",
exp->m_client->m_hostname,
exp->m_export.e_path);
}
- else {
+ else
+#endif
printf("unexporting %s:%s\n",
exp->m_client->m_hostname,
exp->m_export.e_path);
- }
}
+#if 0
if (exp->m_exported && !export_unexport(exp))
error(exp, errno);
+#endif
exp->m_xtabent = 0;
exp->m_mayexport = 0;
}