o Save a copy of the GPT entries for which there's a chunk with an

index referencing it. We need to know the original type and name
   so that we know what to put in the table when we reconstruct it.
o  Clear the table entries before we rebuild it to avoid that we
   end up with stale data.
o  Sequentially populate the table entries from the chunks. For the
   chunks that have an index (now referencing the saved copy) we
   use the saved type and name. This way we can handle unknown types
   better. In all cases we update the start and end LBAs.
This commit is contained in:
marcel 2003-11-04 03:49:01 +00:00
parent 1863735ae3
commit c83ec6383d

View File

@ -224,21 +224,57 @@ static int
update_gpt(int fd, const struct disk *disk, struct gpt_hdr *hdr,
struct gpt_ent *tbl)
{
struct gpt_ent *save;
char *buffer;
struct chunk *c;
off_t off;
size_t bufsz;
int error, idx;
int error, idx, sav;
/*
* Save the entries of those chunks that have an index. They are
* the ones that exist on disk already.
*/
sav = 0;
for (c = disk->chunks->part; c != NULL; c = c->next) {
if ((c->flags & CHUNK_HAS_INDEX))
sav++;
}
if (sav > 0) {
save = malloc(sav * sizeof(struct gpt_ent));
if (save == NULL)
abort();
sav = 0;
for (c = disk->chunks->part; c != NULL; c = c->next) {
if ((c->flags & CHUNK_HAS_INDEX)) {
idx = CHUNK_FTOI(c->flags);
save[sav] = tbl[idx];
c->flags ^= CHUNK_ITOF(idx);
c->flags |= CHUNK_ITOF(sav);
sav++;
}
}
} else
save = NULL;
/*
* Clear the table entries.
*/
for (idx = 0; idx < disk->gpt_size; idx++) {
uuid_create_nil(&tbl[idx].ent_type, NULL);
tbl[idx].ent_lba_start = 0;
tbl[idx].ent_lba_end = 0;
tbl[idx].ent_attr = 0;
bzero(tbl[idx].ent_name, sizeof(tbl[idx].ent_name));
}
/*
* Repopulate the table from the chunks, possibly using saved
* information.
*/
idx = 0;
for (c = disk->chunks->part; c != NULL; c = c->next) {
if (!(c->flags & CHUNK_HAS_INDEX)) {
while (idx < disk->gpt_size &&
!uuid_is_nil(&tbl[idx].ent_type, NULL))
idx++;
if (idx == disk->gpt_size)
return (ENOSPC);
switch (c->type) {
case freebsd:
tbl[idx].ent_type = _fbsd;
@ -261,12 +297,21 @@ update_gpt(int fd, const struct disk *disk, struct gpt_hdr *hdr,
default:
return (EINVAL);
}
} else
idx = CHUNK_FTOI(c->flags);
} else {
sav = CHUNK_FTOI(c->flags);
tbl[idx].ent_type = save[sav].ent_type;
memcpy(tbl[idx].ent_name, save[sav].ent_name,
sizeof(tbl[idx].ent_name));
}
tbl[idx].ent_lba_start = c->offset;
tbl[idx].ent_lba_end = c->end;
idx++;
if (idx == disk->gpt_size)
return (ENOSPC);
}
if (save != NULL)
free(save);
hdr[0].hdr_crc_table = crc32(tbl,
disk->gpt_size * sizeof(struct gpt_ent));