From owner-freebsd-fs@FreeBSD.ORG Wed Sep 2 22:17:15 2009 Return-Path: Delivered-To: freebsd-fs@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2F478106566B for ; Wed, 2 Sep 2009 22:17:15 +0000 (UTC) (envelope-from mel.flynn+fbsd.fs@mailing.thruhere.net) Received: from mailhub.rachie.is-a-geek.net (rachie.is-a-geek.net [66.230.99.27]) by mx1.freebsd.org (Postfix) with ESMTP id C4EB38FC08 for ; Wed, 2 Sep 2009 22:17:14 +0000 (UTC) Received: from smoochies.rachie.is-a-geek.net (mailhub.rachie.is-a-geek.net [192.168.2.11]) by mailhub.rachie.is-a-geek.net (Postfix) with ESMTP id 9202A7E818 for ; Wed, 2 Sep 2009 14:00:25 -0800 (AKDT) From: Mel Flynn To: freebsd-fs@freebsd.org Date: Thu, 3 Sep 2009 00:00:11 +0200 User-Agent: KMail/1.11.4 (FreeBSD/8.0-BETA2; KDE/4.2.4; i386; ; ) MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_rrunKSzo0DzDzG0" Message-Id: <200909030000.11961.mel.flynn+fbsd.fs@mailing.thruhere.net> Subject: Patch to allow gmirror to set priority of a disk X-BeenThere: freebsd-fs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Filesystems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Sep 2009 22:17:15 -0000 --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 __FBSDID("$FreeBSD$"); +#include /* UCHAR_MAX */ #include #include #include @@ -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--