Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 May 2018 12:43:04 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r334325 - projects/pnfs-planb-server/usr.bin/pnfsdscopymr
Message-ID:  <201805291243.w4TCh4nA010851@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805291243.w4TCh4nA010851>