summaryrefslogtreecommitdiffstats
path: root/sbin/bsdlabel/bsdlabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/bsdlabel/bsdlabel.c')
-rw-r--r--sbin/bsdlabel/bsdlabel.c67
1 files changed, 62 insertions, 5 deletions
diff --git a/sbin/bsdlabel/bsdlabel.c b/sbin/bsdlabel/bsdlabel.c
index 3d12834..366d5ec 100644
--- a/sbin/bsdlabel/bsdlabel.c
+++ b/sbin/bsdlabel/bsdlabel.c
@@ -1074,7 +1074,8 @@ checklabel(struct disklabel *lp)
struct partition *pp;
int i, errors = 0;
char part;
- u_long total_size, total_percent, current_offset;
+ u_long base_offset, needed, total_size, total_percent, current_offset;
+ long free_space;
int seen_default_offset;
int hog_part;
int j;
@@ -1201,9 +1202,25 @@ checklabel(struct disklabel *lp)
}
}
}
+
+ /* Find out the total free space, excluding the boot block area. */
+ base_offset = BBSIZE / secsize;
+ free_space = 0;
+ for (i = 0; i < lp->d_npartitions; i++) {
+ pp = &lp->d_partitions[i];
+ if (!part_set[i] || i == RAW_PART ||
+ part_size_type[i] == '%' || part_size_type[i] == '*')
+ continue;
+ if (pp->p_offset > base_offset)
+ free_space += pp->p_offset - base_offset;
+ if (pp->p_offset + pp->p_size > base_offset)
+ base_offset = pp->p_offset + pp->p_size;
+ }
+ if (base_offset < lp->d_secperunit)
+ free_space += lp->d_secperunit - base_offset;
+
/* handle % partitions - note %'s don't need to add up to 100! */
if (total_percent != 0) {
- long free_space = lp->d_secperunit - total_size;
if (total_percent > 100) {
fprintf(stderr,"total percentage %lu is greater than 100\n",
total_percent);
@@ -1232,12 +1249,52 @@ checklabel(struct disklabel *lp)
}
/* give anything remaining to the hog partition */
if (hog_part != -1) {
- lp->d_partitions[hog_part].p_size = lp->d_secperunit - total_size;
- total_size = lp->d_secperunit;
+ /*
+ * Find the range of offsets usable by '*' partitions around
+ * the hog partition and how much space they need.
+ */
+ needed = 0;
+ base_offset = BBSIZE / secsize;
+ for (i = hog_part - 1; i >= 0; i--) {
+ pp = &lp->d_partitions[i];
+ if (!part_set[i] || i == RAW_PART)
+ continue;
+ if (part_offset_type[i] == '*') {
+ needed += pp->p_size;
+ continue;
+ }
+ base_offset = pp->p_offset + pp->p_size;
+ break;
+ }
+ current_offset = lp->d_secperunit;
+ for (i = lp->d_npartitions - 1; i > hog_part; i--) {
+ pp = &lp->d_partitions[i];
+ if (!part_set[i] || i == RAW_PART)
+ continue;
+ if (part_offset_type[i] == '*') {
+ needed += pp->p_size;
+ continue;
+ }
+ current_offset = pp->p_offset;
+ }
+
+ if (current_offset - base_offset <= needed) {
+ fprintf(stderr, "Cannot find space for partition %c\n",
+ hog_part + 'a');
+ fprintf(stderr,
+ "Need more than %lu sectors between %lu and %lu\n",
+ needed, base_offset, current_offset);
+ errors++;
+ lp->d_partitions[hog_part].p_size = 0;
+ } else {
+ lp->d_partitions[hog_part].p_size = current_offset -
+ base_offset - needed;
+ total_size += lp->d_partitions[hog_part].p_size;
+ }
}
/* Now set the offsets for each partition */
- current_offset = 0; /* in sectors */
+ current_offset = BBSIZE / secsize; /* in sectors */
seen_default_offset = 0;
for (i = 0; i < lp->d_npartitions; i++) {
part = 'a' + i;
OpenPOWER on IntegriCloud