From b5dce617d871a3eff4c9215b2a00aa35fe46e107 Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Sun, 21 Mar 2010 15:02:47 +0000 Subject: [PATCH] Add 'rotate' and 'getactive' verbs to provide some control and information about what the currently active path is. Sponsored by: Panasas MFC after: 1 month --- sbin/geom/class/multipath/geom_multipath.c | 8 ++ sys/geom/multipath/g_multipath.c | 87 ++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/sbin/geom/class/multipath/geom_multipath.c b/sbin/geom/class/multipath/geom_multipath.c index 4319d0421c2a..ab91e2d884ca 100644 --- a/sbin/geom/class/multipath/geom_multipath.c +++ b/sbin/geom/class/multipath/geom_multipath.c @@ -62,6 +62,14 @@ struct g_command class_commands[] = { "clear", G_FLAG_VERBOSE, mp_main, G_NULL_OPTS, NULL, "[-v] prov ..." }, + { + "rotate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, + NULL, "[-v] prov ..." + }, + { + "getactive", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, + NULL, "[-v] prov ..." + }, G_CMD_SENTINEL }; diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index a2e61586b52e..1888d7069c9e 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -70,6 +70,8 @@ static int g_multipath_destroy(struct g_geom *); static int g_multipath_destroy_geom(struct gctl_req *, struct g_class *, struct g_geom *); +static int g_multipath_rotate(struct g_geom *); + static g_taste_t g_multipath_taste; static g_ctl_req_t g_multipath_config; static g_init_t g_multipath_init; @@ -406,6 +408,30 @@ g_multipath_destroy_geom(struct gctl_req *req, struct g_class *mp, return (g_multipath_destroy(gp)); } +static int +g_multipath_rotate(struct g_geom *gp) +{ + struct g_consumer *lcp; + struct g_multipath_softc *sc = gp->softc; + + g_topology_assert(); + if (sc == NULL) + return (ENXIO); + LIST_FOREACH(lcp, &gp->consumer, consumer) { + if ((lcp->index & MP_BAD) == 0) { + if (sc->cp_active != lcp) { + break; + } + } + } + if (lcp) { + sc->cp_active = lcp; + printf("GEOM_MULTIPATH: %s now active path in %s\n", + lcp->provider->name, sc->sc_name); + } + return (0); +} + static void g_multipath_init(struct g_class *mp) { @@ -722,6 +748,63 @@ g_multipath_ctl_destroy(struct gctl_req *req, struct g_class *mp) } } +static void +g_multipath_ctl_rotate(struct gctl_req *req, struct g_class *mp) +{ + struct g_geom *gp; + const char *name; + int error; + + g_topology_assert(); + + name = gctl_get_asciiparam(req, "arg0"); + if (name == NULL) { + gctl_error(req, "No 'arg0' argument"); + return; + } + gp = g_multipath_find_geom(mp, name); + if (gp == NULL) { + gctl_error(req, "Device %s is invalid", name); + return; + } + error = g_multipath_rotate(gp); + if (error != 0) { + gctl_error(req, "failed to rotate %s (err=%d)", name, error); + } +} + +static void +g_multipath_ctl_getactive(struct gctl_req *req, struct g_class *mp) +{ + struct sbuf *sb; + struct g_geom *gp; + struct g_multipath_softc *sc; + const char *name; + + sb = sbuf_new_auto(); + + g_topology_assert(); + name = gctl_get_asciiparam(req, "arg0"); + if (name == NULL) { + gctl_error(req, "No 'arg0' argument"); + return; + } + gp = g_multipath_find_geom(mp, name); + if (gp == NULL) { + gctl_error(req, "Device %s is invalid", name); + return; + } + sc = gp->softc; + if (sc->cp_active) { + sbuf_printf(sb, "%s\n", sc->cp_active->provider->name); + } else { + sbuf_printf(sb, "none\n"); + } + sbuf_finish(sb); + gctl_set_param_err(req, "output", sbuf_data(sb), sbuf_len(sb) + 1); + sbuf_delete(sb); +} + static void g_multipath_config(struct gctl_req *req, struct g_class *mp, const char *verb) { @@ -736,6 +819,10 @@ g_multipath_config(struct gctl_req *req, struct g_class *mp, const char *verb) g_multipath_ctl_create(req, mp); } else if (strcmp(verb, "destroy") == 0) { g_multipath_ctl_destroy(req, mp); + } else if (strcmp(verb, "rotate") == 0) { + g_multipath_ctl_rotate(req, mp); + } else if (strcmp(verb, "getactive") == 0) { + g_multipath_ctl_getactive(req, mp); } else { gctl_error(req, "Unknown verb %s", verb); }