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