svn commit: r334325 - projects/pnfs-planb-server/usr.bin/pnfsdscopymr
Rick Macklem
rmacklem at FreeBSD.org
Tue May 29 12:43:04 UTC 2018
Author: rmacklem
Date: Tue May 29 12:43:03 2018
New Revision: 334325
URL: https://svnweb.freebsd.org/changeset/base/334325
Log:
Fix up pnfsdscopymr.c for the distributed mirror handling.
Also change the default to mirror to any other DS and add a "-r" option to
specify the destination mirror DS.
Add a new "-m" option to migrate data storage files between DSs.
The man page still needs to be updated.
Modified:
projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.c
Modified: projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.c
==============================================================================
--- projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.c Tue May 29 12:32:08 2018 (r334324)
+++ projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.c Tue May 29 12:43:03 2018 (r334325)
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
+#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -40,6 +41,8 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <nfs/nfssvc.h>
@@ -51,6 +54,12 @@ __FBSDID("$FreeBSD$");
static void usage(void);
+static struct option longopts[] = {
+ { "migrate", required_argument, NULL, 'm' },
+ { "mirror", required_argument, NULL, 'r' },
+ { NULL, 0, NULL, 0 }
+};
+
/*
* This program creates a copy of the file's (first argument) data on the
* new/recovering DS mirror. If the file is already on the new/recovering
@@ -67,152 +76,218 @@ main(int argc, char *argv[])
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
ssize_t xattrsize;
- int fnd, i, mirrorcnt, ret;
+ size_t mirlen;
+ int ch, fnd, fndzero, i, migrateit, mirrorcnt, mirrorit, ret;
+ int mirrorlevel;
char host[MNAMELEN + NI_MAXHOST + 2], *cp;
- if (argc != 4)
- usage();
if (geteuid() != 0)
errx(1, "Must be run as root/su");
+ mirrorit = migrateit = 0;
+ pnfsdarg.dspath = pnfsdarg.curdspath = NULL;
+ while ((ch = getopt_long(argc, argv, "m:r:", longopts, NULL)) != -1) {
+ switch (ch) {
+ case 'm':
+ /* Migrate the file from the second DS to the first. */
+ if (mirrorit != 0)
+ errx(1, "-r and -m are mutually exclusive");
+ migrateit = 1;
+ pnfsdarg.curdspath = optarg;
+ break;
+ case 'r':
+ /* Mirror the file on the specified DS. */
+ if (migrateit != 0)
+ errx(1, "-r and -m are mutually exclusive");
+ mirrorit = 1;
+ pnfsdarg.dspath = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (migrateit != 0) {
+ if (argc != 2)
+ usage();
+ pnfsdarg.dspath = *argv++;
+ } else if (argc != 1)
+ usage();
+
+ /* Get the pNFS service's mirror level. */
+ mirlen = sizeof(mirrorlevel);
+ ret = sysctlbyname("vfs.nfs.pnfsmirror", &mirrorlevel, &mirlen,
+ NULL, 0);
+ if (ret < 0)
+ errx(1, "Can't get vfs.nfs.pnfsmirror");
+
+ if (pnfsdarg.dspath != NULL && pnfsdarg.curdspath != NULL &&
+ strcmp(pnfsdarg.dspath, pnfsdarg.curdspath) == 0)
+ errx(1, "Can't migrate to same server");
+
/*
* The host address and directory where the data storage file is
* located is in the extended attribute "pnfsd.dsfile".
*/
- xattrsize = extattr_get_file(argv[1], EXTATTR_NAMESPACE_SYSTEM,
+ xattrsize = extattr_get_file(*argv, EXTATTR_NAMESPACE_SYSTEM,
"pnfsd.dsfile", dsfile, sizeof(dsfile));
mirrorcnt = xattrsize / sizeof(struct pnfsdsfile);
if (mirrorcnt < 1 || xattrsize != mirrorcnt * sizeof(struct pnfsdsfile))
- errx(1, "Can't get extattr pnfsd.dsfile for %s", argv[1]);
+ errx(1, "Can't get extattr pnfsd.dsfile for %s", *argv);
- /* Check the second argument to see that it is an NFS mount point. */
- if (stat(argv[2], &sb) < 0)
- errx(1, "Can't stat %s", argv[2]);
- if (!S_ISDIR(sb.st_mode))
- errx(1, "%s is not a directory", argv[2]);
- if (statfs(argv[2], &sf) < 0)
- errx(1, "Can't fsstat %s", argv[2]);
- if (strcmp(sf.f_fstypename, "nfs") != 0)
- errx(1, "%s is not an NFS mount", argv[2]);
- if (strcmp(sf.f_mntonname, argv[2]) != 0)
- errx(1, "%s is not the mounted-on dir for the new DS", argv[2]);
-
- /*
- * Check the IP address of the NFS server against the entrie(s) in
- * the extended attribute.
- */
- strlcpy(host, sf.f_mntfromname, sizeof(host));
- cp = strchr(host, ':');
- if (cp == NULL)
- errx(1, "No <host>: in mount %s", host);
- *cp = '\0';
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- if (getaddrinfo(host, NULL, &hints, &res) != 0)
- errx(1, "Can't get address for %s", host);
+ /* See if there is a 0.0.0.0 entry. */
+ fndzero = 0;
for (i = 0; i < mirrorcnt; i++) {
- nres = res;
- while (nres != NULL) {
- if (dsfile[i].dsf_sin.sin_family == nres->ai_family) {
- /*
- * If there is already an entry for this
- * DS, just exit(0), since copying isn't
- * required.
- */
- if (nres->ai_family == AF_INET) {
- sin = (struct sockaddr_in *)
- nres->ai_addr;
- if (sin->sin_addr.s_addr ==
- dsfile[i].dsf_sin.sin_addr.s_addr)
- exit(0);
- } else if (nres->ai_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)
- nres->ai_addr;
- if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
- &dsfile[i].dsf_sin6.sin6_addr))
- exit(0);
+ if (dsfile[i].dsf_sin.sin_family == AF_INET &&
+ dsfile[i].dsf_sin.sin_addr.s_addr == 0)
+ fndzero = 1;
+ }
+
+ /* If already mirrored for default case, just exit(0); */
+ if (mirrorit == 0 && migrateit == 0 && (mirrorlevel < 2 ||
+ (fndzero == 0 && mirrorcnt >= mirrorlevel) ||
+ (fndzero != 0 && mirrorcnt > mirrorlevel)))
+ exit(0);
+
+ /* For the "-r" case, there must be a 0.0.0.0 entry. */
+ if (mirrorit != 0 && (fndzero == 0 || mirrorlevel < 2 ||
+ mirrorcnt < 2 || mirrorcnt > mirrorlevel))
+ exit(0);
+
+ /* For pnfsdarg.dspath set, if it is already in list, just exit(0); */
+ if (pnfsdarg.dspath != NULL) {
+ /* Check the dspath to see that it's an NFS mount. */
+ if (stat(pnfsdarg.dspath, &sb) < 0)
+ errx(1, "Can't stat %s", pnfsdarg.dspath);
+ if (!S_ISDIR(sb.st_mode))
+ errx(1, "%s is not a directory", pnfsdarg.dspath);
+ if (statfs(pnfsdarg.dspath, &sf) < 0)
+ errx(1, "Can't fsstat %s", pnfsdarg.dspath);
+ if (strcmp(sf.f_fstypename, "nfs") != 0)
+ errx(1, "%s is not an NFS mount", pnfsdarg.dspath);
+ if (strcmp(sf.f_mntonname, pnfsdarg.dspath) != 0)
+ errx(1, "%s is not the mounted-on dir for the new DS",
+ pnfsdarg.dspath);
+
+ /*
+ * Check the IP address of the NFS server against the entrie(s)
+ * in the extended attribute.
+ */
+ strlcpy(host, sf.f_mntfromname, sizeof(host));
+ cp = strchr(host, ':');
+ if (cp == NULL)
+ errx(1, "No <host>: in mount %s", host);
+ *cp = '\0';
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(host, NULL, &hints, &res) != 0)
+ errx(1, "Can't get address for %s", host);
+ for (i = 0; i < mirrorcnt; i++) {
+ nres = res;
+ while (nres != NULL) {
+ if (dsfile[i].dsf_sin.sin_family ==
+ nres->ai_family) {
+ /*
+ * If there is already an entry for this
+ * DS, just exit(0), since copying isn't
+ * required.
+ */
+ if (nres->ai_family == AF_INET) {
+ sin = (struct sockaddr_in *)
+ nres->ai_addr;
+ if (sin->sin_addr.s_addr ==
+ dsfile[i].dsf_sin.sin_addr.s_addr)
+ exit(0);
+ } else if (nres->ai_family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)
+ nres->ai_addr;
+ if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
+ &dsfile[i].dsf_sin6.sin6_addr))
+ exit(0);
+ }
}
+ nres = nres->ai_next;
}
- nres = nres->ai_next;
}
+ freeaddrinfo(res);
}
- freeaddrinfo(res);
- /* Check the third argument to see that it is an NFS mount point. */
- if (stat(argv[3], (struct stat *)&sb) < 0)
- errx(1, "Can't stat %s", argv[3]);
- if (!S_ISDIR(sb.st_mode))
- errx(1, "%s is not a directory", argv[3]);
- if (statfs(argv[3], (struct statfs *)&sf) < 0)
- errx(1, "Can't fsstat %s", argv[3]);
- if (strcmp(sf.f_fstypename, "nfs") != 0)
- errx(1, "%s is not an NFS mount", argv[3]);
- if (strcmp(sf.f_mntonname, argv[3]) != 0)
- errx(1, "%s is not the mounted-on dir of the cur DS", argv[3]);
-
- /*
- * Check the IP address of the NFS server against the entrie(s) in
- * the extended attribute.
- */
- strlcpy(host, sf.f_mntfromname, sizeof(host));
- cp = strchr(host, ':');
- if (cp == NULL)
- errx(1, "No <host>: in mount %s", host);
- *cp = '\0';
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- if (getaddrinfo(host, NULL, &hints, &res) != 0)
- errx(1, "Can't get address for %s", host);
- fnd = 0;
- for (i = 0; i < mirrorcnt && fnd == 0; i++) {
- nres = res;
- while (nres != NULL) {
- if (dsfile[i].dsf_sin.sin_family == nres->ai_family) {
- /*
- * If there is already an entry for this
- * DS, just exit(0), since copying isn't
- * required.
- */
- if (nres->ai_family == AF_INET) {
- sin = (struct sockaddr_in *)
- nres->ai_addr;
- if (sin->sin_addr.s_addr ==
- dsfile[i].dsf_sin.sin_addr.s_addr) {
- fnd = 1;
- break;
+ /* For "-m", the pnfsdarg.curdspath must be in the list. */
+ if (pnfsdarg.curdspath != NULL) {
+ /* Check pnfsdarg.curdspath to see that it's an NFS mount. */
+ if (stat(pnfsdarg.curdspath, &sb) < 0)
+ errx(1, "Can't stat %s", pnfsdarg.curdspath);
+ if (!S_ISDIR(sb.st_mode))
+ errx(1, "%s is not a directory", pnfsdarg.curdspath);
+ if (statfs(pnfsdarg.curdspath, &sf) < 0)
+ errx(1, "Can't fsstat %s", pnfsdarg.curdspath);
+ if (strcmp(sf.f_fstypename, "nfs") != 0)
+ errx(1, "%s is not an NFS mount", pnfsdarg.curdspath);
+ if (strcmp(sf.f_mntonname, pnfsdarg.curdspath) != 0)
+ errx(1, "%s is not the mounted-on dir of the cur DS",
+ pnfsdarg.curdspath);
+
+ /*
+ * Check the IP address of the NFS server against the entrie(s)
+ * in the extended attribute.
+ */
+ strlcpy(host, sf.f_mntfromname, sizeof(host));
+ cp = strchr(host, ':');
+ if (cp == NULL)
+ errx(1, "No <host>: in mount %s", host);
+ *cp = '\0';
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(host, NULL, &hints, &res) != 0)
+ errx(1, "Can't get address for %s", host);
+ fnd = 0;
+ for (i = 0; i < mirrorcnt && fnd == 0; i++) {
+ nres = res;
+ while (nres != NULL) {
+ if (dsfile[i].dsf_sin.sin_family ==
+ nres->ai_family) {
+ /*
+ * Note if the entry is found.
+ */
+ if (nres->ai_family == AF_INET) {
+ sin = (struct sockaddr_in *)
+ nres->ai_addr;
+ if (sin->sin_addr.s_addr ==
+ dsfile[i].dsf_sin.sin_addr.s_addr) {
+ fnd = 1;
+ break;
+ }
+ } else if (nres->ai_family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)
+ nres->ai_addr;
+ if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
+ &dsfile[i].dsf_sin6.sin6_addr)) {
+ fnd = 1;
+ break;
+ }
}
- } else if (nres->ai_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)
- nres->ai_addr;
- if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
- &dsfile[i].dsf_sin6.sin6_addr)) {
- fnd = 1;
- break;
- }
}
+ nres = nres->ai_next;
}
- nres = nres->ai_next;
}
+ freeaddrinfo(res);
+ /*
+ * If not found just exit(0), since it is not on the
+ * source DS.
+ */
+ if (fnd == 0)
+ exit(0);
}
- freeaddrinfo(res);
- /*
- * If not found, just exit(0) since this file isn't stored on the
- * current mirror and, therefore, isn't stored on this mirror set.
- */
- if (fnd == 0)
- exit(0);
/* Do the copy via the nfssvc() syscall. */
pnfsdarg.op = PNFSDOP_COPYMR;
- pnfsdarg.mdspath = argv[1];
- pnfsdarg.dspath = argv[2];
- pnfsdarg.curdspath = argv[3];
+ pnfsdarg.mdspath = *argv;
ret = nfssvc(NFSSVC_PNFSDS, &pnfsdarg);
if (ret < 0 && errno != EEXIST)
- err(1, "Copymr failed args %s, %s, %s", argv[1], argv[2],
- argv[3]);
+ err(1, "Copymr failed args %s, %s", argv[1], argv[2]);
exit(0);
}
@@ -220,8 +295,9 @@ static void
usage(void)
{
- fprintf(stderr, "pnfsdscopymr <mds-filename> "
- "<recovered-DS-mounted-on-path> <current-DS-mounted-on-path>\n");
+ fprintf(stderr, "pnfsdscopymr [-r recovered-DS-mounted-on-path] "
+ "[-m soure-DS-mounted-on-path destination-DS-mounted-on-path] "
+ "mds-filename");
exit(1);
}
More information about the svn-src-projects
mailing list