[BACK]Return to resizedisk.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / gpt

Annotation of src/sbin/gpt/resizedisk.c, Revision 1.6.2.2

1.6.2.2 ! snj         1: /*-
        !             2:  * Copyright (c) 2002 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:  *
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            17:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            18:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            19:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            20:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            21:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            22:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            23:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            24:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            25:  */
        !            26:
        !            27: #if HAVE_NBTOOL_CONFIG_H
        !            28: #include "nbtool_config.h"
        !            29: #endif
        !            30:
        !            31: #include <sys/cdefs.h>
        !            32: #ifdef __FBSDID
        !            33: __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
        !            34: #endif
        !            35: #ifdef __RCSID
        !            36: __RCSID("$NetBSD: resizedisk.c,v 1.1 2014/09/23 07:47:54 jnemeth Exp $");
        !            37: #endif
        !            38:
        !            39: #include <sys/bootblock.h>
        !            40: #include <sys/types.h>
        !            41:
        !            42: #include <err.h>
        !            43: #include <stddef.h>
        !            44: #include <stdio.h>
        !            45: #include <stdlib.h>
        !            46: #include <string.h>
        !            47: #include <unistd.h>
        !            48:
        !            49: #include "map.h"
        !            50: #include "gpt.h"
        !            51:
        !            52: static uint64_t sector, size;
        !            53:
        !            54: const char resizediskmsg[] = "resizedisk [-s size] device ...";
        !            55:
        !            56: __dead static void
        !            57: usage_resizedisk(void)
        !            58: {
        !            59:
        !            60:        fprintf(stderr,
        !            61:            "usage: %s %s\n", getprogname(), resizediskmsg);
        !            62:        exit(1);
        !            63: }
        !            64:
        !            65: /*
        !            66:  * relocate the secondary GPT based on the following criteria:
        !            67:  * - size not specified
        !            68:  *   - disk has not changed size, do nothing
        !            69:  *   - disk has grown, relocate secondary
        !            70:  *   - disk has shrunk, create new secondary
        !            71:  * - size specified
        !            72:  *   - size is larger then disk or same as current location, do nothing
        !            73:  *   - relocate or create new secondary
        !            74:  * - when shrinking, verify that table fits
        !            75:  */
        !            76: static void
        !            77: resizedisk(int fd)
        !            78: {
        !            79:        map_t *gpt, *tpg;
        !            80:        map_t *tbl, *lbt;
        !            81:        map_t *mbrmap;
        !            82:        struct gpt_hdr *hdr;
        !            83:        struct gpt_ent *ent;
        !            84:        struct mbr *mbr;
        !            85:        uint64_t last, oldloc, newloc, lastdata, gpt_size;
        !            86:        int i;
        !            87:
        !            88:        last = mediasz / secsz - 1;
        !            89:        lastdata = 0;
        !            90:        newloc = 0;
        !            91:
        !            92:        if (sector > last) {
        !            93:                warnx("%s: specified size is larger then the disk",
        !            94:                    device_name);
        !            95:                return;
        !            96:        }
        !            97:
        !            98:         mbrmap = map_find(MAP_TYPE_PMBR);
        !            99:         if (mbrmap == NULL || mbrmap->map_start != 0) {
        !           100:                 warnx("%s: error: no valid Protective MBR found", device_name);
        !           101:                 return;
        !           102:         }
        !           103:         mbr = mbrmap->map_data;
        !           104:
        !           105:        gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
        !           106:        ent = NULL;
        !           107:        if (gpt == NULL) {
        !           108:                warnx("%s: error: no primary GPT header; run create or recover",
        !           109:                    device_name);
        !           110:                return;
        !           111:        }
        !           112:        hdr = gpt->map_data;
        !           113:        oldloc = le64toh(hdr->hdr_lba_alt);
        !           114:
        !           115:        tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
        !           116:        if (tpg == NULL)
        !           117:                if (gpt_gpt(fd, oldloc, 1))
        !           118:                        tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
        !           119:
        !           120:        tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
        !           121:        lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
        !           122:        if (tbl == NULL) {
        !           123:                warnx("%s: error: run recover -- trust me", device_name);
        !           124:                return;
        !           125:        }
        !           126:
        !           127:        gpt_size = tbl->map_size;
        !           128:        if (sector == oldloc) {
        !           129:                warnx("%s: device is already the specified size", device_name);
        !           130:                return;
        !           131:        }
        !           132:        if (sector == 0 && last == oldloc) {
        !           133:                warnx("%s: device hasn't changed size", device_name);
        !           134:                return;
        !           135:        }
        !           136:
        !           137:        for (ent = tbl->map_data; ent <
        !           138:            (struct gpt_ent *)((char *)tbl->map_data +
        !           139:            le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)); ent++) {
        !           140:                if (!gpt_uuid_is_nil(ent->ent_type) &&
        !           141:                    (le64toh(ent->ent_lba_end) > lastdata)) {
        !           142:                        lastdata = le64toh(ent->ent_lba_end);
        !           143:                }
        !           144:        }
        !           145:        if (sector - gpt_size <= lastdata) {
        !           146:                warnx("%s: not enough space at %" PRIu64
        !           147:                    " for secondary GPT table", device_name, sector);
        !           148:                return;
        !           149:        }
        !           150:        if (last - gpt_size <= lastdata) {
        !           151:                warnx("%s: not enough space for new secondary GPT table",
        !           152:                    device_name);
        !           153:                return;
        !           154:        }
        !           155:
        !           156:        if (sector > oldloc)
        !           157:                newloc = sector;
        !           158:        if (sector > 0 && sector < oldloc && last >= oldloc)
        !           159:                newloc = sector;
        !           160:        if (sector == 0 && last > oldloc)
        !           161:                newloc = last;
        !           162:        if (newloc > 0) {
        !           163:                if (tpg == NULL) {
        !           164:                        warnx("%s: error: no secondary GPT header; run recover",
        !           165:                            device_name);
        !           166:                        return;
        !           167:                }
        !           168:                if (lbt == NULL) {
        !           169:                        warnx("%s: error: run recover -- trust me",
        !           170:                            device_name);
        !           171:                        return;
        !           172:                }
        !           173:                tpg->map_start = newloc;
        !           174:                lbt->map_start = newloc - gpt_size;
        !           175:        } else {
        !           176:                if (sector > 0)
        !           177:                        newloc = sector;
        !           178:                else
        !           179:                        newloc = last;
        !           180:                tpg = map_add(newloc, 1LL, MAP_TYPE_SEC_GPT_HDR,
        !           181:                    calloc(1, secsz));
        !           182:                lbt = map_add(newloc - gpt_size, gpt_size, MAP_TYPE_SEC_GPT_TBL,
        !           183:                    tbl->map_data);
        !           184:                memcpy(tpg->map_data, gpt->map_data, secsz);
        !           185:        }
        !           186:
        !           187:        hdr = gpt->map_data;
        !           188:        hdr->hdr_lba_alt = tpg->map_start;
        !           189:        hdr->hdr_crc_self = 0;
        !           190:        hdr->hdr_lba_end = htole64(lbt->map_start - 1);
        !           191:        hdr->hdr_crc_self =
        !           192:            htole32(crc32(gpt->map_data, GPT_HDR_SIZE));
        !           193:        gpt_write(fd, gpt);
        !           194:
        !           195:        hdr = tpg->map_data;
        !           196:        hdr->hdr_lba_self = htole64(tpg->map_start);
        !           197:        hdr->hdr_lba_alt = htole64(gpt->map_start);
        !           198:        hdr->hdr_lba_end = htole64(lbt->map_start - 1);
        !           199:        hdr->hdr_lba_table = htole64(lbt->map_start);
        !           200:        hdr->hdr_crc_self = 0;
        !           201:        hdr->hdr_crc_self =
        !           202:            htole32(crc32(tpg->map_data, GPT_HDR_SIZE));
        !           203:        gpt_write(fd, lbt);
        !           204:        gpt_write(fd, tpg);
        !           205:
        !           206:        for (i = 0; i < 4; i++)
        !           207:                if (mbr->mbr_part[0].part_typ == MBR_PTYPE_PMBR)
        !           208:                        break;
        !           209:        if (i == 4) {
        !           210:                warnx("%s: no valid PMBR partition found", device_name);
        !           211:                return;
        !           212:        }
        !           213:        if (last > 0xffffffff) {
        !           214:                mbr->mbr_part[0].part_size_lo = htole16(0xffff);
        !           215:                mbr->mbr_part[0].part_size_hi = htole16(0xffff);
        !           216:        } else {
        !           217:                mbr->mbr_part[0].part_size_lo = htole16(last);
        !           218:                mbr->mbr_part[0].part_size_hi = htole16(last >> 16);
        !           219:        }
        !           220:        gpt_write(fd, mbrmap);
        !           221:
        !           222:        return;
        !           223: }
        !           224:
        !           225: int
        !           226: cmd_resizedisk(int argc, char *argv[])
        !           227: {
        !           228:        char *p;
        !           229:        int ch, fd;
        !           230:        int64_t human_num;
        !           231:
        !           232:        while ((ch = getopt(argc, argv, "s:")) != -1) {
        !           233:                switch(ch) {
        !           234:                case 's':
        !           235:                        if (sector > 0 || size > 0)
        !           236:                                usage_resizedisk();
        !           237:                        sector = strtoll(optarg, &p, 10);
        !           238:                        if (sector < 1)
        !           239:                                usage_resizedisk();
        !           240:                        if (*p == '\0')
        !           241:                                break;
        !           242:                        if (*p == 's' || *p == 'S') {
        !           243:                                if (*(p + 1) == '\0')
        !           244:                                        break;
        !           245:                                else
        !           246:                                        usage_resizedisk();
        !           247:                        }
        !           248:                        if (*p == 'b' || *p == 'B') {
        !           249:                                if (*(p + 1) == '\0') {
        !           250:                                        size = sector;
        !           251:                                        sector = 0;
        !           252:                                        break;
        !           253:                                } else
        !           254:                                        usage_resizedisk();
        !           255:                        }
        !           256:                        if (dehumanize_number(optarg, &human_num) < 0)
        !           257:                                usage_resizedisk();
        !           258:                        size = human_num;
        !           259:                        sector = 0;
        !           260:                        break;
        !           261:                default:
        !           262:                        usage_resizedisk();
        !           263:                }
        !           264:        }
        !           265:
        !           266:        if (argc == optind)
        !           267:                usage_resizedisk();
        !           268:
        !           269:        while (optind < argc) {
        !           270:                fd = gpt_open(argv[optind++]);
        !           271:                if (fd == -1) {
        !           272:                        warn("unable to open device '%s'", device_name);
        !           273:                        continue;
        !           274:                }
        !           275:
        !           276:                if (size % secsz != 0) {
        !           277:                        warnx("Size in bytes must be a multiple of sector "
        !           278:                              "size;");
        !           279:                        warnx("the sector size for %s is %d bytes.",
        !           280:                            device_name, secsz);
        !           281:                        continue;
        !           282:                }
        !           283:                if (size > 0)
        !           284:                        sector = size / secsz - 1;
        !           285:
        !           286:                resizedisk(fd);
        !           287:
        !           288:                gpt_close(fd);
        !           289:        }
        !           290:
        !           291:        return 0;
        !           292: }

CVSweb <webmaster@jp.NetBSD.org>