Deleted Added
sdiff udiff text old ( 139778 ) new ( 185309 )
full compact
1/*-
2 * Copyright (c) 2004 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
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
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_list.c 139778 2005-01-06 18:27:30Z imp $");
30
31#include <sys/param.h>
32#include <sys/libkern.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>
38#include <geom/vinum/geom_vinum_share.h>
39
40void gv_lvi(struct gv_volume *, struct sbuf *, int);
41void gv_lpi(struct gv_plex *, struct sbuf *, int);
42void gv_lsi(struct gv_sd *, struct sbuf *, int);
43void gv_ldi(struct gv_drive *, struct sbuf *, int);
44
45void
46gv_list(struct g_geom *gp, struct gctl_req *req)
47{
48 struct gv_softc *sc;
49 struct gv_drive *d;
50 struct gv_plex *p;
51 struct gv_sd *s;
52 struct gv_volume *v;
53 struct sbuf *sb;
54 int *argc, i, *flags, type;
55 char *arg, buf[20], *cmd;
56
57 argc = gctl_get_paraml(req, "argc", sizeof(*argc));
58
59 if (argc == NULL) {
60 gctl_error(req, "no arguments given");
61 return;
62 }
63
64 flags = gctl_get_paraml(req, "flags", sizeof(*flags));
65
66 sc = gp->softc;
67
68 sb = sbuf_new(NULL, NULL, GV_CFG_LEN, SBUF_FIXEDLEN);
69
70 /* Figure out which command was given. */
71 cmd = gctl_get_param(req, "cmd", NULL);
72
73 /* List specific objects or everything. */
74 if (!strcmp(cmd, "list") || !strcmp(cmd, "l")) {
75 if (*argc) {
76 for (i = 0; i < *argc; i++) {
77 snprintf(buf, sizeof(buf), "argv%d", i);
78 arg = gctl_get_param(req, buf, NULL);
79 if (arg == NULL)
80 continue;
81 type = gv_object_type(sc, arg);
82 switch (type) {
83 case GV_TYPE_VOL:
84 v = gv_find_vol(sc, arg);
85 gv_lvi(v, sb, *flags);
86 break;
87 case GV_TYPE_PLEX:
88 p = gv_find_plex(sc, arg);
89 gv_lpi(p, sb, *flags);
90 break;
91 case GV_TYPE_SD:
92 s = gv_find_sd(sc, arg);
93 gv_lsi(s, sb, *flags);
94 break;
95 case GV_TYPE_DRIVE:
96 d = gv_find_drive(sc, arg);
97 gv_ldi(d, sb, *flags);
98 break;
99 default:
100 gctl_error(req, "unknown object '%s'",
101 arg);
102 break;
103 }
104 }
105 } else {
106 gv_ld(gp, req, sb);
107 sbuf_printf(sb, "\n");
108 gv_lv(gp, req, sb);
109 sbuf_printf(sb, "\n");
110 gv_lp(gp, req, sb);
111 sbuf_printf(sb, "\n");
112 gv_ls(gp, req, sb);
113 }
114
115 /* List drives. */
116 } else if (!strcmp(cmd, "ld")) {
117 if (*argc) {
118 for (i = 0; i < *argc; i++) {
119 snprintf(buf, sizeof(buf), "argv%d", i);
120 arg = gctl_get_param(req, buf, NULL);
121 if (arg == NULL)
122 continue;
123 type = gv_object_type(sc, arg);
124 if (type != GV_TYPE_DRIVE) {
125 gctl_error(req, "'%s' is not a drive",
126 arg);
127 continue;
128 } else {
129 d = gv_find_drive(sc, arg);
130 gv_ldi(d, sb, *flags);
131 }
132 }
133 } else
134 gv_ld(gp, req, sb);
135
136 /* List volumes. */
137 } else if (!strcmp(cmd, "lv")) {
138 if (*argc) {
139 for (i = 0; i < *argc; i++) {
140 snprintf(buf, sizeof(buf), "argv%d", i);
141 arg = gctl_get_param(req, buf, NULL);
142 if (arg == NULL)
143 continue;
144 type = gv_object_type(sc, arg);
145 if (type != GV_TYPE_VOL) {
146 gctl_error(req, "'%s' is not a volume",
147 arg);
148 continue;
149 } else {
150 v = gv_find_vol(sc, arg);
151 gv_lvi(v, sb, *flags);
152 }
153 }
154 } else
155 gv_lv(gp, req, sb);
156
157 /* List plexes. */
158 } else if (!strcmp(cmd, "lp")) {
159 if (*argc) {
160 for (i = 0; i < *argc; i++) {
161 snprintf(buf, sizeof(buf), "argv%d", i);
162 arg = gctl_get_param(req, buf, NULL);
163 if (arg == NULL)
164 continue;
165 type = gv_object_type(sc, arg);
166 if (type != GV_TYPE_PLEX) {
167 gctl_error(req, "'%s' is not a plex",
168 arg);
169 continue;
170 } else {
171 p = gv_find_plex(sc, arg);
172 gv_lpi(p, sb, *flags);
173 }
174 }
175 } else
176 gv_lp(gp, req, sb);
177
178 /* List subdisks. */
179 } else if (!strcmp(cmd, "ls")) {
180 if (*argc) {
181 for (i = 0; i < *argc; i++) {
182 snprintf(buf, sizeof(buf), "argv%d", i);
183 arg = gctl_get_param(req, buf, NULL);
184 if (arg == NULL)
185 continue;
186 type = gv_object_type(sc, arg);
187 if (type != GV_TYPE_SD) {
188 gctl_error(req, "'%s' is not a subdisk",
189 arg);
190 continue;
191 } else {
192 s = gv_find_sd(sc, arg);
193 gv_lsi(s, sb, *flags);
194 }
195 }
196 } else
197 gv_ls(gp, req, sb);
198
199 } else
200 gctl_error(req, "unknown command '%s'", cmd);
201
202 sbuf_finish(sb);
203 gctl_set_param(req, "config", sbuf_data(sb), sbuf_len(sb) + 1);
204 sbuf_delete(sb);
205}
206
207/* List one or more volumes. */
208void
209gv_lv(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
210{
211 struct gv_softc *sc;
212 struct gv_volume *v;
213 int i, *flags;
214
215 sc = gp->softc;
216 i = 0;
217
218 LIST_FOREACH(v, &sc->volumes, volume)
219 i++;
220
221 sbuf_printf(sb, "%d volume%s:\n", i, i == 1 ? "" : "s");
222
223 if (i) {
224 flags = gctl_get_paraml(req, "flags", sizeof(*flags));
225 LIST_FOREACH(v, &sc->volumes, volume)
226 gv_lvi(v, sb, *flags);
227 }
228}
229
230/* List a single volume. */
231void
232gv_lvi(struct gv_volume *v, struct sbuf *sb, int flags)
233{
234 struct gv_plex *p;
235 int i;
236
237 if (flags & GV_FLAG_V) {
238 sbuf_printf(sb, "Volume %s:\tSize: %jd bytes (%jd MB)\n",
239 v->name, (intmax_t)v->size, (intmax_t)v->size / MEGABYTE);
240 sbuf_printf(sb, "\t\tState: %s\n", gv_volstate(v->state));
241 } else {
242 sbuf_printf(sb, "V %-21s State: %s\tPlexes: %7d\tSize: %s\n",
243 v->name, gv_volstate(v->state), v->plexcount,
244 gv_roughlength(v->size, 0));
245 }
246
247 if (flags & GV_FLAG_VV) {
248 i = 0;
249 LIST_FOREACH(p, &v->plexes, in_volume) {
250 sbuf_printf(sb, "\t\tPlex %2d:\t%s\t(%s), %s\n", i,
251 p->name, gv_plexstate(p->state),
252 gv_roughlength(p->size, 0));
253 i++;
254 }
255 }
256
257 if (flags & GV_FLAG_R) {
258 LIST_FOREACH(p, &v->plexes, in_volume)
259 gv_lpi(p, sb, flags);
260 }
261}
262
263/* List one or more plexes. */
264void
265gv_lp(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
266{
267 struct gv_softc *sc;
268 struct gv_plex *p;
269 int i, *flags;
270
271 sc = gp->softc;
272 i = 0;
273
274 LIST_FOREACH(p, &sc->plexes, plex)
275 i++;
276
277 sbuf_printf(sb, "%d plex%s:\n", i, i == 1 ? "" : "es");
278
279 if (i) {
280 flags = gctl_get_paraml(req, "flags", sizeof(*flags));
281 LIST_FOREACH(p, &sc->plexes, plex)
282 gv_lpi(p, sb, *flags);
283 }
284}
285
286/* List a single plex. */
287void
288gv_lpi(struct gv_plex *p, struct sbuf *sb, int flags)
289{
290 struct gv_sd *s;
291 int i;
292
293 if (flags & GV_FLAG_V) {
294 sbuf_printf(sb, "Plex %s:\tSize:\t%9jd bytes (%jd MB)\n",
295 p->name, (intmax_t)p->size, (intmax_t)p->size / MEGABYTE);
296 sbuf_printf(sb, "\t\tSubdisks: %8d\n", p->sdcount);
297 sbuf_printf(sb, "\t\tState: %s\n\t\tOrganization: %s",
298 gv_plexstate(p->state), gv_plexorg(p->org));
299 if (gv_is_striped(p)) {
300 sbuf_printf(sb, "\tStripe size: %s\n",
301 gv_roughlength(p->stripesize, 1));
302 }
303 if (p->vol_sc != NULL) {
304 sbuf_printf(sb, "\t\tPart of volume %s\n", p->volume);
305 }
306 } else {
307 sbuf_printf(sb, "P %-18s %2s State: %s\tSubdisks: %5d"
308 "\tSize: %s\n", p->name, gv_plexorg_short(p->org),
309 gv_plexstate(p->state), p->sdcount,
310 gv_roughlength(p->size, 0));
311 }
312
313 if (flags & GV_FLAG_VV) {
314 i = 0;
315 LIST_FOREACH(s, &p->subdisks, in_plex) {
316 sbuf_printf(sb, "\t\tSubdisk %d:\t%s\n", i, s->name);
317 sbuf_printf(sb, "\t\t state: %s\tsize %11jd "
318 "(%jd MB)\n", gv_sdstate(s->state),
319 (intmax_t)s->size, (intmax_t)s->size / MEGABYTE);
320 if (p->org == GV_PLEX_CONCAT) {
321 sbuf_printf(sb, "\t\t\toffset %9jd (0x%jx)\n",
322 (intmax_t)s->plex_offset,
323 (intmax_t)s->plex_offset);
324 }
325 i++;
326 }
327 }
328
329 if (flags & GV_FLAG_R) {
330 LIST_FOREACH(s, &p->subdisks, in_plex)
331 gv_lsi(s, sb, flags);
332 }
333}
334
335/* List one or more subdisks. */
336void
337gv_ls(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
338{
339 struct gv_softc *sc;
340 struct gv_sd *s;
341 int i, *flags;
342
343 sc = gp->softc;
344 i = 0;
345
346 LIST_FOREACH(s, &sc->subdisks, sd)
347 i++;
348
349 sbuf_printf(sb, "%d subdisk%s:\n", i, i == 1 ? "" : "s");
350
351 if (i) {
352 flags = gctl_get_paraml(req, "flags", sizeof(*flags));
353 LIST_FOREACH(s, &sc->subdisks, sd)
354 gv_lsi(s, sb, *flags);
355 }
356}
357
358/* List a single subdisk. */
359void
360gv_lsi(struct gv_sd *s, struct sbuf *sb, int flags)
361{
362 if (flags & GV_FLAG_V) {
363 sbuf_printf(sb, "Subdisk %s:\n", s->name);
364 sbuf_printf(sb, "\t\tSize: %16jd bytes (%jd MB)\n",
365 (intmax_t)s->size, (intmax_t)s->size / MEGABYTE);
366 sbuf_printf(sb, "\t\tState: %s\n", gv_sdstate(s->state));
367
368 if (s->state == GV_SD_INITIALIZING ||
369 s->state == GV_SD_REVIVING) {
370 if (s->state == GV_SD_INITIALIZING)
371 sbuf_printf(sb, "\t\tInitialized: ");
372 else
373 sbuf_printf(sb, "\t\tRevived: ");
374
375 sbuf_printf(sb, "%16jd bytes (%d%%)\n",
376 (intmax_t)s->initialized,
377 (int)((s->initialized * 100) / s->size));
378 }
379
380 if (s->plex_sc != NULL) {
381 sbuf_printf(sb, "\t\tPlex %s at offset %jd (%s)\n",
382 s->plex, (intmax_t)s->plex_offset,
383 gv_roughlength(s->plex_offset, 1));
384 }
385
386 sbuf_printf(sb, "\t\tDrive %s (%s) at offset %jd (%s)\n",
387 s->drive,
388 s->drive_sc == NULL ? "*missing*" : s->drive_sc->name,
389 (intmax_t)s->drive_offset,
390 gv_roughlength(s->drive_offset, 1));
391 } else {
392 sbuf_printf(sb, "S %-21s State: ", s->name);
393 if (s->state == GV_SD_INITIALIZING ||
394 s->state == GV_SD_REVIVING) {
395 if (s->state == GV_SD_INITIALIZING)
396 sbuf_printf(sb, "I ");
397 else
398 sbuf_printf(sb, "R ");
399 sbuf_printf(sb, "%d%%\t",
400 (int)((s->initialized * 100) / s->size));
401 } else {
402 sbuf_printf(sb, "%s\t", gv_sdstate(s->state));
403 }
404 sbuf_printf(sb, "D: %-12s Size: %s\n", s->drive,
405 gv_roughlength(s->size, 0));
406 }
407}
408
409/* List one or more drives. */
410void
411gv_ld(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
412{
413 struct gv_softc *sc;
414 struct gv_drive *d;
415 int i, *flags;
416
417 sc = gp->softc;
418 i = 0;
419
420 LIST_FOREACH(d, &sc->drives, drive)
421 i++;
422
423 sbuf_printf(sb, "%d drive%s:\n", i, i == 1 ? "" : "s");
424
425 if (i) {
426 flags = gctl_get_paraml(req, "flags", sizeof(*flags));
427 LIST_FOREACH(d, &sc->drives, drive)
428 gv_ldi(d, sb, *flags);
429 }
430}
431
432/* List a single drive. */
433void
434gv_ldi(struct gv_drive *d, struct sbuf *sb, int flags)
435{
436 struct gv_freelist *fl;
437 struct gv_sd *s;
438
439 /* Verbose listing. */
440 if (flags & GV_FLAG_V) {
441 sbuf_printf(sb, "Drive %s:\tDevice %s\n", d->name, d->device);
442 sbuf_printf(sb, "\t\tSize: %16jd bytes (%jd MB)\n",
443 (intmax_t)d->size, (intmax_t)d->size / MEGABYTE);
444 sbuf_printf(sb, "\t\tUsed: %16jd bytes (%jd MB)\n",
445 (intmax_t)d->size - d->avail,
446 (intmax_t)(d->size - d->avail) / MEGABYTE);
447 sbuf_printf(sb, "\t\tAvailable: %11jd bytes (%jd MB)\n",
448 (intmax_t)d->avail, (intmax_t)d->avail / MEGABYTE);
449 sbuf_printf(sb, "\t\tState: %s\n", gv_drivestate(d->state));
450
451 /* Be very verbose. */
452 if (flags & GV_FLAG_VV) {
453 sbuf_printf(sb, "\t\tFree list contains %d entries:\n",
454 d->freelist_entries);
455 sbuf_printf(sb, "\t\t Offset\t Size\n");
456 LIST_FOREACH(fl, &d->freelist, freelist)
457 sbuf_printf(sb, "\t\t%9jd\t%9jd\n",
458 (intmax_t)fl->offset, (intmax_t)fl->size);
459 }
460 } else {
461 sbuf_printf(sb, "D %-21s State: %s\t/dev/%s\tA: %jd/%jd MB "
462 "(%d%%)\n", d->name, gv_drivestate(d->state), d->device,
463 (intmax_t)d->avail / MEGABYTE, (intmax_t)d->size / MEGABYTE,
464 (int)((d->avail * 100) / d->size));
465 }
466
467 /* Recursive listing. */
468 if (flags & GV_FLAG_R) {
469 LIST_FOREACH(s, &d->subdisks, from_drive)
470 gv_lsi(s, sb, flags);
471 }
472}