aboutsummaryrefslogtreecommitdiff
path: root/sbin/bsdlabel/bsdlabel.c
diff options
context:
space:
mode:
authorIan Dowse <iedowse@FreeBSD.org>2005-08-14 22:46:50 +0000
committerIan Dowse <iedowse@FreeBSD.org>2005-08-14 22:46:50 +0000
commit3b89beb171320bbd7fa270ebcbbe2119fd385fbc (patch)
treeee0f2cf3df89ef4530691a177e17b848f74777aa /sbin/bsdlabel/bsdlabel.c
parentadf98e7afa6a88f1e9ca5a79d97ddc54d4b65c8f (diff)
downloadsrc-3b89beb171320bbd7fa270ebcbbe2119fd385fbc.tar.gz
src-3b89beb171320bbd7fa270ebcbbe2119fd385fbc.zip
Attempt to improve the logic for automatically sizing partitions
to take into account the new default of starting the first partition after the boot blocks instead of at sector 0. If you used automatic sizing when the first partition did not start at 0, you would get an error that the automatically sized partition extended beyond the end of the disk. Note that there are probably still many more complex cases where automatic sizing and placement will not work (e.g. non-contiguous or out of order partitions).
Notes
Notes: svn path=/head/; revision=149061
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 3d12834f6030..366d5ec2c5c4 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;