geom_vinum_rm.c (185309) | geom_vinum_rm.c (190507) |
---|---|
1/*- | 1/*- |
2 * Copyright (c) 2004 Lukas Ertl | 2 * Copyright (c) 2004, 2007 Lukas Ertl |
3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 10 unchanged lines hidden (view full) --- 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h> | 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 10 unchanged lines hidden (view full) --- 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: head/sys/geom/vinum/geom_vinum_rm.c 185309 2008-11-25 19:13:58Z lulf $"); | 29__FBSDID("$FreeBSD: head/sys/geom/vinum/geom_vinum_rm.c 190507 2009-03-28 17:20:08Z lulf $"); |
30 31#include <sys/param.h> 32#include <sys/libkern.h> | 30 31#include <sys/param.h> 32#include <sys/libkern.h> |
33#include <sys/kernel.h> | |
34#include <sys/malloc.h> 35 36#include <geom/geom.h> 37#include <geom/vinum/geom_vinum_var.h> 38#include <geom/vinum/geom_vinum.h> | 33#include <sys/malloc.h> 34 35#include <geom/geom.h> 36#include <geom/vinum/geom_vinum_var.h> 37#include <geom/vinum/geom_vinum.h> |
39#include <geom/vinum/geom_vinum_share.h> | |
40 | 38 |
41static int gv_rm_drive(struct gv_softc *, struct gctl_req *, 42 struct gv_drive *, int); 43static int gv_rm_plex(struct gv_softc *, struct gctl_req *, 44 struct gv_plex *, int); 45static int gv_rm_vol(struct gv_softc *, struct gctl_req *, 46 struct gv_volume *, int); 47 | |
48/* General 'remove' routine. */ 49void 50gv_remove(struct g_geom *gp, struct gctl_req *req) 51{ 52 struct gv_softc *sc; 53 struct gv_volume *v; 54 struct gv_plex *p; 55 struct gv_sd *s; 56 struct gv_drive *d; 57 int *argc, *flags; 58 char *argv, buf[20]; | 39/* General 'remove' routine. */ 40void 41gv_remove(struct g_geom *gp, struct gctl_req *req) 42{ 43 struct gv_softc *sc; 44 struct gv_volume *v; 45 struct gv_plex *p; 46 struct gv_sd *s; 47 struct gv_drive *d; 48 int *argc, *flags; 49 char *argv, buf[20]; |
59 int i, type, err; | 50 int i, type; |
60 61 argc = gctl_get_paraml(req, "argc", sizeof(*argc)); 62 63 if (argc == NULL || *argc == 0) { 64 gctl_error(req, "no arguments given"); 65 return; 66 } 67 68 flags = gctl_get_paraml(req, "flags", sizeof(*flags)); 69 if (flags == NULL) { 70 gctl_error(req, "no flags given"); 71 return; 72 } 73 74 sc = gp->softc; 75 | 51 52 argc = gctl_get_paraml(req, "argc", sizeof(*argc)); 53 54 if (argc == NULL || *argc == 0) { 55 gctl_error(req, "no arguments given"); 56 return; 57 } 58 59 flags = gctl_get_paraml(req, "flags", sizeof(*flags)); 60 if (flags == NULL) { 61 gctl_error(req, "no flags given"); 62 return; 63 } 64 65 sc = gp->softc; 66 |
67 /* XXX config locking */ 68 |
|
76 for (i = 0; i < *argc; i++) { 77 snprintf(buf, sizeof(buf), "argv%d", i); 78 argv = gctl_get_param(req, buf, NULL); 79 if (argv == NULL) 80 continue; 81 type = gv_object_type(sc, argv); 82 switch (type) { 83 case GV_TYPE_VOL: 84 v = gv_find_vol(sc, argv); | 69 for (i = 0; i < *argc; i++) { 70 snprintf(buf, sizeof(buf), "argv%d", i); 71 argv = gctl_get_param(req, buf, NULL); 72 if (argv == NULL) 73 continue; 74 type = gv_object_type(sc, argv); 75 switch (type) { 76 case GV_TYPE_VOL: 77 v = gv_find_vol(sc, argv); |
85 if (v == NULL) { 86 gctl_error(req, "unknown volume '%s'", argv); | 78 79 /* 80 * If this volume has plexes, we want a recursive 81 * removal. 82 */ 83 if (!LIST_EMPTY(&v->plexes) && !(*flags & GV_FLAG_R)) { 84 gctl_error(req, "volume '%s' has attached " 85 "plexes - need recursive removal", v->name); |
87 return; 88 } | 86 return; 87 } |
89 err = gv_rm_vol(sc, req, v, *flags); 90 if (err) 91 return; | 88 89 gv_post_event(sc, GV_EVENT_RM_VOLUME, v, NULL, 0, 0); |
92 break; | 90 break; |
91 |
|
93 case GV_TYPE_PLEX: 94 p = gv_find_plex(sc, argv); | 92 case GV_TYPE_PLEX: 93 p = gv_find_plex(sc, argv); |
95 if (p == NULL) { 96 gctl_error(req, "unknown plex '%s'", argv); | 94 95 /* 96 * If this plex has subdisks, we want a recursive 97 * removal. 98 */ 99 if (!LIST_EMPTY(&p->subdisks) && 100 !(*flags & GV_FLAG_R)) { 101 gctl_error(req, "plex '%s' has attached " 102 "subdisks - need recursive removal", 103 p->name); |
97 return; 98 } | 104 return; 105 } |
99 err = gv_rm_plex(sc, req, p, *flags); 100 if (err) | 106 107 /* Don't allow removal of the only plex of a volume. */ 108 if (p->vol_sc != NULL && p->vol_sc->plexcount == 1) { 109 gctl_error(req, "plex '%s' is still attached " 110 "to volume '%s'", p->name, p->volume); |
101 return; | 111 return; |
112 } 113 114 gv_post_event(sc, GV_EVENT_RM_PLEX, p, NULL, 0, 0); |
|
102 break; | 115 break; |
116 |
|
103 case GV_TYPE_SD: 104 s = gv_find_sd(sc, argv); | 117 case GV_TYPE_SD: 118 s = gv_find_sd(sc, argv); |
105 if (s == NULL) { 106 gctl_error(req, "unknown subdisk '%s'", argv); | 119 120 /* Don't allow removal if attached to a plex. */ 121 if (s->plex_sc != NULL) { 122 gctl_error(req, "subdisk '%s' is still attached" 123 " to plex '%s'", s->name, s->plex_sc->name); |
107 return; 108 } | 124 return; 125 } |
109 err = gv_rm_sd(sc, req, s, *flags); 110 if (err) 111 return; | 126 127 gv_post_event(sc, GV_EVENT_RM_SD, s, NULL, 0, 0); |
112 break; | 128 break; |
129 |
|
113 case GV_TYPE_DRIVE: 114 d = gv_find_drive(sc, argv); | 130 case GV_TYPE_DRIVE: 131 d = gv_find_drive(sc, argv); |
115 if (d == NULL) { 116 gctl_error(req, "unknown drive '%s'", argv); | 132 /* We don't allow to remove open drives. */ 133 if (gv_consumer_is_open(d->consumer) && 134 !(*flags & GV_FLAG_F)) { 135 gctl_error(req, "drive '%s' is open", d->name); |
117 return; 118 } | 136 return; 137 } |
119 err = gv_rm_drive(sc, req, d, *flags); 120 if (err) | 138 139 /* A drive with subdisks needs a recursive removal. */ 140/* if (!LIST_EMPTY(&d->subdisks) && 141 !(*flags & GV_FLAG_R)) { 142 gctl_error(req, "drive '%s' still has subdisks" 143 " - need recursive removal", d->name); |
121 return; | 144 return; |
145 }*/ 146 147 gv_post_event(sc, GV_EVENT_RM_DRIVE, d, NULL, *flags, 148 0); |
|
122 break; | 149 break; |
150 |
|
123 default: 124 gctl_error(req, "unknown object '%s'", argv); 125 return; 126 } 127 } 128 | 151 default: 152 gctl_error(req, "unknown object '%s'", argv); 153 return; 154 } 155 } 156 |
129 gv_save_config_all(sc); | 157 gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0); |
130} 131 132/* Resets configuration */ 133int | 158} 159 160/* Resets configuration */ 161int |
134gv_resetconfig(struct g_geom *gp, struct gctl_req *req) | 162gv_resetconfig(struct gv_softc *sc) |
135{ | 163{ |
136 struct gv_softc *sc; | |
137 struct gv_drive *d, *d2; 138 struct gv_volume *v, *v2; 139 struct gv_plex *p, *p2; 140 struct gv_sd *s, *s2; | 164 struct gv_drive *d, *d2; 165 struct gv_volume *v, *v2; 166 struct gv_plex *p, *p2; 167 struct gv_sd *s, *s2; |
141 int flags; | |
142 | 168 |
143 d = NULL; 144 d2 = NULL; 145 p = NULL; 146 p2 = NULL; 147 s = NULL; 148 s2 = NULL; 149 flags = GV_FLAG_R; 150 sc = gp->softc; 151 /* First loop through to make sure no volumes are up */ 152 LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) { 153 if (gv_is_open(v->geom)) { 154 gctl_error(req, "volume '%s' is busy", v->name); 155 return (-1); | 169 /* First make sure nothing is open. */ 170 LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) { 171 if (gv_consumer_is_open(d->consumer)) { 172 return (GV_ERR_ISBUSY); |
156 } 157 } 158 /* Then if not, we remove everything. */ | 173 } 174 } 175 /* Then if not, we remove everything. */ |
159 LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) 160 gv_rm_vol(sc, req, v, flags); 161 LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) 162 gv_rm_plex(sc, req, p, flags); | |
163 LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2) | 176 LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2) |
164 gv_rm_sd(sc, req, s, flags); | 177 gv_rm_sd(sc, s); |
165 LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) | 178 LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) |
166 gv_rm_drive(sc, req, d, flags); 167 gv_save_config_all(sc); | 179 gv_rm_drive(sc, d, 0); 180 LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) 181 gv_rm_plex(sc, p); 182 LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) 183 gv_rm_vol(sc, v); 184 185 gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0); 186 |
168 return (0); 169} 170 171/* Remove a volume. */ | 187 return (0); 188} 189 190/* Remove a volume. */ |
172static int 173gv_rm_vol(struct gv_softc *sc, struct gctl_req *req, struct gv_volume *v, int flags) | 191void 192gv_rm_vol(struct gv_softc *sc, struct gv_volume *v) |
174{ | 193{ |
175 struct g_geom *gp; | 194 struct g_provider *pp; |
176 struct gv_plex *p, *p2; | 195 struct gv_plex *p, *p2; |
177 int err; | |
178 | 196 |
179 g_topology_assert(); | |
180 KASSERT(v != NULL, ("gv_rm_vol: NULL v")); | 197 KASSERT(v != NULL, ("gv_rm_vol: NULL v")); |
198 pp = v->provider; 199 KASSERT(pp != NULL, ("gv_rm_vol: NULL pp")); |
|
181 | 200 |
182 /* If this volume has plexes, we want a recursive removal. */ 183 if (!LIST_EMPTY(&v->plexes) && !(flags & GV_FLAG_R)) { 184 gctl_error(req, "volume '%s' has attached plexes", v->name); 185 return (-1); 186 } 187 188 gp = v->geom; 189 | |
190 /* Check if any of our consumers is open. */ | 201 /* Check if any of our consumers is open. */ |
191 if (gp != NULL && gv_is_open(gp)) { 192 gctl_error(req, "volume '%s' is busy", v->name); 193 return (-1); | 202 if (gv_provider_is_open(pp)) { 203 G_VINUM_DEBUG(0, "Unable to remove %s: volume still in use", 204 v->name); 205 return; |
194 } 195 196 /* Remove the plexes our volume has. */ | 206 } 207 208 /* Remove the plexes our volume has. */ |
197 LIST_FOREACH_SAFE(p, &v->plexes, in_volume, p2) { 198 v->plexcount--; 199 LIST_REMOVE(p, in_volume); 200 p->vol_sc = NULL; | 209 LIST_FOREACH_SAFE(p, &v->plexes, in_volume, p2) 210 gv_rm_plex(sc, p); |
201 | 211 |
202 err = gv_rm_plex(sc, req, p, flags); 203 if (err) 204 return (err); 205 } 206 207 /* Clean up and let our geom fade away. */ | 212 /* Clean up. */ |
208 LIST_REMOVE(v, volume); | 213 LIST_REMOVE(v, volume); |
209 gv_kill_vol_thread(v); | |
210 g_free(v); | 214 g_free(v); |
211 if (gp != NULL) { 212 gp->softc = NULL; 213 g_wither_geom(gp, ENXIO); 214 } | |
215 | 215 |
216 return (0); | 216 /* Get rid of the volume's provider. */ 217 if (pp != NULL) { 218 g_topology_lock(); 219 pp->flags |= G_PF_WITHER; 220 g_orphan_provider(pp, ENXIO); 221 g_topology_unlock(); 222 } |
217} 218 219/* Remove a plex. */ | 223} 224 225/* Remove a plex. */ |
220static int 221gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int flags) | 226void 227gv_rm_plex(struct gv_softc *sc, struct gv_plex *p) |
222{ | 228{ |
223 struct g_geom *gp; | |
224 struct gv_volume *v; 225 struct gv_sd *s, *s2; | 229 struct gv_volume *v; 230 struct gv_sd *s, *s2; |
226 int err; | |
227 | 231 |
228 g_topology_assert(); 229 | |
230 KASSERT(p != NULL, ("gv_rm_plex: NULL p")); | 232 KASSERT(p != NULL, ("gv_rm_plex: NULL p")); |
233 v = p->vol_sc; |
|
231 | 234 |
232 /* If this plex has subdisks, we want a recursive removal. */ 233 if (!LIST_EMPTY(&p->subdisks) && !(flags & GV_FLAG_R)) { 234 gctl_error(req, "plex '%s' has attached subdisks", p->name); 235 return (-1); 236 } 237 238 if (p->vol_sc != NULL && p->vol_sc->plexcount == 1) { 239 gctl_error(req, "plex '%s' is still attached to volume '%s'", 240 p->name, p->volume); 241 return (-1); 242 } 243 244 gp = p->geom; 245 | |
246 /* Check if any of our consumers is open. */ | 235 /* Check if any of our consumers is open. */ |
247 if (gp != NULL && gv_is_open(gp)) { 248 gctl_error(req, "plex '%s' is busy", p->name); 249 return (-1); | 236 if (v != NULL && gv_provider_is_open(v->provider) && v->plexcount < 2) { 237 G_VINUM_DEBUG(0, "Unable to remove %s: volume still in use", 238 p->name); 239 return; |
250 } 251 252 /* Remove the subdisks our plex has. */ | 240 } 241 242 /* Remove the subdisks our plex has. */ |
253 LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) { 254#if 0 255 LIST_REMOVE(s, in_plex); 256 s->plex_sc = NULL; 257#endif | 243 LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) 244 gv_rm_sd(sc, s); |
258 | 245 |
259 err = gv_rm_sd(sc, req, s, flags); 260 if (err) 261 return (err); 262 } 263 | |
264 v = p->vol_sc; 265 /* Clean up and let our geom fade away. */ 266 LIST_REMOVE(p, plex); 267 if (p->vol_sc != NULL) { 268 p->vol_sc->plexcount--; 269 LIST_REMOVE(p, in_volume); 270 p->vol_sc = NULL; 271 /* Correctly update the volume size. */ 272 gv_update_vol_size(v, gv_vol_size(v)); 273 } 274 | 246 v = p->vol_sc; 247 /* Clean up and let our geom fade away. */ 248 LIST_REMOVE(p, plex); 249 if (p->vol_sc != NULL) { 250 p->vol_sc->plexcount--; 251 LIST_REMOVE(p, in_volume); 252 p->vol_sc = NULL; 253 /* Correctly update the volume size. */ 254 gv_update_vol_size(v, gv_vol_size(v)); 255 } 256 |
275 gv_kill_plex_thread(p); | |
276 g_free(p); | 257 g_free(p); |
277 278 if (gp != NULL) { 279 gp->softc = NULL; 280 g_wither_geom(gp, ENXIO); 281 } 282 283 return (0); | |
284} 285 286/* Remove a subdisk. */ | 258} 259 260/* Remove a subdisk. */ |
287int 288gv_rm_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, int flags) | 261void 262gv_rm_sd(struct gv_softc *sc, struct gv_sd *s) |
289{ | 263{ |
290 struct g_provider *pp; | |
291 struct gv_plex *p; 292 struct gv_volume *v; 293 294 KASSERT(s != NULL, ("gv_rm_sd: NULL s")); 295 | 264 struct gv_plex *p; 265 struct gv_volume *v; 266 267 KASSERT(s != NULL, ("gv_rm_sd: NULL s")); 268 |
296 pp = s->provider; | |
297 p = s->plex_sc; 298 v = NULL; 299 300 /* Clean up. */ 301 if (p != NULL) { 302 LIST_REMOVE(s, in_plex); | 269 p = s->plex_sc; 270 v = NULL; 271 272 /* Clean up. */ 273 if (p != NULL) { 274 LIST_REMOVE(s, in_plex); |
303 | 275 s->plex_sc = NULL; |
304 p->sdcount--; 305 /* Update the plexsize. */ 306 p->size = gv_plex_size(p); 307 v = p->vol_sc; 308 if (v != NULL) { 309 /* Update the size of our plex' volume. */ 310 gv_update_vol_size(v, gv_vol_size(v)); 311 } 312 } | 276 p->sdcount--; 277 /* Update the plexsize. */ 278 p->size = gv_plex_size(p); 279 v = p->vol_sc; 280 if (v != NULL) { 281 /* Update the size of our plex' volume. */ 282 gv_update_vol_size(v, gv_vol_size(v)); 283 } 284 } |
313 if (s->drive_sc) | 285 if (s->drive_sc && !(s->drive_sc->flags & GV_DRIVE_REFERENCED)) |
314 LIST_REMOVE(s, from_drive); 315 LIST_REMOVE(s, sd); 316 gv_free_sd(s); 317 g_free(s); | 286 LIST_REMOVE(s, from_drive); 287 LIST_REMOVE(s, sd); 288 gv_free_sd(s); 289 g_free(s); |
318 319 /* If the subdisk has a provider we need to clean up this one too. */ 320 if (pp != NULL) { 321 pp->flags |= G_PF_WITHER; 322 g_orphan_provider(pp, ENXIO); 323 } 324 325 return (0); | |
326} 327 328/* Remove a drive. */ | 290} 291 292/* Remove a drive. */ |
329static int 330gv_rm_drive(struct gv_softc *sc, struct gctl_req *req, struct gv_drive *d, int flags) | 293void 294gv_rm_drive(struct gv_softc *sc, struct gv_drive *d, int flags) |
331{ | 295{ |
332 struct g_geom *gp; | |
333 struct g_consumer *cp; 334 struct gv_freelist *fl, *fl2; 335 struct gv_plex *p; 336 struct gv_sd *s, *s2; 337 struct gv_volume *v; | 296 struct g_consumer *cp; 297 struct gv_freelist *fl, *fl2; 298 struct gv_plex *p; 299 struct gv_sd *s, *s2; 300 struct gv_volume *v; |
301 struct gv_drive *d2; |
|
338 int err; 339 340 KASSERT(d != NULL, ("gv_rm_drive: NULL d")); | 302 int err; 303 304 KASSERT(d != NULL, ("gv_rm_drive: NULL d")); |
341 gp = d->geom; 342 KASSERT(gp != NULL, ("gv_rm_drive: NULL gp")); | |
343 | 305 |
344 /* We don't allow to remove open drives. */ 345 if (gv_is_open(gp)) { 346 gctl_error(req, "drive '%s' is open", d->name); 347 return (-1); 348 } | 306 cp = d->consumer; |
349 | 307 |
350 /* A drive with subdisks needs a recursive removal. */ 351 if (!LIST_EMPTY(&d->subdisks) && !(flags & GV_FLAG_R)) { 352 gctl_error(req, "drive '%s' still has subdisks", d->name); 353 return (-1); 354 } | 308 if (cp != NULL) { 309 g_topology_lock(); 310 err = g_access(cp, 0, 1, 0); 311 g_topology_unlock(); |
355 | 312 |
356 cp = LIST_FIRST(&gp->consumer); 357 err = g_access(cp, 0, 1, 0); 358 if (err) { 359 G_VINUM_DEBUG(0, "%s: unable to access '%s', errno: " 360 "%d", __func__, cp->provider->name, err); 361 return (err); 362 } | 313 if (err) { 314 G_VINUM_DEBUG(0, "%s: couldn't access '%s', " 315 "errno: %d", __func__, cp->provider->name, err); 316 return; 317 } |
363 | 318 |
364 /* Clear the Vinum Magic. */ 365 d->hdr->magic = GV_NOMAGIC; 366 g_topology_unlock(); 367 err = gv_write_header(cp, d->hdr); 368 if (err) { 369 G_VINUM_DEBUG(0, "%s: unable to write header to '%s'" 370 ", errno: %d", __func__, cp->provider->name, err); 371 d->hdr->magic = GV_MAGIC; | 319 /* Clear the Vinum Magic. */ 320 d->hdr->magic = GV_NOMAGIC; 321 err = gv_write_header(cp, d->hdr); 322 if (err) 323 G_VINUM_DEBUG(0, "gv_rm_drive: couldn't write header to" 324 " '%s', errno: %d", cp->provider->name, err); 325 326 g_topology_lock(); 327 g_access(cp, -cp->acr, -cp->acw, -cp->ace); 328 g_detach(cp); 329 g_destroy_consumer(cp); 330 g_topology_unlock(); |
372 } | 331 } |
373 g_topology_lock(); 374 g_access(cp, 0, -1, 0); | |
375 376 /* Remove all associated subdisks, plexes, volumes. */ | 332 333 /* Remove all associated subdisks, plexes, volumes. */ |
377 if (!LIST_EMPTY(&d->subdisks)) { 378 LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) { 379 p = s->plex_sc; 380 if (p != NULL) { 381 v = p->vol_sc; 382 if (v != NULL) 383 gv_rm_vol(sc, req, v, flags); | 334 if (flags & GV_FLAG_R) { 335 if (!LIST_EMPTY(&d->subdisks)) { 336 LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) { 337 p = s->plex_sc; 338 if (p != NULL) { 339 v = p->vol_sc; 340 if (v != NULL) 341 gv_rm_vol(sc, v); 342 } |
384 } 385 } 386 } 387 388 /* Clean up. */ 389 LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) { 390 LIST_REMOVE(fl, freelist); 391 g_free(fl); 392 } | 343 } 344 } 345 } 346 347 /* Clean up. */ 348 LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) { 349 LIST_REMOVE(fl, freelist); 350 g_free(fl); 351 } |
393 LIST_REMOVE(d, drive); | |
394 | 352 |
395 gv_kill_drive_thread(d); 396 gp = d->geom; 397 d->geom = NULL; | 353 LIST_REMOVE(d, drive); |
398 g_free(d->hdr); | 354 g_free(d->hdr); |
355 356 /* Put ourself into referenced state if we have subdisks. */ 357 if (d->sdcount > 0) { 358 d->consumer = NULL; 359 d->hdr = NULL; 360 d->flags |= GV_DRIVE_REFERENCED; 361 snprintf(d->device, sizeof(d->device), "???"); 362 d->size = 0; 363 d->avail = 0; 364 d->freelist_entries = 0; 365 LIST_FOREACH(s, &d->subdisks, from_drive) { 366 s->flags |= GV_SD_TASTED; 367 gv_set_sd_state(s, GV_SD_DOWN, GV_SETSTATE_FORCE); 368 } 369 /* Shuffle around so we keep gv_is_newer happy. */ 370 LIST_REMOVE(d, drive); 371 d2 = LIST_FIRST(&sc->drives); 372 if (d2 == NULL) 373 LIST_INSERT_HEAD(&sc->drives, d, drive); 374 else 375 LIST_INSERT_AFTER(d2, d, drive); 376 return; 377 } |
|
399 g_free(d); | 378 g_free(d); |
400 gv_save_config_all(sc); 401 g_wither_geom(gp, ENXIO); | |
402 | 379 |
403 return (err); | 380 gv_save_config(sc); |
404} | 381} |