summaryrefslogtreecommitdiffstats
path: root/utils/nfsref/add.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/nfsref/add.c')
-rw-r--r--utils/nfsref/add.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/utils/nfsref/add.c b/utils/nfsref/add.c
new file mode 100644
index 0000000..781aeee
--- /dev/null
+++ b/utils/nfsref/add.c
@@ -0,0 +1,272 @@
+/**
+ * @file utils/nfsref/add.c
+ * @brief Add junction metadata to a local file system object
+ */
+
+/*
+ * Copyright 2011, 2018 Oracle. All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-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.
+ *
+ * nfs-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 nfs-utils. If not, see:
+ *
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <uuid/uuid.h>
+
+#include "junction.h"
+#include "xlog.h"
+#include "nfsref.h"
+
+/**
+ * Default cache expiration for FSN information
+ */
+#define FSN_DEFAULT_TTL (300)
+
+/**
+ * Display help message for "add" subcommand
+ *
+ * @param progname NUL-terminated C string containing name of program
+ * @return program exit status
+ */
+int
+nfsref_add_help(const char *progname)
+{
+ fprintf(stderr, " \n");
+
+ fprintf(stderr, "Usage: %s [ -t type ] add <junction path> "
+ "<server> <export> [ <server> <export> ... ]\n\n",
+ progname);
+
+ fprintf(stderr, "Add a new junction containing the specified list "
+ "of fileset locations.\n");
+ fprintf(stderr, "<junction path> is the filename of the new junction. "
+ "<server> is the hostname\n");
+ fprintf(stderr, "or IP address of an NFS server where the fileset is "
+ "located. <export> is the\n");
+ fprintf(stderr, "export pathname of the fileset on that server.\n\n");
+
+ fprintf(stderr, "For NFS basic junctions, the location list is stored "
+ "locally in the junction.\n");
+ fprintf(stderr, "For FedFS junctions, the location list is stored "
+ "as new FSN and FSL records\n");
+ fprintf(stderr, "on an NSDB.\n");
+
+ return EXIT_SUCCESS;
+}
+
+/**
+ * Fill in default settings for NFSv4.0 fs_locations4
+ *
+ * @param new NFS location structure to fill in
+ *
+ * See section 5.1.3.2 of the NSDB protocol draft.
+ */
+static void
+nfsref_add_fsloc_defaults(struct nfs_fsloc *new)
+{
+ new->nfl_hostport = 0;
+ new->nfl_flags.nfl_varsub = false;
+ new->nfl_currency = -1;
+ new->nfl_validfor = 0;
+ new->nfl_genflags.nfl_writable = false;
+ new->nfl_genflags.nfl_going = false;
+ new->nfl_genflags.nfl_split = true;
+ new->nfl_transflags.nfl_rdma = true;
+ new->nfl_info.nfl_simul = 0;
+ new->nfl_info.nfl_handle = 0;
+ new->nfl_info.nfl_fileid = 0;
+ new->nfl_info.nfl_writever = 0;
+ new->nfl_info.nfl_change = 0;
+ new->nfl_info.nfl_readdir = 0;
+ new->nfl_info.nfl_readrank = 0;
+ new->nfl_info.nfl_readorder = 0;
+ new->nfl_info.nfl_writerank = 0;
+ new->nfl_info.nfl_writeorder = 0;
+}
+
+/**
+ * Convert a pair of command line arguments to one nfs_fsloc structure
+ *
+ * @param server NUL-terminated C string containing file server hostname
+ * @param rootpath NUL-terminated C string containing POSIX-style export path
+ * @param fsloc OUT: NFS location structure
+ * @return a FedFsStatus code
+ *
+ * If nfsref_add_build_fsloc() returns FEDFS_OK, caller must free the
+ * returned fsloc with nfs_free_location().
+ */
+static FedFsStatus
+nfsref_add_build_fsloc(const char *server, const char *rootpath,
+ struct nfs_fsloc **fsloc)
+{
+ struct nfs_fsloc *new;
+ FedFsStatus retval;
+
+ if (server == NULL || rootpath == NULL)
+ return FEDFS_ERR_INVAL;
+
+ xlog(D_GENERAL, "%s: Building fsloc for %s:%s",
+ __func__, server, rootpath);
+
+ new = nfs_new_location();
+ if (new == NULL) {
+ xlog(D_GENERAL, "%s: No memory", __func__);
+ return FEDFS_ERR_SVRFAULT;
+ }
+
+ new->nfl_hostname = strdup(server);
+ if (new->nfl_hostname == NULL) {
+ nfs_free_location(new);
+ xlog(D_GENERAL, "%s: No memory", __func__);
+ return FEDFS_ERR_SVRFAULT;
+ }
+
+ retval = nsdb_posix_to_path_array(rootpath, &new->nfl_rootpath);
+ if (retval != FEDFS_OK) {
+ nfs_free_location(new);
+ return retval;
+ }
+
+ nfsref_add_fsloc_defaults(new);
+ *fsloc = new;
+ return FEDFS_OK;
+}
+
+/**
+ * Convert array of command line arguments to list of nfs_fsloc structures
+ *
+ * @param argv array of pointers to NUL-terminated C strings contains arguments
+ * @param optind index of "argv" where "add" subcommand arguments start
+ * @param fslocs OUT: list of NFS locations
+ * @return a FedFsStatus code
+ *
+ * If nfsref_add_build_fsloc_list() returns FEDFS_OK, caller must free the
+ * returned list of fslocs with nfs_free_locations().
+ */
+static FedFsStatus
+nfsref_add_build_fsloc_list(char **argv, int optind, struct nfs_fsloc **fslocs)
+{
+ struct nfs_fsloc *fsloc, *result = NULL;
+ FedFsStatus retval;
+ int i;
+
+ for (i = optind + 2; argv[i] != NULL; i += 2) {
+ retval = nfsref_add_build_fsloc(argv[i], argv[i + 1], &fsloc);
+ if (retval != FEDFS_OK) {
+ nfs_free_locations(result);
+ return retval;
+ }
+ if (result == NULL)
+ result = fsloc;
+ else
+ result->nfl_next = fsloc;
+ }
+ if (result == NULL)
+ return FEDFS_ERR_INVAL;
+
+ *fslocs = result;
+ return FEDFS_OK;
+}
+
+/**
+ * Add NFS locations to a junction
+ *
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @param argv array of pointers to NUL-terminated C strings contains arguments
+ * @param optind index of "argv" where "add" subcommand arguments start
+ * @return program exit status
+ */
+static int
+nfsref_add_nfs_basic(const char *junct_path, char **argv, int optind)
+{
+ struct nfs_fsloc *fslocs = NULL;
+ FedFsStatus retval;
+
+ xlog(D_GENERAL, "%s: Adding basic junction to %s",
+ __func__, junct_path);
+
+ retval = nfsref_add_build_fsloc_list(argv, optind, &fslocs);
+ switch (retval) {
+ case FEDFS_OK:
+ break;
+ case FEDFS_ERR_INVAL:
+ xlog(L_ERROR, "Missing arguments");
+ return EXIT_FAILURE;
+ case FEDFS_ERR_SVRFAULT:
+ xlog(L_ERROR, "No memory");
+ return EXIT_FAILURE;
+ default:
+ xlog(L_ERROR, "Failed to add NFS location metadata to %s: %s",
+ junct_path, nsdb_display_fedfsstatus(retval));
+ return EXIT_FAILURE;
+ }
+
+ retval = nfs_add_junction(junct_path, fslocs);
+ nfs_free_locations(fslocs);
+ switch (retval) {
+ case FEDFS_OK:
+ break;
+ case FEDFS_ERR_EXIST:
+ xlog(L_ERROR, "%s already contains junction metadata",
+ junct_path);
+ return EXIT_FAILURE;
+ default:
+ xlog(L_ERROR, "Failed to add NFS location metadata to %s: %s",
+ junct_path, nsdb_display_fedfsstatus(retval));
+ return EXIT_FAILURE;
+ }
+
+ printf("Created junction %s\n", junct_path);
+ return EXIT_SUCCESS;
+}
+
+/**
+ * Add locations to a junction
+ *
+ * @param type type of junction to add
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @param argv array of pointers to NUL-terminated C strings contains arguments
+ * @param optind index of "argv" where "add" subcommand arguments start
+ * @return program exit status
+ */
+int
+nfsref_add(enum nfsref_type type, const char *junct_path, char **argv, int optind)
+{
+ if (mkdir(junct_path, 0755) == -1)
+ if (errno != EEXIST) {
+ xlog(L_ERROR, "Failed to create junction object: %m");
+ return EXIT_FAILURE;
+ }
+
+ switch (type) {
+ case NFSREF_TYPE_UNSPECIFIED:
+ case NFSREF_TYPE_NFS_BASIC:
+ return nfsref_add_nfs_basic(junct_path, argv, optind);
+ default:
+ xlog(L_ERROR, "Unrecognized junction type");
+ }
+ return EXIT_FAILURE;
+}