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>