Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Apr 2018 22:37:07 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r332846 - projects/pnfs-planb-server/usr.bin/pnfsdscopymr
Message-ID:  <201804202237.w3KMb7Uw001877@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Fri Apr 20 22:37:07 2018
New Revision: 332846
URL: https://svnweb.freebsd.org/changeset/base/332846

Log:
  Add the pnfsdscopymr command that is used to copy a file to a recovered
  mirrored DS.

Added:
  projects/pnfs-planb-server/usr.bin/pnfsdscopymr/
  projects/pnfs-planb-server/usr.bin/pnfsdscopymr/Makefile   (contents, props changed)
  projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.1   (contents, props changed)
  projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.c   (contents, props changed)

Added: projects/pnfs-planb-server/usr.bin/pnfsdscopymr/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/pnfs-planb-server/usr.bin/pnfsdscopymr/Makefile	Fri Apr 20 22:37:07 2018	(r332846)
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+PROG=	pnfsdscopymr
+
+.include <bsd.prog.mk>

Added: projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.1
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.1	Fri Apr 20 22:37:07 2018	(r332846)
@@ -0,0 +1,96 @@
+.\" Copyright (c) 2018 Rick Macklem
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 9, 2018
+.Dt PNFSDSCOPYMR 1
+.Os
+.Sh NAME
+.Nm pnfsdscopymr
+.Nd
+makes a copy of a file's data on a recovered/new mirror data storage server (DS)
+.Sh SYNOPSIS
+.Nm
+.Ar file
+.Ar mounted_on_path_of_recovered_DS
+.Ar mounted_on_path_of_operational_DS
+.Sh DESCRIPTION
+The
+.Nm
+command copies a file's data from a operational DS to a recovered (or new)
+DS that is configured as a mirror of this operational DS.
+If the recovered/new DS is configured as a mirror of the operational DS, the
+data of the
+.Ar file
+on the MDS
+is copied to the recovered DS, unless the recovered/new DS
+already has a valid copy.
+The copy is considered valid if it exists in the extended attribute of the
+MDS file and its IP address is non-zero.
+If the
+.Ar file
+does not have the operational DS in its extended attribute or it already
+has a valid copy of the file's data, the command simply does an exit(0).
+This is done so that the command can be called on any file within the MDS's
+exported file tree safely.
+.Pp
+The first argument
+.Ar file
+is the file on the MDS, the second argument
+.Ar mounted_on_path_of_recovered_DS
+is the mounted on directory path of the recovered/new mirror and
+the third argument
+.Ar mounted_on_path_of_operational_DS
+is the mounted on directory path of a non-disabled DS that is a mirror of the
+recovered/new DS.
+The third argument is used to check if the
+.Ar file
+argument is stored on the mirror set that includes the recovered/new DS
+so that it can be used within a
+.Xr find 1 .
+.Pp
+This command must be run on the MDS and a typical usage would be as an
+argument for
+.Xr find 1
+for all regular files.
+.sp
+For example, if the recovered/new DS is mounted on /data3 and it is a
+mirror of the DS mounted on /data2:
+.br
+# cd <top-level-exported-directory-on-the-MDS>
+.br
+# find . -type f -exec pnfsdscopymr {} /data3 /data2 \\;
+.El
+.Sh SEE ALSO
+.Xr find 1 ,
+.Xr pnfsdsfile 1 ,
+.Xr pnfsdskill 1 ,
+.Xr nfsv4 4 ,
+.Xr pnfs 4 ,
+.Xr nfsd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in FreeBSD12.

Added: projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/pnfs-planb-server/usr.bin/pnfsdscopymr/pnfsdscopymr.c	Fri Apr 20 22:37:07 2018	(r332846)
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 2017 Rick Macklem
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/extattr.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <nfs/nfssvc.h>
+
+#include <fs/nfs/nfsproto.h>
+#include <fs/nfs/nfskpiport.h>
+#include <fs/nfs/nfs.h>
+#include <fs/nfs/nfsrvstate.h>
+
+static void usage(void);
+
+/*
+ * 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
+ * DS, it will simply exit(0).
+ */
+int
+main(int argc, char *argv[])
+{
+	struct nfsd_pnfsd_args pnfsdarg;
+	struct pnfsdsfile dsfile[NFSDEV_MAXMIRRORS];
+	struct stat sb;
+	struct statfs sf;
+	struct addrinfo hints, *res, *nres;
+	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin6;
+	ssize_t xattrsize;
+	int fnd, i, mirrorcnt, ret;
+	char host[MNAMELEN + NI_MAXHOST + 2], *cp;
+
+	if (argc != 4)
+		usage();
+	if (geteuid() != 0)
+		errx(1, "Must be run as root/su");
+
+	/*
+	 * 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,
+	    "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]);
+
+	/* 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);
+	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;
+		}
+	}
+	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;
+					}
+				} 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;
+		}
+	}
+	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];
+	ret = nfssvc(NFSSVC_PNFSDS, &pnfsdarg);
+	if (ret < 0 && errno != EEXIST)
+		err(1, "Copymr failed args %s, %s, %s", argv[1], argv[2],
+		    argv[3]);
+	exit(0);
+}
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "pnfsdscopymr <mds-filename> "
+	    "<recovered-DS-mounted-on-path> <current-DS-mounted-on-path>\n");
+	exit(1);
+}
+



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