|
|
b394b9 |
From 28b08b639aeaadbfcc3fb66558e6b392b2b5d44c Mon Sep 17 00:00:00 2001
|
|
|
6ec1d7 |
From: Karel Zak <kzak@redhat.com>
|
|
|
6ec1d7 |
Date: Tue, 28 Jun 2016 11:30:21 +0200
|
|
|
b394b9 |
Subject: [PATCH 82/86] fdisk: backport DOS logical partitions chain reorder
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
... from the current upstream.
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1304246
|
|
|
6ec1d7 |
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
|
6ec1d7 |
---
|
|
|
6ec1d7 |
fdisks/fdiskdoslabel.c | 170 +++++++++++++++++++++++++++++++++----------------
|
|
|
b394b9 |
1 file changed, 116 insertions(+), 54 deletions(-)
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
diff --git a/fdisks/fdiskdoslabel.c b/fdisks/fdiskdoslabel.c
|
|
|
6ec1d7 |
index fe04ac7..b7eb35a 100644
|
|
|
6ec1d7 |
--- a/fdisks/fdiskdoslabel.c
|
|
|
6ec1d7 |
+++ b/fdisks/fdiskdoslabel.c
|
|
|
6ec1d7 |
@@ -55,6 +55,22 @@ static int MBRbuffer_changed;
|
|
|
6ec1d7 |
#define cround(c, n) (fdisk_context_use_cylinders(c) ? \
|
|
|
6ec1d7 |
((n) / fdisk_context_get_units_per_sector(c)) + 1 : (n))
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+static unsigned long long
|
|
|
6ec1d7 |
+get_abs_partition_start(struct pte *pe)
|
|
|
6ec1d7 |
+{
|
|
|
6ec1d7 |
+ return pe->offset + get_start_sect(pe->part_table);
|
|
|
6ec1d7 |
+}
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+static unsigned long long
|
|
|
6ec1d7 |
+get_abs_partition_end(struct pte *pe)
|
|
|
6ec1d7 |
+{
|
|
|
6ec1d7 |
+ unsigned long long size;
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ size = get_nr_sects(pe->part_table);
|
|
|
6ec1d7 |
+ return get_abs_partition_start(pe) + size - (size ? 1 : 0);
|
|
|
6ec1d7 |
+}
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
static void warn_alignment(struct fdisk_context *cxt)
|
|
|
6ec1d7 |
{
|
|
|
6ec1d7 |
if (nowarn)
|
|
|
6ec1d7 |
@@ -1254,67 +1270,113 @@ void dos_list_table_expert(struct fdisk_context *cxt, int extend)
|
|
|
6ec1d7 |
}
|
|
|
6ec1d7 |
}
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
-/*
|
|
|
6ec1d7 |
- * Fix the chain of logicals.
|
|
|
6ec1d7 |
- * extended_offset is unchanged, the set of sectors used is unchanged
|
|
|
6ec1d7 |
- * The chain is sorted so that sectors increase, and so that
|
|
|
6ec1d7 |
- * starting sectors increase.
|
|
|
6ec1d7 |
- *
|
|
|
6ec1d7 |
- * After this it may still be that cfdisk doesn't like the table.
|
|
|
6ec1d7 |
- * (This is because cfdisk considers expanded parts, from link to
|
|
|
6ec1d7 |
- * end of partition, and these may still overlap.)
|
|
|
6ec1d7 |
- * Now
|
|
|
6ec1d7 |
- * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
|
|
|
6ec1d7 |
- * may help.
|
|
|
6ec1d7 |
- */
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+static void print_chain_of_logicals(struct fdisk_context *cxt)
|
|
|
6ec1d7 |
+{
|
|
|
6ec1d7 |
+ size_t i;
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ fputc('\n', stdout);
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ for (i = 4; i < cxt->label->nparts_max; i++) {
|
|
|
6ec1d7 |
+ struct pte *pe = &ptes[i];
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ fprintf(stderr, "#%02zu EBR [%10ju], "
|
|
|
6ec1d7 |
+ "data[start=%10ju (%10ju), size=%10ju], "
|
|
|
6ec1d7 |
+ "link[start=%10ju (%10ju), size=%10ju]\n",
|
|
|
6ec1d7 |
+ i, (uintmax_t) pe->offset,
|
|
|
6ec1d7 |
+ /* data */
|
|
|
6ec1d7 |
+ (uintmax_t) get_start_sect(pe->part_table),
|
|
|
6ec1d7 |
+ (uintmax_t) get_abs_partition_start(pe),
|
|
|
6ec1d7 |
+ (uintmax_t) get_nr_sects(pe->part_table),
|
|
|
6ec1d7 |
+ /* link */
|
|
|
6ec1d7 |
+ (uintmax_t) get_start_sect(pe->ext_pointer),
|
|
|
6ec1d7 |
+ (uintmax_t) (extended_offset + get_start_sect(pe->ext_pointer)),
|
|
|
6ec1d7 |
+ (uintmax_t) get_nr_sects(pe->ext_pointer));
|
|
|
6ec1d7 |
+ }
|
|
|
6ec1d7 |
+}
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+static int cmp_ebr_offsets(const void *a, const void *b)
|
|
|
6ec1d7 |
+{
|
|
|
6ec1d7 |
+ struct pte *ae = (struct pte *) a,
|
|
|
6ec1d7 |
+ *be = (struct pte *) b;
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ if (ae->offset == 0 && be->offset == 0)
|
|
|
6ec1d7 |
+ return 0;
|
|
|
6ec1d7 |
+ if (ae->offset == 0)
|
|
|
6ec1d7 |
+ return 1;
|
|
|
6ec1d7 |
+ if (be->offset == 0)
|
|
|
6ec1d7 |
+ return -1;
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ return cmp_numbers(ae->offset, be->offset);
|
|
|
6ec1d7 |
+}
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
static void fix_chain_of_logicals(struct fdisk_context *cxt)
|
|
|
6ec1d7 |
{
|
|
|
6ec1d7 |
- size_t j, oj, ojj, sj, sjj;
|
|
|
6ec1d7 |
- struct partition *pj,*pjj,tmp;
|
|
|
6ec1d7 |
-
|
|
|
6ec1d7 |
- /* Stage 1: sort sectors but leave sector of part 4 */
|
|
|
6ec1d7 |
- /* (Its sector is the global extended_offset.) */
|
|
|
6ec1d7 |
- stage1:
|
|
|
6ec1d7 |
- for (j = 5; j < cxt->label->nparts_max - 1; j++) {
|
|
|
6ec1d7 |
- oj = ptes[j].offset;
|
|
|
6ec1d7 |
- ojj = ptes[j+1].offset;
|
|
|
6ec1d7 |
- if (oj > ojj) {
|
|
|
6ec1d7 |
- ptes[j].offset = ojj;
|
|
|
6ec1d7 |
- ptes[j+1].offset = oj;
|
|
|
6ec1d7 |
- pj = ptes[j].part_table;
|
|
|
6ec1d7 |
- set_start_sect(pj, get_start_sect(pj)+oj-ojj);
|
|
|
6ec1d7 |
- pjj = ptes[j+1].part_table;
|
|
|
6ec1d7 |
- set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
|
|
|
6ec1d7 |
- set_start_sect(ptes[j-1].ext_pointer,
|
|
|
6ec1d7 |
- ojj-extended_offset);
|
|
|
6ec1d7 |
- set_start_sect(ptes[j].ext_pointer,
|
|
|
6ec1d7 |
- oj-extended_offset);
|
|
|
6ec1d7 |
- goto stage1;
|
|
|
6ec1d7 |
+ struct pte *last;
|
|
|
6ec1d7 |
+ size_t i;
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ DBG(CONTEXT, print_chain_of_logicals(cxt));
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ /* Sort chain by EBR offsets */
|
|
|
6ec1d7 |
+ qsort(&ptes[4], cxt->label->nparts_max - 4, sizeof(struct pte),
|
|
|
6ec1d7 |
+ cmp_ebr_offsets);
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+again:
|
|
|
6ec1d7 |
+ /* Sort data partitions by start */
|
|
|
6ec1d7 |
+ for (i = 4; i < cxt->label->nparts_max - 1; i++) {
|
|
|
6ec1d7 |
+ struct pte *cur = &ptes[i],
|
|
|
6ec1d7 |
+ *nxt = &ptes[i + 1];
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ if (get_abs_partition_start(cur) >
|
|
|
6ec1d7 |
+ get_abs_partition_start(nxt)) {
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ struct partition tmp = *cur->part_table;
|
|
|
6ec1d7 |
+ sector_t cur_start = get_abs_partition_start(cur),
|
|
|
6ec1d7 |
+ nxt_start = get_abs_partition_start(nxt);
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ /* swap data partitions */
|
|
|
6ec1d7 |
+ *cur->part_table = *nxt->part_table;
|
|
|
6ec1d7 |
+ *nxt->part_table = tmp;
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ /* Recount starts according to EBR offsets, the absolute
|
|
|
6ec1d7 |
+ * address still has to be the same! */
|
|
|
6ec1d7 |
+ set_start_sect(cur->part_table, nxt_start - cur->offset);
|
|
|
6ec1d7 |
+ set_start_sect(nxt->part_table, cur_start - nxt->offset);
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ cur->changed = 1;
|
|
|
6ec1d7 |
+ nxt->changed = 1;
|
|
|
6ec1d7 |
+ goto again;
|
|
|
6ec1d7 |
}
|
|
|
6ec1d7 |
}
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
- /* Stage 2: sort starting sectors */
|
|
|
6ec1d7 |
- stage2:
|
|
|
6ec1d7 |
- for (j = 4; j < cxt->label->nparts_max - 1; j++) {
|
|
|
6ec1d7 |
- pj = ptes[j].part_table;
|
|
|
6ec1d7 |
- pjj = ptes[j+1].part_table;
|
|
|
6ec1d7 |
- sj = get_start_sect(pj);
|
|
|
6ec1d7 |
- sjj = get_start_sect(pjj);
|
|
|
6ec1d7 |
- oj = ptes[j].offset;
|
|
|
6ec1d7 |
- ojj = ptes[j+1].offset;
|
|
|
6ec1d7 |
- if (oj+sj > ojj+sjj) {
|
|
|
6ec1d7 |
- tmp = *pj;
|
|
|
6ec1d7 |
- *pj = *pjj;
|
|
|
6ec1d7 |
- *pjj = tmp;
|
|
|
6ec1d7 |
- set_start_sect(pj, ojj+sjj-oj);
|
|
|
6ec1d7 |
- set_start_sect(pjj, oj+sj-ojj);
|
|
|
6ec1d7 |
- goto stage2;
|
|
|
6ec1d7 |
- }
|
|
|
6ec1d7 |
+ /* Update EBR links */
|
|
|
6ec1d7 |
+ for (i = 4; i < cxt->label->nparts_max - 1; i++) {
|
|
|
6ec1d7 |
+ struct pte *cur = &ptes[i],
|
|
|
6ec1d7 |
+ *nxt = &ptes[i + 1];
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ sector_t noff = nxt->offset - extended_offset,
|
|
|
6ec1d7 |
+ ooff = get_start_sect(cur->ext_pointer);
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ if (noff == ooff)
|
|
|
6ec1d7 |
+ continue;
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ DBG(CONTEXT, dbgprint("DOS: fix EBR [%10ju] link %ju -> %ju",
|
|
|
6ec1d7 |
+ (uintmax_t) cur->offset,
|
|
|
6ec1d7 |
+ (uintmax_t) ooff, (uintmax_t) noff));
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ set_partition(cxt, i, 1, nxt->offset,
|
|
|
6ec1d7 |
+ get_abs_partition_end(nxt),
|
|
|
6ec1d7 |
+ EXTENDED);
|
|
|
6ec1d7 |
+ }
|
|
|
6ec1d7 |
+
|
|
|
6ec1d7 |
+ /* always terminate the chain ! */
|
|
|
6ec1d7 |
+ last = &ptes[cxt->label->nparts_max - 1];
|
|
|
6ec1d7 |
+ if (last) {
|
|
|
6ec1d7 |
+ clear_partition(last->ext_pointer);
|
|
|
6ec1d7 |
+ last->changed = 1;
|
|
|
6ec1d7 |
}
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
- /* Probably something was changed */
|
|
|
6ec1d7 |
- for (j = 4; j < cxt->label->nparts_max; j++)
|
|
|
6ec1d7 |
- ptes[j].changed = 1;
|
|
|
6ec1d7 |
+ DBG(CONTEXT, print_chain_of_logicals(cxt));
|
|
|
6ec1d7 |
}
|
|
|
6ec1d7 |
|
|
|
6ec1d7 |
void dos_fix_partition_table_order(struct fdisk_context *cxt)
|
|
|
6ec1d7 |
--
|
|
|
6ec1d7 |
2.7.4
|
|
|
6ec1d7 |
|