@@ -1181,6 +1181,103 @@ lookup_export(char *dom, char *path, struct addrinfo *ai)
return found;
}
+static char *get_export_path(char *path)
+{
+ int i;
+ nfs_export *exp;
+ nfs_export *found = NULL;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+ if (!path_matches(exp, path))
+ continue;
+
+ if (!found) {
+ found = exp;
+ continue;
+ }
+
+ /* Always prefer non-V4ROOT exports */
+ if (exp->m_export.e_flags & NFSEXP_V4ROOT)
+ continue;
+ if (found->m_export.e_flags & NFSEXP_V4ROOT) {
+ found = exp;
+ continue;
+ }
+
+ /* If one is a CROSSMOUNT, then prefer the longest path */
+ if (((found->m_export.e_flags & NFSEXP_CROSSMOUNT) ||
+ (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)) &&
+ strlen(found->m_export.e_path) !=
+ strlen(exp->m_export.e_path)) {
+
+ if (strlen(exp->m_export.e_path) >
+ strlen(found->m_export.e_path)) {
+ found = exp;
+ }
+ continue;
+ }
+ }
+ }
+
+ if (found)
+ return found->m_export.e_path;
+ else
+ return NULL;
+}
+
+int export_subvol_orphaned(char *path)
+{
+ struct statfs st, stp;
+ char *path_parent;
+ int ret;
+
+ path_parent = get_export_path(path);
+ if (!path_parent)
+ /*
+ * Path has no parent in export list.
+ * Must be orphaned.
+ */
+ return 1;
+
+ ret = statfs(path_parent, &stp);
+ if (ret == -1)
+ /*
+ * Parent path is not statfs'able. Maybe not yet mounted?
+ * Can't be sure, don't treat path as orphaned.
+ */
+ return 0;
+
+ if (strcmp(path_parent, path) == 0)
+ /*
+ * This is not a subvolume, it is listed in exports.
+ * No need to keep tack of it.
+ */
+ return 1;
+
+ if (stp.f_type != 0x6969)
+ /*
+ * Parent is not a NFS mount. Maybe not yet mounted?
+ * Can't be sure either.
+ */
+ return 0;
+
+ ret = statfs(path, &st);
+ if (ret == -1) {
+ if (errno == ENOENT)
+ /*
+ * Parent is a NFS mount but path is gone.
+ * Must be orphaned.
+ */
+ return 1;
+ }
+
+ /*
+ * For all remaining cases we can't be sure either.
+ */
+ return 0;
+}
+
#ifdef HAVE_JUNCTION_SUPPORT
#include <libxml/parser.h>
@@ -38,4 +38,7 @@ static inline bool is_ipaddr_client(char *dom)
{
return dom[0] == '$';
}
+
+int export_subvol_orphaned(char *path);
+
#endif /* EXPORT__H */
@@ -208,6 +208,12 @@ read_exportd_conf(char *progname, char **argv)
default_ttl = ttl;
}
+static void subvol_cb(char *path)
+{
+ if (export_subvol_orphaned(path))
+ reexpdb_drop_subvolume_unlocked(path);
+}
+
int
main(int argc, char **argv)
{
@@ -297,7 +303,16 @@ main(int argc, char **argv)
/* Open files now to avoid sharing descriptors among forked processes */
cache_open();
v4clients_init();
- reexpdb_init();
+ if (reexpdb_init() != 0) {
+ xlog(L_ERROR, "%s: Failed to init reexport database", __func__);
+ exit(1);
+ }
+
+ /*
+ * Load exports into memory and garbage collect orphaned subvolumes.
+ */
+ auth_reload();
+ reexpdb_uncover_subvolumes(subvol_cb);
/* Process incoming upcalls */
cache_process_loop();
@@ -32,6 +32,7 @@
#include "nfsd_path.h"
#include "nfslib.h"
#include "export.h"
+#include "reexport.h"
extern void my_svc_run(void);
@@ -57,6 +57,7 @@
#include <rpc/rpc_com.h>
#endif
#include "export.h"
+#include "reexport.h"
void my_svc_run(void);
@@ -87,6 +88,12 @@ my_svc_getreqset (fd_set *readfds)
#endif
+static void subvol_cb(char *path)
+{
+ if (export_subvol_orphaned(path))
+ reexpdb_drop_subvolume_unlocked(path);
+}
+
/*
* The heart of the server. A crib from libc for the most part...
*/
@@ -96,6 +103,17 @@ my_svc_run(void)
fd_set readfds;
int selret;
+ if (reexpdb_init() != 0) {
+ xlog(L_ERROR, "%s: Failed to init reexport database", __func__);
+ return;
+ }
+
+ /*
+ * Load exports into memory and garbage collect orphaned subvolumes.
+ */
+ auth_reload();
+ reexpdb_uncover_subvolumes(subvol_cb);
+
for (;;) {
readfds = svc_fdset;
Make sure the database contains no orphaned subvolumes. We have to be careful. Signed-off-by: Richard Weinberger <richard@nod.at> --- support/export/cache.c | 97 +++++++++++++++++++++++++++++++++++++++++ support/export/export.h | 3 ++ utils/exportd/exportd.c | 17 +++++++- utils/mountd/mountd.c | 1 + utils/mountd/svc_run.c | 18 ++++++++ 5 files changed, 135 insertions(+), 1 deletion(-)