Submit #3276 ยป expand.patch
sbin/gpt/expand.c | ||
---|---|---|
#include "map.h"
|
||
#include "gpt.h"
|
||
static void expand(int fd);
|
||
static void expand(int fd, int expand_last);
|
||
static void
|
||
usage_expand(void)
|
||
{
|
||
fprintf(stderr, "usage: %s expand [-x] <device>...\n", getprogname());
|
||
exit(1);
|
||
}
|
||
int
|
||
cmd_expand(int argc, char *argv[])
|
||
{
|
||
int fd;
|
||
if (argc == optind) {
|
||
fprintf(stderr, "usage: gpt expand <device>...\n");
|
||
exit(1);
|
||
int ch;
|
||
int expand_last = 0;
|
||
while ((ch = getopt(argc, argv, "x")) != -1) {
|
||
switch(ch) {
|
||
case 'x':
|
||
expand_last = 1;
|
||
break;
|
||
default:
|
||
usage_expand();
|
||
}
|
||
}
|
||
if (argc == optind)
|
||
usage_expand();
|
||
while (optind < argc) {
|
||
fd = gpt_open(argv[optind++]);
|
||
if (fd == -1) {
|
||
... | ... | |
continue;
|
||
}
|
||
expand(fd);
|
||
expand(fd, expand_last);
|
||
gpt_close(fd);
|
||
}
|
||
... | ... | |
}
|
||
static void
|
||
expand(int fd __unused)
|
||
expand_last_to_fill(struct gpt_hdr *hdr, map_t *tbl, off_t last, off_t blocks)
|
||
{
|
||
struct gpt_ent *ent;
|
||
struct gpt_ent *lent = NULL;
|
||
u_int i;
|
||
u_int li;
|
||
off_t nblocks;
|
||
char *name = NULL;
|
||
li = 0;
|
||
for (i = 0; i < le32toh(hdr->hdr_entries); ++i) {
|
||
ent = (void *)((char *)tbl->map_data + i *
|
||
le32toh(hdr->hdr_entsz));
|
||
if (uuid_is_nil(&ent->ent_type, NULL))
|
||
continue;
|
||
lent = ent;
|
||
li = i;
|
||
}
|
||
if (lent) {
|
||
uuid_to_string(&ent->ent_type, &name, NULL);
|
||
nblocks = last - blocks - le64toh(lent->ent_lba_start);
|
||
nblocks = (nblocks * secsz / (1024 * 1024)) * 1024 * 1024 /
|
||
secsz;
|
||
if (le64toh(lent->ent_lba_end) ==
|
||
le64toh(lent->ent_lba_start) + nblocks - 1) {
|
||
printf("entry %d type=%s %ld,%ld unchanged\n",
|
||
li, name,
|
||
le64toh(lent->ent_lba_start),
|
||
le64toh(lent->ent_lba_end));
|
||
} else {
|
||
printf("expand entry %d type=%s %ld,%ld to %ld\n",
|
||
li, name,
|
||
le64toh(lent->ent_lba_start),
|
||
le64toh(lent->ent_lba_end),
|
||
le64toh(lent->ent_lba_start) + nblocks - 1);
|
||
lent->ent_lba_end = htole64(
|
||
le64toh(lent->ent_lba_start) +
|
||
nblocks - 1);
|
||
}
|
||
if (name != NULL) {
|
||
free(name);
|
||
name = NULL;
|
||
}
|
||
}
|
||
}
|
||
static void
|
||
expand(int fd __unused, int expand_last)
|
||
{
|
||
map_t *pmbr;
|
||
map_t *gpt, *gpt2;
|
||
... | ... | |
off_t last;
|
||
off_t blocks;
|
||
off_t delta;
|
||
off_t nblocks;
|
||
struct gpt_hdr *hdr;
|
||
struct gpt_ent *ent;
|
||
struct gpt_ent *lent;
|
||
char *name = NULL;
|
||
u_int i;
|
||
u_int li;
|
||
pmbr = map_find(MAP_TYPE_PMBR);
|
||
if (pmbr == NULL) {
|
||
... | ... | |
hdr->hdr_lba_table = htole64(tbl2->map_start);
|
||
hdr->hdr_lba_alt = htole64(1);
|
||
lent = NULL;
|
||
li = 0;
|
||
for (i = 0; i < le32toh(hdr->hdr_entries); ++i) {
|
||
ent = (void *)((char *)tbl->map_data + i *
|
||
le32toh(hdr->hdr_entsz));
|
||
if (uuid_is_nil(&ent->ent_type, NULL))
|
||
continue;
|
||
lent = ent;
|
||
li = i;
|
||
}
|
||
hdr = gpt2->map_data;
|
||
if (lent) {
|
||
uuid_to_string(&ent->ent_type, &name, NULL);
|
||
nblocks = last - blocks - le64toh(lent->ent_lba_start);
|
||
nblocks = (nblocks * secsz / (1024 * 1024)) * 1024 * 1024 /
|
||
secsz;
|
||
if (le64toh(lent->ent_lba_end) ==
|
||
le64toh(lent->ent_lba_start) + nblocks - 1) {
|
||
printf("entry %d type=%s %ld,%ld unchanged\n",
|
||
li, name,
|
||
le64toh(lent->ent_lba_start),
|
||
le64toh(lent->ent_lba_end));
|
||
} else {
|
||
printf("expand entry %d type=%s %ld,%ld to %ld\n",
|
||
li, name,
|
||
le64toh(lent->ent_lba_start),
|
||
le64toh(lent->ent_lba_end),
|
||
le64toh(lent->ent_lba_start) + nblocks - 1);
|
||
lent->ent_lba_end = htole64(
|
||
le64toh(lent->ent_lba_start) +
|
||
nblocks - 1);
|
||
}
|
||
}
|
||
if (expand_last)
|
||
expand_last_to_fill(hdr, tbl, last, blocks);
|
||
/*
|
||
* Write out
|
||
... | ... | |
gpt_write(fd, gpt); /* primary partition table */
|
||
gpt_write(fd, tbl); /* primary header */
|
||
gpt_write(fd, pmbr); /* primary header */
|
||
if (name)
|
||
free(name);
|
||
}
|
sbin/gpt/gpt.8 | ||
---|---|---|
.Nm
|
||
to destroy the table in a way that it can be recovered.
|
||
.\" ==== expand ====
|
||
.It Nm Ic expand Ar device
|
||
.It Nm Ic expand Oo Fl x Oc Ar device
|
||
The
|
||
.Ic expand
|
||
command will expand an existing gpt label to cover a device which
|
||
has grown in size, and will also expand the size of the last GPT
|
||
partition to fit.
|
||
has grown in size.
|
||
.Pp
|
||
If the
|
||
.Fl x
|
||
option is specified, last GPT partition is expanded to fit.
|
||
This is typically the first step when expanding a hammer2 filesystem,
|
||
after which disklabel -x and hammer2 growfs are run.
|
||
.\" ==== init ====
|