summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/dos.c
diff options
context:
space:
mode:
authorKarel Zak2014-02-03 18:06:07 +0100
committerKarel Zak2014-03-11 11:35:14 +0100
commitbcddbe96882b88d53b6bc0495e7322c0820a5122 (patch)
tree9a755edc5bd80f7d0e4b448b10ac9400202d0f0a /libfdisk/src/dos.c
parentlibfdisk: again improve freespace code (diff)
downloadkernel-qcow2-util-linux-bcddbe96882b88d53b6bc0495e7322c0820a5122.tar.gz
kernel-qcow2-util-linux-bcddbe96882b88d53b6bc0495e7322c0820a5122.tar.xz
kernel-qcow2-util-linux-bcddbe96882b88d53b6bc0495e7322c0820a5122.zip
libfdisk: (dos) fix log.partition delete
- deallocate sector buffer and deincrement part_max when delete last logical partition - zap obsolete EBR on begin of the extended partition when no logical partition defined Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/dos.c')
-rw-r--r--libfdisk/src/dos.c70
1 files changed, 54 insertions, 16 deletions
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index 327a747cf..5d01b3fbe 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -142,7 +142,8 @@ static void partition_set_changed(
if (!pe)
return;
- DBG(LABEL, dbgprint("DOS: setting %zu partition changed", i));
+ DBG(LABEL, dbgprint("DOS: setting %zu partition to %s", i,
+ changed ? "changed" : "unchnaged"));
pe->changed = changed ? 1 : 0;
if (changed)
@@ -357,7 +358,8 @@ static int dos_delete_partition(struct fdisk_context *cxt, size_t partnum)
if (!pe)
return -EINVAL;
- DBG(LABEL, dbgprint("DOS: delete partiton %zu", partnum));
+ DBG(LABEL, dbgprint("DOS: delete partiton %zu (max=%zu)", partnum,
+ cxt->label->nparts_max));
l = self_label(cxt);
p = pe->pt_entry;
@@ -381,19 +383,20 @@ static int dos_delete_partition(struct fdisk_context *cxt, size_t partnum)
clear_partition(l->ptes[partnum].ex_entry);
partition_set_changed(cxt, partnum, 1);
} else {
- DBG(LABEL, dbgprint("--> delete logical [non-last, move down]"));
+ DBG(LABEL, dbgprint("--> delete logical [move down]"));
if (partnum > 4) {
- /* delete this link in the chain */
+ DBG(LABEL, dbgprint(" --> delete %zu logical link", partnum));
p = l->ptes[partnum - 1].ex_entry;
*p = *q;
dos_partition_set_start(p, dos_partition_get_start(q));
dos_partition_set_size(p, dos_partition_get_size(q));
partition_set_changed(cxt, partnum - 1, 1);
- } else if (cxt->label->nparts_max > 5) { /* 5 will be moved to 4 */
- /* the first logical in a longer chain */
- pe = &l->ptes[5];
- if (pe->pt_entry) /* prevent SEGFAULT */
+ } else if (cxt->label->nparts_max > 5) {
+ DBG(LABEL, dbgprint(" --> delete first logical link"));
+ pe = &l->ptes[5]; /* second logical */
+
+ if (pe->pt_entry) /* prevent SEGFAULT */
dos_partition_set_start(pe->pt_entry,
get_abs_partition_start(pe) -
l->ext_offset);
@@ -402,21 +405,35 @@ static int dos_delete_partition(struct fdisk_context *cxt, size_t partnum)
}
if (cxt->label->nparts_max > 5) {
+ DBG(LABEL, dbgprint(" --> move ptes"));
cxt->label->nparts_max--;
if (l->ptes[partnum].private_sectorbuffer) {
- DBG(LABEL, dbgprint("--> freeing pte %zu sector buffer %p",
+ DBG(LABEL, dbgprint(" --> freeing pte %zu sector buffer %p",
partnum, l->ptes[partnum].sectorbuffer));
free(l->ptes[partnum].sectorbuffer);
}
while (partnum < cxt->label->nparts_max) {
- DBG(LABEL, dbgprint("--> moving pte %zu <-- %zu", partnum, partnum + 1));
+ DBG(LABEL, dbgprint(" --> moving pte %zu <-- %zu", partnum, partnum + 1));
l->ptes[partnum] = l->ptes[partnum + 1];
partnum++;
}
memset(&l->ptes[partnum], 0, sizeof(struct pte));
- } else
- /* the only logical: clear only */
+ } else {
+ DBG(LABEL, dbgprint(" --> the only logical: clear only"));
clear_partition(l->ptes[partnum].pt_entry);
+ cxt->label->nparts_max--;
+
+ if (partnum == 4) {
+ DBG(LABEL, dbgprint(" --> clear last logical"));
+ if (l->ptes[partnum].private_sectorbuffer) {
+ DBG(LABEL, dbgprint(" --> freeing pte %zu sector buffer %p",
+ partnum, l->ptes[partnum].sectorbuffer));
+ free(l->ptes[partnum].sectorbuffer);
+ }
+ memset(&l->ptes[partnum], 0, sizeof(struct pte));
+ partition_set_changed(cxt, l->ext_index, 1);
+ }
+ }
}
fdisk_label_set_changed(cxt->label, 1);
@@ -440,7 +457,7 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
return;
}
- DBG(LABEL, dbgprint("DOS: REading extended %zu", ext));
+ DBG(LABEL, dbgprint("DOS: Reading extended %zu", ext));
while (IS_EXTENDED (p->sys_ind)) {
struct pte *pe = self_pte(cxt, cxt->label->nparts_max);
@@ -705,15 +722,20 @@ static int dos_probe_label(struct fdisk_context *cxt)
for (i = 3; i < cxt->label->nparts_max; i++) {
struct pte *pe = self_pte(cxt, i);
+ struct fdisk_dos_label *l = self_label(cxt);
if (!mbr_is_valid_magic(pe->sectorbuffer)) {
fdisk_info(cxt, _(
- "Invalid flag 0x%02x%02x of partition table %zu will "
- "be corrected by w(rite)"),
+ "Invalid flag 0x%02x%02x of EBR (for partition %zu) will "
+ "be corrected by w(rite)."),
pe->sectorbuffer[510],
pe->sectorbuffer[511],
i + 1);
- partition_set_changed(cxt, 1, 1);
+ partition_set_changed(cxt, i, 1);
+
+ /* mark also extended as changed to update the first EBR
+ * in situation that there is no logical partitions at all */
+ partition_set_changed(cxt, l->ext_index, 1);
}
}
@@ -1423,6 +1445,9 @@ static int write_sector(struct fdisk_context *cxt, sector_t secno,
(uintmax_t) secno);
return rc;
}
+
+ DBG(LABEL, dbgprint("DOS: writting to sector %ju", (uintmax_t) secno));
+
if (write(cxt->dev_fd, buf, cxt->sector_size) != (ssize_t) cxt->sector_size)
return -errno;
return 0;
@@ -1455,6 +1480,19 @@ static int dos_write_disklabel(struct fdisk_context *cxt)
goto done;
}
+ if (cxt->label->nparts_max <= 4 && l->ext_offset) {
+ /* we have empty extended partition, check if the partition has
+ * been modified and then cleanup possible remaining EBR */
+ struct pte *pe = self_pte(cxt, l->ext_index);
+ unsigned char empty[512] = { 0 };
+ sector_t off = pe ? get_abs_partition_start(pe) : 0;
+
+ if (off && pe->changed) {
+ mbr_set_magic(empty);
+ write_sector(cxt, off, empty);
+ }
+ }
+
/* EBR (logical partitions) */
for (i = 4; i < cxt->label->nparts_max; i++) {
struct pte *pe = self_pte(cxt, i);