Add support for changing providers priority.

Submitted by:	Mel Flynn
This commit is contained in:
Pawel Jakub Dawidek 2009-09-06 06:52:06 +00:00
parent 87070efb4d
commit b740e905a4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196879
3 changed files with 81 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> * Copyright (c) 2004-2009 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -41,13 +41,12 @@ __FBSDID("$FreeBSD$");
#include <core/geom.h> #include <core/geom.h>
#include <misc/subr.h> #include <misc/subr.h>
uint32_t lib_version = G_LIB_VERSION; uint32_t lib_version = G_LIB_VERSION;
uint32_t version = G_MIRROR_VERSION; uint32_t version = G_MIRROR_VERSION;
static char label_balance[] = "split", configure_balance[] = "none"; static char label_balance[] = "split", configure_balance[] = "none";
static intmax_t label_slice = 4096, configure_slice = -1; static intmax_t label_slice = 4096, configure_slice = -1;
static intmax_t insert_priority = 0; static intmax_t insert_priority = 0, configure_priority = -1;
static void mirror_main(struct gctl_req *req, unsigned flags); static void mirror_main(struct gctl_req *req, unsigned flags);
static void mirror_activate(struct gctl_req *req); static void mirror_activate(struct gctl_req *req);
@ -71,10 +70,12 @@ struct g_command class_commands[] = {
{ 'F', "nofailsync", NULL, G_TYPE_BOOL }, { 'F', "nofailsync", NULL, G_TYPE_BOOL },
{ 'h', "hardcode", NULL, G_TYPE_BOOL }, { 'h', "hardcode", NULL, G_TYPE_BOOL },
{ 'n', "noautosync", NULL, G_TYPE_BOOL }, { 'n', "noautosync", NULL, G_TYPE_BOOL },
{ 'p', "priority", &configure_priority, G_TYPE_NUMBER },
{ 's', "slice", &configure_slice, G_TYPE_NUMBER }, { 's', "slice", &configure_slice, G_TYPE_NUMBER },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
NULL, "[-adfFhnv] [-b balance] [-s slice] name" NULL, "[-adfFhnv] [-b balance] [-s slice] name\n"
"[-v] -p priority name prov"
}, },
{ "deactivate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, NULL, { "deactivate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, NULL,
"[-v] name prov ..." "[-v] name prov ..."

View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> .\" Copyright (c) 2004-2009 Pawel Jakub Dawidek <pjd@FreeBSD.org>
.\" All rights reserved. .\" All rights reserved.
.\" .\"
.\" Redistribution and use in source and binary forms, with or without .\" Redistribution and use in source and binary forms, with or without
@ -24,7 +24,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd November 1, 2006 .Dd August 1, 2009
.Dt GMIRROR 8 .Dt GMIRROR 8
.Os .Os
.Sh NAME .Sh NAME
@ -49,6 +49,12 @@
.Op Fl s Ar slice .Op Fl s Ar slice
.Ar name .Ar name
.Nm .Nm
.Cm configure
.Op Fl v
.Fl p Ar priority
.Ar name
.Ar prov
.Nm
.Cm rebuild .Cm rebuild
.Op Fl v .Op Fl v
.Ar name .Ar name
@ -115,8 +121,8 @@ indicates an action to be performed:
.It Cm label .It Cm label
Create a mirror. Create a mirror.
The order of components is important, because a component's priority is based on its position The order of components is important, because a component's priority is based on its position
(starting from 0). (starting from 0 to 255).
The component with the biggest priority is used by the The component with the biggest priority (the lowest number) is used by the
.Cm prefer .Cm prefer
balance algorithm balance algorithm
and is also used as a master component when resynchronization is needed, and is also used as a master component when resynchronization is needed,
@ -159,7 +165,7 @@ Clear metadata on the given providers.
Configure the given device. Configure the given device.
.Pp .Pp
Additional options include: Additional options include:
.Bl -tag -width ".Fl b Ar balance" .Bl -tag -width ".Fl p Ar priority"
.It Fl a .It Fl a
Turn on autosynchronization of stale components. Turn on autosynchronization of stale components.
.It Fl b Ar balance .It Fl b Ar balance
@ -175,6 +181,9 @@ Assumes device is in consistent state.
Hardcode providers' names in metadata. Hardcode providers' names in metadata.
.It Fl n .It Fl n
Turn off autosynchronization of stale components. Turn off autosynchronization of stale components.
.It Fl p Ar priority
Specifies priority for the given component
.Ar prov .
.It Fl s Ar slice .It Fl s Ar slice
Specifies slice size for Specifies slice size for
.Cm split .Cm split

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> * Copyright (c) 2004-2009 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -93,19 +93,19 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
{ {
struct g_mirror_softc *sc; struct g_mirror_softc *sc;
struct g_mirror_disk *disk; struct g_mirror_disk *disk;
const char *name, *balancep; const char *name, *balancep, *prov;
intmax_t *slicep; intmax_t *slicep, *priority;
uint32_t slice; uint32_t slice;
uint8_t balance; uint8_t balance;
int *autosync, *noautosync, *failsync, *nofailsync, *hardcode, *dynamic; int *autosync, *noautosync, *failsync, *nofailsync, *hardcode, *dynamic;
int *nargs, do_sync = 0, dirty = 1; int *nargs, do_sync = 0, dirty = 1, do_priority = 0;
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
if (nargs == NULL) { if (nargs == NULL) {
gctl_error(req, "No '%s' argument.", "nargs"); gctl_error(req, "No '%s' argument.", "nargs");
return; return;
} }
if (*nargs != 1) { if (*nargs != 1 && *nargs != 2) {
gctl_error(req, "Invalid number of arguments."); gctl_error(req, "Invalid number of arguments.");
return; return;
} }
@ -149,6 +149,29 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "No '%s' argument.", "dynamic"); gctl_error(req, "No '%s' argument.", "dynamic");
return; return;
} }
priority = gctl_get_paraml(req, "priority", sizeof(*priority));
if (priority == NULL) {
gctl_error(req, "No '%s' argument.", "priority");
return;
}
if (*priority < -1 || *priority > 255) {
gctl_error(req, "Priority range is 0 to 255, %jd given",
*priority);
return;
}
/*
* Since we have a priority, we also need a provider now.
* Note: be WARNS safe, by always assigning prov and only throw an
* error if *priority != -1.
*/
prov = gctl_get_asciiparam(req, "arg1");
if (*priority > -1) {
if (prov == NULL) {
gctl_error(req, "Priority needs a disk name");
return;
}
do_priority = 1;
}
if (*autosync && *noautosync) { if (*autosync && *noautosync) {
gctl_error(req, "'%s' and '%s' specified.", "autosync", gctl_error(req, "'%s' and '%s' specified.", "autosync",
"noautosync"); "noautosync");
@ -189,19 +212,32 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
slice = sc->sc_slice; slice = sc->sc_slice;
else else
slice = *slicep; slice = *slicep;
if (g_mirror_ndisks(sc, -1) < sc->sc_ndisks) { /* Enforce usage() of -p not allowing any other options. */
if (do_priority && (*autosync || *noautosync || *failsync ||
*nofailsync || *hardcode || *dynamic || *slicep != -1 ||
strcmp(balancep, "none") != 0)) {
sx_xunlock(&sc->sc_lock); sx_xunlock(&sc->sc_lock);
gctl_error(req, "Not all disks connected. Try 'forget' command " gctl_error(req, "only -p accepted when setting priority");
"first.");
return; return;
} }
if (sc->sc_balance == balance && sc->sc_slice == slice && !*autosync && if (sc->sc_balance == balance && sc->sc_slice == slice && !*autosync &&
!*noautosync && !*failsync && !*nofailsync && !*hardcode && !*noautosync && !*failsync && !*nofailsync && !*hardcode &&
!*dynamic) { !*dynamic && !do_priority) {
sx_xunlock(&sc->sc_lock); sx_xunlock(&sc->sc_lock);
gctl_error(req, "Nothing has changed."); gctl_error(req, "Nothing has changed.");
return; return;
} }
if ((!do_priority && *nargs != 1) || (do_priority && *nargs != 2)) {
sx_xunlock(&sc->sc_lock);
gctl_error(req, "Invalid number of arguments.");
return;
}
if (g_mirror_ndisks(sc, -1) < sc->sc_ndisks) {
sx_xunlock(&sc->sc_lock);
gctl_error(req, "Not all disks connected. Try 'forget' command "
"first.");
return;
}
sc->sc_balance = balance; sc->sc_balance = balance;
sc->sc_slice = slice; sc->sc_slice = slice;
if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOAUTOSYNC) != 0) { if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOAUTOSYNC) != 0) {
@ -223,6 +259,23 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
} }
} }
LIST_FOREACH(disk, &sc->sc_disks, d_next) { LIST_FOREACH(disk, &sc->sc_disks, d_next) {
/*
* Handle priority first, since we only need one disk, do one
* operation on it and then we're done. No need to check other
* flags, as usage doesn't allow it.
*/
if (do_priority) {
if (strcmp(disk->d_name, prov) == 0) {
if (disk->d_priority == *priority)
gctl_error(req, "Nothing has changed.");
else {
disk->d_priority = *priority;
g_mirror_update_metadata(disk);
}
break;
}
continue;
}
if (do_sync) { if (do_sync) {
if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING) if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING)
disk->d_flags &= ~G_MIRROR_DISK_FLAG_FORCE_SYNC; disk->d_flags &= ~G_MIRROR_DISK_FLAG_FORCE_SYNC;