1152615Sle/*- 2152615Sle * Copyright (c) 2005 Chris Jones 3152615Sle * All rights reserved. 4152615Sle * 5152615Sle * This software was developed for the FreeBSD Project by Chris Jones 6152615Sle * thanks to the support of Google's Summer of Code program and 7152615Sle * mentoring by Lukas Ertl. 8152634Sle * 9152615Sle * Redistribution and use in source and binary forms, with or without 10152615Sle * modification, are permitted provided that the following conditions 11152615Sle * are met: 12152615Sle * 1. Redistributions of source code must retain the above copyright 13152615Sle * notice, this list of conditions and the following disclaimer. 14152615Sle * 2. Redistributions in binary form must reproduce the above copyright 15152615Sle * notice, this list of conditions and the following disclaimer in the 16152615Sle * documentation and/or other materials provided with the distribution. 17152634Sle * 18152615Sle * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19152615Sle * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20152615Sle * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21152615Sle * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 22152615Sle * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23152615Sle * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24152615Sle * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25152615Sle * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26152615Sle * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27152615Sle * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28152615Sle * SUCH DAMAGE. 29152615Sle * 30152615Sle */ 31152615Sle 32152615Sle#include <sys/cdefs.h> 33152615Sle__FBSDID("$FreeBSD$"); 34152615Sle 35152615Sle#include <sys/param.h> 36152615Sle#include <sys/libkern.h> 37152615Sle#include <sys/malloc.h> 38152615Sle 39152615Sle#include <geom/geom.h> 40152615Sle#include <geom/vinum/geom_vinum_var.h> 41152615Sle#include <geom/vinum/geom_vinum.h> 42152615Sle 43152615Slevoid 44152615Slegv_rename(struct g_geom *gp, struct gctl_req *req) 45152615Sle{ 46152615Sle struct gv_softc *sc; 47152615Sle struct gv_volume *v; 48152615Sle struct gv_plex *p; 49152615Sle struct gv_sd *s; 50152615Sle struct gv_drive *d; 51190507Slulf char *newname, *object, *name; 52190507Slulf int *flags, type; 53152615Sle 54152615Sle sc = gp->softc; 55152615Sle 56152615Sle flags = gctl_get_paraml(req, "flags", sizeof(*flags)); 57185309Slulf if (flags == NULL) { 58185309Slulf gctl_error(req, "no flags given"); 59185309Slulf return; 60185309Slulf } 61152615Sle 62152615Sle newname = gctl_get_param(req, "newname", NULL); 63152615Sle if (newname == NULL) { 64152615Sle gctl_error(req, "no new name given"); 65152615Sle return; 66152615Sle } 67152615Sle 68152615Sle object = gctl_get_param(req, "object", NULL); 69152615Sle if (object == NULL) { 70152615Sle gctl_error(req, "no object given"); 71152615Sle return; 72152615Sle } 73152615Sle 74152615Sle type = gv_object_type(sc, object); 75152615Sle switch (type) { 76152615Sle case GV_TYPE_VOL: 77152615Sle v = gv_find_vol(sc, object); 78152615Sle if (v == NULL) { 79152615Sle gctl_error(req, "unknown volume '%s'", object); 80152615Sle return; 81152615Sle } 82190507Slulf name = g_malloc(GV_MAXVOLNAME, M_WAITOK | M_ZERO); 83190507Slulf strlcpy(name, newname, GV_MAXVOLNAME); 84190507Slulf gv_post_event(sc, GV_EVENT_RENAME_VOL, v, name, *flags, 0); 85152615Sle break; 86152615Sle case GV_TYPE_PLEX: 87152615Sle p = gv_find_plex(sc, object); 88152615Sle if (p == NULL) { 89152615Sle gctl_error(req, "unknown plex '%s'", object); 90152615Sle return; 91152615Sle } 92190507Slulf name = g_malloc(GV_MAXPLEXNAME, M_WAITOK | M_ZERO); 93190507Slulf strlcpy(name, newname, GV_MAXPLEXNAME); 94190507Slulf gv_post_event(sc, GV_EVENT_RENAME_PLEX, p, name, *flags, 0); 95152615Sle break; 96152615Sle case GV_TYPE_SD: 97152615Sle s = gv_find_sd(sc, object); 98152615Sle if (s == NULL) { 99152615Sle gctl_error(req, "unknown subdisk '%s'", object); 100152615Sle return; 101152615Sle } 102190507Slulf name = g_malloc(GV_MAXSDNAME, M_WAITOK | M_ZERO); 103190507Slulf strlcpy(name, newname, GV_MAXSDNAME); 104190507Slulf gv_post_event(sc, GV_EVENT_RENAME_SD, s, name, *flags, 0); 105152615Sle break; 106152615Sle case GV_TYPE_DRIVE: 107152615Sle d = gv_find_drive(sc, object); 108152615Sle if (d == NULL) { 109152615Sle gctl_error(req, "unknown drive '%s'", object); 110152615Sle return; 111152615Sle } 112190507Slulf name = g_malloc(GV_MAXDRIVENAME, M_WAITOK | M_ZERO); 113190507Slulf strlcpy(name, newname, GV_MAXDRIVENAME); 114190507Slulf gv_post_event(sc, GV_EVENT_RENAME_DRIVE, d, name, *flags, 0); 115152615Sle break; 116152615Sle default: 117152615Sle gctl_error(req, "unknown object '%s'", object); 118152615Sle return; 119152615Sle } 120152615Sle} 121152615Sle 122190507Slulfint 123190507Slulfgv_rename_drive(struct gv_softc *sc, struct gv_drive *d, char *newname, 124190507Slulf int flags) 125152615Sle{ 126152615Sle struct gv_sd *s; 127152615Sle 128152615Sle KASSERT(d != NULL, ("gv_rename_drive: NULL d")); 129152615Sle 130190507Slulf if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) { 131190507Slulf G_VINUM_DEBUG(1, "drive name '%s' already in use", newname); 132190507Slulf return (GV_ERR_NAMETAKEN); 133152615Sle } 134152615Sle 135190507Slulf strlcpy(d->name, newname, sizeof(d->name)); 136190507Slulf if (d->hdr != NULL) 137190507Slulf strlcpy(d->hdr->label.name, newname, sizeof(d->hdr->label.name)); 138152615Sle 139152615Sle LIST_FOREACH(s, &d->subdisks, from_drive) 140190507Slulf strlcpy(s->drive, d->name, sizeof(s->drive)); 141152615Sle 142152615Sle return (0); 143152615Sle} 144152615Sle 145190507Slulfint 146190507Slulfgv_rename_plex(struct gv_softc *sc, struct gv_plex *p, char *newname, int flags) 147152615Sle{ 148190507Slulf char newsd[GV_MAXSDNAME]; 149152615Sle struct gv_sd *s; 150190507Slulf char *ptr; 151152615Sle int err; 152152615Sle 153152615Sle KASSERT(p != NULL, ("gv_rename_plex: NULL p")); 154152615Sle 155190507Slulf if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) { 156190507Slulf G_VINUM_DEBUG(1, "plex name '%s' already in use", newname); 157190507Slulf return (GV_ERR_NAMETAKEN); 158152615Sle } 159152615Sle 160152633Sle /* 161152633Sle * Locate the plex number part of the plex names. 162190507Slulf * XXX: might be a good idea to sanitize input a bit more 163152633Sle */ 164190507Slulf ptr = strrchr(newname, '.'); 165190507Slulf if (ptr == NULL) { 166190507Slulf G_VINUM_DEBUG(0, "proposed plex name '%s' is not a valid plex " 167152633Sle "name", newname); 168190507Slulf return (GV_ERR_INVNAME); 169152633Sle } 170152615Sle 171190507Slulf strlcpy(p->name, newname, sizeof(p->name)); 172152615Sle 173152615Sle /* Fix up references and potentially rename subdisks. */ 174152615Sle LIST_FOREACH(s, &p->subdisks, in_plex) { 175190507Slulf strlcpy(s->plex, p->name, sizeof(s->plex)); 176213318Slulf if (flags & GV_FLAG_R) { 177152633Sle /* 178190507Slulf * Look for the two last dots in the string, and assume 179190507Slulf * that the old value was ok. 180152633Sle */ 181190507Slulf ptr = strrchr(s->name, '.'); 182190507Slulf if (ptr == NULL) 183190507Slulf return (GV_ERR_INVNAME); 184190507Slulf ptr++; 185190507Slulf snprintf(newsd, sizeof(newsd), "%s.%s", p->name, ptr); 186190507Slulf err = gv_rename_sd(sc, s, newsd, flags); 187152615Sle if (err) 188190507Slulf return (err); 189152615Sle } 190152615Sle } 191190507Slulf return (0); 192152615Sle} 193152615Sle 194152615Sle/* 195152615Sle * gv_rename_sd: renames a subdisk. Note that the 'flags' argument is ignored, 196152615Sle * since there are no structures below a subdisk. Similarly, we don't have to 197152615Sle * clean up any references elsewhere to the subdisk's name. 198152615Sle */ 199190507Slulfint 200190507Slulfgv_rename_sd(struct gv_softc *sc, struct gv_sd *s, char *newname, int flags) 201152615Sle{ 202190507Slulf char *dot1, *dot2; 203152615Sle 204152615Sle KASSERT(s != NULL, ("gv_rename_sd: NULL s")); 205152615Sle 206190507Slulf if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) { 207190507Slulf G_VINUM_DEBUG(1, "subdisk name %s already in use", newname); 208190507Slulf return (GV_ERR_NAMETAKEN); 209152615Sle } 210152615Sle 211190507Slulf /* Locate the sd number part of the sd names. */ 212190507Slulf dot1 = strchr(newname, '.'); 213190507Slulf if (dot1 == NULL || (dot2 = strchr(dot1 + 1, '.')) == NULL) { 214190507Slulf G_VINUM_DEBUG(0, "proposed sd name '%s' is not a valid sd name", 215152633Sle newname); 216190507Slulf return (GV_ERR_INVNAME); 217152633Sle } 218190507Slulf strlcpy(s->name, newname, sizeof(s->name)); 219190507Slulf return (0); 220152615Sle} 221152615Sle 222190507Slulfint 223190507Slulfgv_rename_vol(struct gv_softc *sc, struct gv_volume *v, char *newname, 224190507Slulf int flags) 225152615Sle{ 226190507Slulf struct g_provider *pp; 227152615Sle struct gv_plex *p; 228190507Slulf char newplex[GV_MAXPLEXNAME], *ptr; 229152615Sle int err; 230152615Sle 231152615Sle KASSERT(v != NULL, ("gv_rename_vol: NULL v")); 232190507Slulf pp = v->provider; 233190507Slulf KASSERT(pp != NULL, ("gv_rename_vol: NULL pp")); 234152615Sle 235190507Slulf if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) { 236190507Slulf G_VINUM_DEBUG(1, "volume name %s already in use", newname); 237190507Slulf return (GV_ERR_NAMETAKEN); 238152615Sle } 239152615Sle 240152615Sle /* Rename the volume. */ 241190507Slulf strlcpy(v->name, newname, sizeof(v->name)); 242152615Sle 243152615Sle /* Fix up references and potentially rename plexes. */ 244152615Sle LIST_FOREACH(p, &v->plexes, in_volume) { 245190507Slulf strlcpy(p->volume, v->name, sizeof(p->volume)); 246213318Slulf if (flags & GV_FLAG_R) { 247152633Sle /* 248190507Slulf * Look for the last dot in the string, and assume that 249190507Slulf * the old value was ok. 250152633Sle */ 251190507Slulf ptr = strrchr(p->name, '.'); 252190507Slulf ptr++; 253190507Slulf snprintf(newplex, sizeof(newplex), "%s.%s", v->name, ptr); 254190507Slulf err = gv_rename_plex(sc, p, newplex, flags); 255152615Sle if (err) 256152633Sle return (err); 257152615Sle } 258152615Sle } 259152634Sle 260152615Sle return (0); 261152615Sle} 262