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>
