Project

General

Profile

Submit #3276 ยป expand.patch

falsifian, 05/26/2021 09:40 PM

View differences:

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 ====
    (1-1/1)