Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Sep 2009 00:00:11 +0200
From:      Mel Flynn <mel.flynn+fbsd.fs@mailing.thruhere.net>
To:        freebsd-fs@freebsd.org
Subject:   Patch to allow gmirror to set priority of a disk
Message-ID:  <200909030000.11961.mel.flynn%2Bfbsd.fs@mailing.thruhere.net>

next in thread | raw e-mail | index | archive | help
--Boundary-00=_rrunKSzo0DzDzG0
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hi,

I've created a patch that allows gmirror to set the priority of a disk. I've 
needed this feature so I can signal which disk is the "master" on the next 
reboot and also because insertion of a 3rd disk comes with the same priority 
as the master disk.

Some background about the first issue: I've got one system that gets READ_DMA 
errors and then dumps the disk out of the mirror. I believe it is NOT related 
to disk errors, but rather to IDE/Motherboard bandwidth (SMART doesn't show 
any errors and the READ_DMA errors are scattered amongst LBA blocks, no 
WRITE_DMA errors ever, never got SATA disks to work on this mobo and last but 
not least it only happens when IO is high, like daily backup with dump -C 
20M).
Which disk gets thrown out, is random and the last time that happened I 
rebooted since I needed a new kernel anyway and the wrong disk was consider 
master. This is a side-effect of me having to do several:
gmirror forget gm0
gmirror insert gm0 adX

during an uptime sequence. As a result, both disks have the same priority.

Unfortunately, due to geographic relocation, I no longer have physical access 
to the machine, so I have only compile tested this patch, but I wanted to get 
some feedback about it:
- Have I made some mistakes that would trash my mirror? ;)
- Is there any desire to have this feature other then my own?
- Any style issues?

-- 
Mel

--Boundary-00=_rrunKSzo0DzDzG0
Content-Type: text/plain;
  charset="UTF-8";
  name="gmirror.patch.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="gmirror.patch.txt"

Index: sbin/geom/class/mirror/geom_mirror.c
===================================================================
--- sbin/geom/class/mirror/geom_mirror.c	(revision 196761)
+++ sbin/geom/class/mirror/geom_mirror.c	(working copy)
@@ -27,6 +27,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/limits.h> /* UCHAR_MAX */
 #include <sys/param.h>
 #include <errno.h>
 #include <paths.h>
@@ -54,6 +55,7 @@
 static void mirror_clear(struct gctl_req *req);
 static void mirror_dump(struct gctl_req *req);
 static void mirror_label(struct gctl_req *req);
+static void mirror_setprio(struct gctl_req *req);
 
 struct g_command class_commands[] = {
 	{ "activate", G_FLAG_VERBOSE, mirror_main, G_NULL_OPTS, NULL,
@@ -111,6 +113,9 @@
 	{ "remove", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, NULL,
 	    "[-v] name prov ..."
 	},
+	{ "setprio", G_FLAG_VERBOSE, mirror_main, G_NULL_OPTS, NULL,
+	    "[-v] name prov priority"
+	},
 	{ "stop", G_FLAG_VERBOSE, NULL,
 	    {
 		{ 'f', "force", NULL, G_TYPE_BOOL },
@@ -144,6 +149,8 @@
 		mirror_dump(req);
 	else if (strcmp(name, "activate") == 0)
 		mirror_activate(req);
+	else if (strcmp(name, "setprio") == 0)
+		mirror_setprio(req);
 	else
 		gctl_error(req, "Unknown command: %s.", name);
 }
@@ -375,3 +382,64 @@
 			printf("Provider %s activated.\n", path);
 	}
 }
+
+static void
+mirror_setprio(struct gctl_req *req)
+{
+	struct g_mirror_metadata md, tmpmd;
+	const char *name, *prov;
+	intmax_t prio;
+	uint8_t oldprio;
+	int error, nargs;
+
+	nargs = gctl_get_int(req, "nargs");
+	if (nargs < 3) {
+		gctl_error(req, "Too few arguments.");
+		return;
+	}
+
+	name = gctl_get_ascii(req, "arg0");
+	prov = gctl_get_ascii(req, "arg1");
+	prio = gctl_get_intmax(req, "arg2");
+	if ( prio < 0 || prio > UCHAR_MAX ) {
+		fprintf(stderr,
+		    "Priority has to be between 0 and %u", UCHAR_MAX);
+		gctl_error(req, "Failed.");
+		return;
+	}
+	error = g_metadata_read(prov, (u_char *)&tmpmd, sizeof(tmpmd),
+	    G_MIRROR_MAGIC);
+	if (error != 0) {
+		fprintf(stderr, "Can't read metadata from %s: %s.\n",
+		    name, strerror(error));
+		gctl_error(req, "Failed.");
+		return;
+	}
+	if (mirror_metadata_decode((u_char *)&tmpmd, &md) != 0) {
+		fprintf(stderr,
+		    "MD5 hash mismatch for provider %s: %s, aborting\n",
+		    prov, strerror(error));
+		gctl_error(req, "Failed.");
+		return;
+	}
+	if (strcmp(md.md_name, name) != 0) {
+		fprintf(stderr,
+		    "Provider %s is not the mirror %s component.\n",
+		    prov, name);
+		gctl_error(req, "Failed.");
+		return;
+	}
+	oldprio = md.md_priority;
+	md.md_priority = (uint8_t)prio;
+	mirror_metadata_encode(&md, (u_char *)&tmpmd);
+	error = g_metadata_store(prov, (u_char *)&tmpmd, sizeof(tmpmd));
+	if (error != 0) {
+		fprintf(stderr, "Cannot write metadata from %s: %s.\n",
+		    prov, strerror(error));
+		gctl_error(req, "Failed.");
+		return;
+	}
+	if (verbose)
+		printf("Provider %s priority %u => %u", prov, oldprio,
+		    md.md_priority);
+}

--Boundary-00=_rrunKSzo0DzDzG0--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909030000.11961.mel.flynn%2Bfbsd.fs>