geom_part.c revision 173313
1/*- 2 * Copyright (c) 2007 Marcel Moolenaar 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 THE AUTHORS 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 THE AUTHORS 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#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sbin/geom/class/part/geom_part.c 173313 2007-11-04 00:32:54Z marcel $"); 29 30#include <stdio.h> 31#include <stdint.h> 32#include <stdlib.h> 33#include <unistd.h> 34#include <err.h> 35#include <fcntl.h> 36#include <string.h> 37#include <strings.h> 38#include <libgeom.h> 39#include <paths.h> 40#include <errno.h> 41#include <assert.h> 42 43#include "core/geom.h" 44#include "misc/subr.h" 45 46#ifdef RESCUE 47#define PUBSYM(x) gpart_##x 48#else 49#define PUBSYM(x) x 50#endif 51 52uint32_t PUBSYM(lib_version) = G_LIB_VERSION; 53uint32_t PUBSYM(version) = 0; 54 55static char optional[] = ""; 56static char flags[] = "C"; 57 58static void gpart_show(struct gctl_req *, unsigned); 59 60struct g_command PUBSYM(class_commands)[] = { 61 { "add", 0, NULL, { 62 { 'b', "start", NULL, G_TYPE_STRING }, 63 { 's', "size", NULL, G_TYPE_STRING }, 64 { 't', "type", NULL, G_TYPE_STRING }, 65 { 'i', "index", optional, G_TYPE_STRING }, 66 { 'l', "label", optional, G_TYPE_STRING }, 67 { 'f', "flags", flags, G_TYPE_STRING }, 68 G_OPT_SENTINEL }, 69 "geom", NULL, 70 }, 71 { "commit", 0, NULL, G_NULL_OPTS, "geom", NULL }, 72 { "create", 0, NULL, { 73 { 's', "scheme", NULL, G_TYPE_STRING }, 74 { 'n', "entries", optional, G_TYPE_STRING }, 75 { 'f', "flags", flags, G_TYPE_STRING }, 76 G_OPT_SENTINEL }, 77 "provider", NULL 78 }, 79 { "delete", 0, NULL, { 80 { 'i', "index", NULL, G_TYPE_STRING }, 81 { 'f', "flags", flags, G_TYPE_STRING }, 82 G_OPT_SENTINEL }, 83 "geom", NULL 84 }, 85 { "destroy", 0, NULL, { 86 { 'f', "flags", flags, G_TYPE_STRING }, 87 G_OPT_SENTINEL }, 88 "geom", NULL }, 89 { "modify", 0, NULL, { 90 { 'i', "index", NULL, G_TYPE_STRING }, 91 { 'l', "label", optional, G_TYPE_STRING }, 92 { 't', "type", optional, G_TYPE_STRING }, 93 { 'f', "flags", flags, G_TYPE_STRING }, 94 G_OPT_SENTINEL }, 95 "geom", NULL 96 }, 97 { "show", 0, gpart_show, G_NULL_OPTS, NULL, "[geom ...]" }, 98 { "undo", 0, NULL, G_NULL_OPTS, "geom", NULL }, 99 G_CMD_SENTINEL 100}; 101 102static struct gclass * 103find_class(struct gmesh *mesh, const char *name) 104{ 105 struct gclass *classp; 106 107 LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 108 if (strcmp(classp->lg_name, name) == 0) 109 return (classp); 110 } 111 return (NULL); 112} 113 114static struct ggeom * 115find_geom(struct gclass *classp, const char *name) 116{ 117 struct ggeom *gp; 118 119 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 120 if (strcmp(gp->lg_name, name) == 0) 121 return (gp); 122 } 123 return (NULL); 124} 125 126static const char * 127find_geomcfg(struct ggeom *gp, const char *cfg) 128{ 129 struct gconfig *gc; 130 131 LIST_FOREACH(gc, &gp->lg_config, lg_config) { 132 if (!strcmp(gc->lg_name, cfg)) 133 return (gc->lg_val); 134 } 135 return (NULL); 136} 137 138static const char * 139find_provcfg(struct gprovider *pp, const char *cfg) 140{ 141 struct gconfig *gc; 142 143 LIST_FOREACH(gc, &pp->lg_config, lg_config) { 144 if (!strcmp(gc->lg_name, cfg)) 145 return (gc->lg_val); 146 } 147 return (NULL); 148} 149 150static struct gprovider * 151find_provider(struct ggeom *gp, unsigned long long minsector) 152{ 153 struct gprovider *pp, *bestpp; 154 unsigned long long offset; 155 unsigned long long sector, bestsector; 156 157 bestpp = NULL; 158 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 159 offset = atoll(find_provcfg(pp, "offset")); 160 sector = offset / pp->lg_sectorsize; 161 if (sector < minsector) 162 continue; 163 if (bestpp != NULL && sector >= bestsector) 164 continue; 165 bestpp = pp; 166 bestsector = sector; 167 } 168 return (bestpp); 169} 170 171static const char * 172fmtsize(long double rawsz) 173{ 174 static char buf[32]; 175 static const char *sfx[] = { "B", "KB", "MB", "GB", "TB" }; 176 long double sz; 177 int sfxidx; 178 179 sfxidx = 0; 180 sz = (long double)rawsz; 181 while (sfxidx < 4 && sz > 1099.0) { 182 sz /= 1000; 183 sfxidx++; 184 } 185 186 sprintf(buf, "%.1Lf%s", sz, sfx[sfxidx]); 187 return (buf); 188} 189 190static void 191gpart_show_geom(struct ggeom *gp) 192{ 193 struct gprovider *pp; 194 const char *s, *scheme; 195 unsigned long long first, last, sector, end; 196 unsigned long long offset, length, secsz; 197 int idx, wblocks, wname; 198 199 scheme = find_geomcfg(gp, "scheme"); 200 s = find_geomcfg(gp, "first"); 201 first = atoll(s); 202 s = find_geomcfg(gp, "last"); 203 last = atoll(s); 204 wblocks = strlen(s); 205 wname = strlen(gp->lg_name); 206 pp = LIST_FIRST(&gp->lg_consumer)->lg_provider; 207 secsz = pp->lg_sectorsize; 208 printf("=>%*llu %*llu %*s %s (%s)\n", 209 wblocks, first, wblocks, (last - first + 1), 210 wname, gp->lg_name, 211 scheme, fmtsize(pp->lg_mediasize)); 212 213 while ((pp = find_provider(gp, first)) != NULL) { 214 s = find_provcfg(pp, "offset"); 215 offset = atoll(s); 216 sector = offset / secsz; 217 s = find_provcfg(pp, "length"); 218 length = atoll(s); 219 s = find_provcfg(pp, "index"); 220 idx = atoi(s); 221 end = sector + length / secsz; 222 if (first < sector) { 223 printf(" %*llu %*llu %*s - free - (%s)\n", 224 wblocks, first, wblocks, sector - first, 225 wname, "", 226 fmtsize((sector - first) * secsz)); 227 } 228 printf(" %*llu %*llu %*d %s (%s)\n", 229 wblocks, sector, wblocks, end - sector, 230 wname, idx, 231 find_provcfg(pp, "type"), fmtsize(pp->lg_mediasize)); 232 first = end; 233 } 234 if (first <= last) { 235 printf(" %*llu %*llu %*s - free - (%s)\n", 236 wblocks, first, wblocks, last - first + 1, 237 wname, "", 238 fmtsize((last - first + 1) * secsz)); 239 } 240 printf("\n"); 241} 242 243static void 244gpart_show(struct gctl_req *req, unsigned fl __unused) 245{ 246 struct gmesh mesh; 247 struct gclass *classp; 248 struct ggeom *gp; 249 const char *name; 250 int error, i, nargs; 251 252 name = gctl_get_ascii(req, "class"); 253 if (name == NULL) 254 abort(); 255 error = geom_gettree(&mesh); 256 if (error != 0) 257 errc(EXIT_FAILURE, error, "Cannot get GEOM tree"); 258 classp = find_class(&mesh, name); 259 if (classp == NULL) { 260 geom_deletetree(&mesh); 261 errx(EXIT_FAILURE, "Class %s not found.", name); 262 } 263 nargs = gctl_get_int(req, "nargs"); 264 if (nargs > 0) { 265 for (i = 0; i < nargs; i++) { 266 name = gctl_get_ascii(req, "arg%d", i); 267 gp = find_geom(classp, name); 268 if (gp != NULL) 269 gpart_show_geom(gp); 270 else 271 errx(EXIT_FAILURE, "No such geom: %s.", name); 272 } 273 } else { 274 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 275 gpart_show_geom(gp); 276 } 277 } 278 geom_deletetree(&mesh); 279} 280