@@ -538,15 +538,16 @@ fedfsd_svc_create_junction_1(SVCXPRT *xprt)
}
result = fedfs_store_fsn(pathname, fsn_uuid, host);
- if (result != FEDFS_OK)
+ if (result != FEDFS_OK) {
xlog(D_GENERAL, "%s: fedfs_store_fsn", __func__);
- else {
- xlog(D_CALL, "%s: uuid: %s",
- __func__, fsn_uuid);
- xlog(D_CALL, "%s: nsdb: %s:%u",
- __func__, nsdb_hostname(host), nsdb_port(host));
+ goto out;
}
+ (void)junction_flush_exports_cache();
+ xlog(D_CALL, "%s: uuid: %s", __func__, fsn_uuid);
+ xlog(D_CALL, "%s: nsdb: %s:%u",
+ __func__, nsdb_hostname(host), nsdb_port(host));
+
out:
xlog(D_CALL, "%s: Replying with %s",
__func__, nsdb_display_fedfsstatus(result));
@@ -643,6 +644,7 @@ fedfsd_svc_delete_junction_1(SVCXPRT *xprt)
goto out;
fedfsd_rmdir(pathname);
+ (void)junction_flush_exports_cache();
result = FEDFS_OK;
out:
@@ -800,9 +802,11 @@ fedfsd_svc_lookup_junction_1(SVCXPRT *xprt)
result.status = FEDFS_ERR_BADXDR;
switch (args.resolve) {
case FEDFS_RESOLVE_NONE:
- case FEDFS_RESOLVE_CACHE:
case FEDFS_RESOLVE_NSDB:
break;
+ case FEDFS_RESOLVE_CACHE:
+ result.status = FEDFS_ERR_UNKNOWN_CACHE;
+ goto out;
default:
goto out;
}
@@ -839,7 +843,6 @@ fedfsd_svc_lookup_junction_1(SVCXPRT *xprt)
switch (args.resolve) {
case FEDFS_RESOLVE_NONE:
- case FEDFS_RESOLVE_CACHE:
break;
case FEDFS_RESOLVE_NSDB:
result.status = nsdb_open_nsdb(host, NULL, NULL, &ldap_err);
@@ -857,6 +860,12 @@ fedfsd_svc_lookup_junction_1(SVCXPRT *xprt)
break;
result.status = fedfsd_prepare_fedfsfsl_array(fsls, resok);
nsdb_free_fedfs_fsls(fsls);
+ if (result.status != FEDFS_OK)
+ break;
+ result.status = junction_flush_exports_cache();
+ if (result.status != FEDFS_OK &&
+ result.status != FEDFS_ERR_NO_CACHE_UPDATE)
+ result.status = FEDFS_OK;
break;
default:
result.status = FEDFS_ERR_SVRFAULT;
@@ -39,4 +39,6 @@ FedFsStatus fedfs_is_junction(const char *pathname);
FedFsStatus fedfs_save_mode(const char *pathname);
FedFsStatus fedfs_restore_mode(const char *pathname);
+FedFsStatus junction_flush_exports_cache(void);
+
#endif /* !_FEDFS_JUNCTION_H_ */
@@ -24,7 +24,7 @@
##
noinst_LTLIBRARIES = libjunction.la
-libjunction_la_SOURCES = junction.c
+libjunction_la_SOURCES = export-cache.c junction.c
CLEANFILES = cscope.in.out cscope.out cscope.po.out *~
DISTCLEANFILES = Makefile.in
new file mode 100644
@@ -0,0 +1,121 @@
+/**
+ * @file src/libjunction/export-cache.c
+ * @brief Try to flush NFSD's exports cache
+ */
+
+/*
+ * Copyright 2011 Oracle. All rights reserved.
+ *
+ * This file is part of fedfs-utils.
+ *
+ * fedfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2.0 as
+ * published by the Free Software Foundation.
+ *
+ * fedfs-utils is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License version 2.0 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2.0 along with fedfs-utils. If not, see:
+ *
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+//#include <errno.h>
+#include <time.h>
+
+
+#include "fedfs.h"
+#include "nsdb.h"
+#include "junction.h"
+#include "xlog.h"
+
+/**
+ * Ordered list of proc files to poke when requesting an NFSD cache flush
+ */
+static const char *junction_proc_files[] = {
+ "/proc/net/rpc/auth.unix.ip/flush",
+ "/proc/net/rpc/auth.unix.gid/flush",
+ "/proc/net/rpc/nfsd.fh/flush",
+ "/proc/net/rpc/nfsd.export/flush",
+ NULL,
+};
+
+/**
+ * Write time into one file
+ *
+ * @param pathname NUL-terminated C string containing POSIX pathname of file to write
+ * @param flushtime NUL-terminated C string containing current time in seconds since the Epoch
+ * @return a FedFsStatus code
+ */
+static FedFsStatus
+junction_write_time(const char *pathname, const char *flushtime)
+{
+ FedFsStatus retval;
+ ssize_t len;
+ int fd;
+
+ fd = open(pathname, O_RDWR);
+ if (fd == -1) {
+ xlog(D_GENERAL, "%s: Failed to open %s: %m",
+ __func__, pathname);
+ /* If the proc files don't exist, no server
+ * is running on this system */
+ return FEDFS_ERR_NO_CACHE_UPDATE;
+ }
+
+ len = write(fd, flushtime, strlen(flushtime));
+ if (len != (ssize_t)strlen(flushtime)) {
+ xlog(D_GENERAL, "%s: Failed to write %s: %m",
+ __func__, pathname);
+ /* If the proc files exist but the update failed,
+ * we don't know the state of the cache */
+ retval = FEDFS_ERR_UNKNOWN_CACHE;
+ } else
+ /* Cache flush succeeded */
+ retval = FEDFS_OK;
+
+ (void)close(fd);
+ return retval;
+}
+
+/**
+ * Flush the kernel NFSD's exports cache
+ *
+ * @return a FedFsStatus code
+ */
+FedFsStatus
+junction_flush_exports_cache(void)
+{
+ FedFsStatus retval;
+ char flushtime[20];
+ unsigned int i;
+ time_t now;
+
+ xlog(D_CALL, "%s: Flushing NFSD caches...", __func__);
+
+ now = time(NULL);
+ if (now == -1) {
+ xlog(D_GENERAL, "%s: time(3) failed", __func__);
+ return FEDFS_ERR_SVRFAULT;
+ }
+ snprintf(flushtime, sizeof(flushtime), "%ld\n", now);
+
+ for (i = 0; junction_proc_files[i] != NULL; i++) {
+ retval = junction_write_time(junction_proc_files[i], flushtime);
+ if (retval != FEDFS_OK)
+ return retval;
+ }
+ return FEDFS_OK;
+}
We want the effects of junction operations to appear to NFS clients immediately. But NFSD's export cache will hang onto old junction information for a time. All we can do is flush that cache after any operation that changes a junction. FedFS ADMIN clients can explicitly request cache flushing by using certain parameters to the FEDFS_LOOKUP_JUNCTION operation. Introduce an API to libjunction that can request an export cache flush. Call that function in appropriate places within fedfsd. This is cribbed from the exportfs command in nfs-utils. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- src/fedfsd/svc.c | 25 ++++++-- src/include/junction.h | 2 + src/libjunction/Makefile.am | 2 - src/libjunction/export-cache.c | 121 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 9 deletions(-) create mode 100644 src/libjunction/export-cache.c