svn commit: r217480 - user/nwhitehorn/bsdinstall/partedit
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Sun Jan 16 18:46:17 UTC 2011
Author: nwhitehorn
Date: Sun Jan 16 18:46:17 2011
New Revision: 217480
URL: http://svn.freebsd.org/changeset/base/217480
Log:
Improve the robustness of the partition wizard.
Modified:
user/nwhitehorn/bsdinstall/partedit/gpart_ops.c
user/nwhitehorn/bsdinstall/partedit/part_wizard.c
user/nwhitehorn/bsdinstall/partedit/partedit.c
user/nwhitehorn/bsdinstall/partedit/partedit.h
Modified: user/nwhitehorn/bsdinstall/partedit/gpart_ops.c
==============================================================================
--- user/nwhitehorn/bsdinstall/partedit/gpart_ops.c Sun Jan 16 18:04:01 2011 (r217479)
+++ user/nwhitehorn/bsdinstall/partedit/gpart_ops.c Sun Jan 16 18:46:17 2011 (r217480)
@@ -517,6 +517,105 @@ set_default_part_metadata(const char *na
}
}
+static
+int part_compare(const void *xa, const void *xb)
+{
+ struct gprovider **a = (struct gprovider **)xa;
+ struct gprovider **b = (struct gprovider **)xb;
+ intmax_t astart, bstart;
+ struct gconfig *gc;
+
+ astart = bstart = 0;
+ LIST_FOREACH(gc, &(*a)->lg_config, lg_config)
+ if (strcmp(gc->lg_name, "start") == 0) {
+ astart = strtoimax(gc->lg_val, NULL, 0);
+ break;
+ }
+ LIST_FOREACH(gc, &(*b)->lg_config, lg_config)
+ if (strcmp(gc->lg_name, "start") == 0) {
+ bstart = strtoimax(gc->lg_val, NULL, 0);
+ break;
+ }
+
+ if (astart < bstart)
+ return -1;
+ else if (astart > bstart)
+ return 1;
+ else
+ return 0;
+}
+
+intmax_t
+gpart_max_free(struct ggeom *geom, intmax_t *npartstart)
+{
+ struct gconfig *gc;
+ struct gprovider *pp, **providers;
+ intmax_t lastend;
+ intmax_t start, end;
+ intmax_t maxsize, maxstart;
+ intmax_t partstart, partend;
+ int i, nparts;
+
+ /* Now get the maximum free size and free start */
+ start = end = 0;
+ LIST_FOREACH(gc, &geom->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "first") == 0)
+ start = strtoimax(gc->lg_val, NULL, 0);
+ if (strcmp(gc->lg_name, "last") == 0)
+ end = strtoimax(gc->lg_val, NULL, 0);
+ }
+
+ i = nparts = 0;
+ LIST_FOREACH(pp, &geom->lg_provider, lg_provider)
+ nparts++;
+ providers = calloc(nparts, sizeof(providers[0]));
+ LIST_FOREACH(pp, &geom->lg_provider, lg_provider)
+ providers[i++] = pp;
+ qsort(providers, nparts, sizeof(providers[0]), part_compare);
+
+ lastend = start - 1;
+ maxsize = 0;
+ for (i = 0; i < nparts; i++) {
+ pp = providers[i];
+
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "start") == 0)
+ partstart = strtoimax(gc->lg_val, NULL, 0);
+ if (strcmp(gc->lg_name, "end") == 0)
+ partend = strtoimax(gc->lg_val, NULL, 0);
+ }
+
+ if (partstart - lastend > maxsize) {
+ maxsize = partstart - lastend - 1;
+ maxstart = lastend + 1;
+ }
+
+ lastend = partend;
+ }
+
+ if (end - lastend > maxsize) {
+ maxsize = end - lastend - 1;
+ maxstart = lastend + 1;
+ }
+
+ pp = LIST_FIRST(&geom->lg_consumer)->lg_provider;
+
+ /* Compute beginning of new partition and maximum available space */
+ if (pp->lg_stripesize > 0 &&
+ (maxstart*pp->lg_sectorsize % pp->lg_stripesize) != 0) {
+ intmax_t offset = (pp->lg_stripesize -
+ ((maxstart*pp->lg_sectorsize) % pp->lg_stripesize)) /
+ pp->lg_sectorsize;
+ maxstart += offset;
+ maxsize -= offset;
+ }
+
+ if (npartstart != NULL)
+ *npartstart = maxstart;
+
+ return (maxsize);
+}
+
void
gpart_create(struct gprovider *pp, char *default_type, char *default_size,
char *default_mountpoint, char **partname, int interactive)
@@ -527,7 +626,7 @@ gpart_create(struct gprovider *pp, char
struct ggeom *geom;
const char *errstr, *scheme;
char sizestr[32], startstr[32], output[64];
- intmax_t maxsize, size, start, end, sector, firstfree, stripe;
+ intmax_t maxsize, size, sector, firstfree, stripe;
uint64_t bytes;
int nitems, choice, junk;
unsigned i;
@@ -586,34 +685,12 @@ gpart_create(struct gprovider *pp, char
if (geom == NULL)
return;
- /* Now get the maximum free size and free start */
- start = end = 0;
- LIST_FOREACH(gc, &geom->lg_config, lg_config) {
- if (strcmp(gc->lg_name, "first") == 0)
- start = strtoimax(gc->lg_val, NULL, 0);
- if (strcmp(gc->lg_name, "last") == 0)
- end = strtoimax(gc->lg_val, NULL, 0);
+ /* Now get the partition scheme */
+ LIST_FOREACH(gc, &geom->lg_config, lg_config)
if (strcmp(gc->lg_name, "scheme") == 0)
scheme = gc->lg_val;
- }
-
- firstfree = start;
- LIST_FOREACH(pp, &geom->lg_provider, lg_provider) {
- LIST_FOREACH(gc, &pp->lg_config, lg_config) {
- if (strcmp(gc->lg_name, "end") == 0) {
- intmax_t partend;
- partend = strtoimax(gc->lg_val, NULL, 0);
- if (partend > firstfree)
- firstfree = partend + 1;
- }
- }
- }
-
- /* Compute beginning of new partition and maximum available space */
- if (stripe > 0 && (firstfree*sector % stripe) != 0)
- firstfree += (stripe - ((firstfree*sector) % stripe)) / sector;
- size = end - firstfree;
+ size = gpart_max_free(geom, &firstfree);
if (size <= 0) {
dialog_msgbox("Error", "No free space left on device.", 0, 0,
TRUE);
@@ -621,8 +698,8 @@ gpart_create(struct gprovider *pp, char
}
/* Leave a free megabyte in case we need to write a boot partition */
- if (size*sector >= 1024*1024)
- size -= 1024*1024/sector;
+ if (size*sector >= (intmax_t)bootpart_size(scheme))
+ size -= bootpart_size(scheme)/sector;
maxsize = size;
humanize_number(sizestr, 7, size*sector, "B", HN_AUTOSCALE,
Modified: user/nwhitehorn/bsdinstall/partedit/part_wizard.c
==============================================================================
--- user/nwhitehorn/bsdinstall/partedit/part_wizard.c Sun Jan 16 18:04:01 2011 (r217479)
+++ user/nwhitehorn/bsdinstall/partedit/part_wizard.c Sun Jan 16 18:46:17 2011 (r217480)
@@ -9,11 +9,12 @@
#include "partedit.h"
-#define GPART_FLAGS "x" /* Do not commit changes by default */
+#define MIN_FREE_SPACE (1024*1024*1024) /* 1 GB */
+#define SWAP_SIZE(available) MIN(available/20, 4*1024*1024*1024LL)
static char *boot_disk(struct gmesh *mesh);
static char *wizard_partition(struct gmesh *mesh, const char *disk);
-static void wizard_makeparts(struct gmesh *mesh, const char *disk);
+static int wizard_makeparts(struct gmesh *mesh, const char *disk);
int
part_wizard(void) {
@@ -21,6 +22,7 @@ part_wizard(void) {
struct gmesh mesh;
char *disk, *schemeroot;
+startwizard:
error = geom_gettree(&mesh);
dlg_put_backtitle();
@@ -40,7 +42,9 @@ part_wizard(void) {
geom_deletetree(&mesh);
error = geom_gettree(&mesh);
- wizard_makeparts(&mesh, schemeroot);
+ error = wizard_makeparts(&mesh, schemeroot);
+ if (error)
+ goto startwizard;
free(schemeroot);
geom_deletetree(&mesh);
@@ -212,7 +216,7 @@ query:
return (retval);
}
-static void
+static int
wizard_makeparts(struct gmesh *mesh, const char *disk)
{
struct gmesh submesh;
@@ -221,9 +225,9 @@ wizard_makeparts(struct gmesh *mesh, con
struct gconfig *gc;
const char *scheme;
struct gprovider *pp;
- intmax_t start, end;
- intmax_t swapsize;
+ intmax_t swapsize, available;
char swapsizestr[10], rootsizestr[10];
+ int retval;
LIST_FOREACH(classp, &mesh->lg_class, lg_class)
if (strcmp(classp->lg_name, "PART") == 0)
@@ -233,23 +237,37 @@ wizard_makeparts(struct gmesh *mesh, con
if (strcmp(gp->lg_name, disk) == 0)
break;
- LIST_FOREACH(gc, &gp->lg_config, lg_config) {
- if (strcmp(gc->lg_name, "first") == 0)
- start = strtoimax(gc->lg_val, NULL, 0);
- if (strcmp(gc->lg_name, "last") == 0)
- end = strtoimax(gc->lg_val, NULL, 0);
+ LIST_FOREACH(gc, &gp->lg_config, lg_config)
if (strcmp(gc->lg_name, "scheme") == 0)
scheme = gc->lg_val;
- }
pp = provider_for_name(mesh, disk);
- swapsize = MIN((end - start)*pp->lg_sectorsize/50,
- 4*1024*1024*(intmax_t)(1024));
+ available = gpart_max_free(gp, NULL)*pp->lg_sectorsize;
+ if (available < MIN_FREE_SPACE) {
+ char availablestr[10], neededstr[10], message[512];
+ humanize_number(availablestr, 7, available, "B", HN_AUTOSCALE,
+ HN_DECIMAL);
+ humanize_number(neededstr, 7, MIN_FREE_SPACE, "B", HN_AUTOSCALE,
+ HN_DECIMAL);
+ sprintf(message, "There is not enough free space on %s to "
+ "install FreeBSD (%s free, %s required). Would you like "
+ "to choose another disk or to open the partition editor?",
+ disk, availablestr, neededstr);
+
+ dialog_vars.yes_label = "Another Disk";
+ dialog_vars.no_label = "Editor";
+ retval = dialog_yesno("Warning", message, 0, 0);
+ dialog_vars.yes_label = NULL;
+ dialog_vars.no_label = NULL;
+
+ return (!retval); /* Editor -> return 0 */
+ }
+
+ swapsize = SWAP_SIZE(available);
humanize_number(swapsizestr, 7, swapsize, "B", HN_AUTOSCALE,
HN_NOSPACE | HN_DECIMAL);
- humanize_number(rootsizestr, 7,
- (end - start)*pp->lg_sectorsize - swapsize - 1024*1024,
+ humanize_number(rootsizestr, 7, available - swapsize - 1024*1024,
"B", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
geom_gettree(&submesh);
@@ -261,4 +279,7 @@ wizard_makeparts(struct gmesh *mesh, con
pp = provider_for_name(&submesh, disk);
gpart_create(pp, "freebsd-swap", swapsizestr, NULL, NULL, 0);
geom_deletetree(&submesh);
+
+ return (0);
}
+
Modified: user/nwhitehorn/bsdinstall/partedit/partedit.c
==============================================================================
--- user/nwhitehorn/bsdinstall/partedit/partedit.c Sun Jan 16 18:04:01 2011 (r217479)
+++ user/nwhitehorn/bsdinstall/partedit/partedit.c Sun Jan 16 18:46:17 2011 (r217480)
@@ -25,6 +25,7 @@ static int validate_setup(void);
int
main(int argc, const char **argv) {
struct partition_metadata *md;
+ const char *prompt;
struct partedit_item *items;
struct gmesh mesh;
int i, op, nitems, nscroll;
@@ -40,8 +41,14 @@ main(int argc, const char **argv) {
dialog_vars.item_help = TRUE;
nscroll = i = 0;
- if (strcmp(basename(argv[0]), "autopart") == 0) /* Guided */
+ if (strcmp(basename(argv[0]), "autopart") == 0) { /* Guided */
+ prompt = "Please review the disk setup. When complete, press "
+ "the Finished button.";
part_wizard();
+ } else {
+ prompt = "Create partitions for FreeBSD. No changes will be "
+ "made until you select Finished.";
+ }
/* Show the part editor either immediately, or to confirm wizard */
while (1) {
@@ -53,9 +60,7 @@ main(int argc, const char **argv) {
if (i >= nitems)
i = nitems - 1;
- op = diskeditor_show("Partition Editor",
- "Create partitions for FreeBSD. No changes will be made "
- "until you select Finished.",
+ op = diskeditor_show("Partition Editor", prompt,
items, nitems, &i, &nscroll);
switch (op) {
@@ -95,7 +100,7 @@ main(int argc, const char **argv) {
if (op == 4 && validate_setup()) { /* Finished */
dialog_vars.extra_button = TRUE;
dialog_vars.extra_label =
- __DECONST(char *, "Don't Save");
+ __DECONST(char *, "Abort");
dialog_vars.ok_label = __DECONST(char *, "Save");
op = dialog_yesno("Confirmation", "Your changes will "
"now be written to disk. If you have chosen to "
Modified: user/nwhitehorn/bsdinstall/partedit/partedit.h
==============================================================================
--- user/nwhitehorn/bsdinstall/partedit/partedit.h Sun Jan 16 18:04:01 2011 (r217479)
+++ user/nwhitehorn/bsdinstall/partedit/partedit.h Sun Jan 16 18:46:17 2011 (r217480)
@@ -1,4 +1,5 @@
#include <sys/queue.h>
+#include <inttypes.h>
#include <fstab.h>
struct gprovider;
@@ -30,6 +31,7 @@ void gpart_destroy(struct ggeom *lg_geom
void gpart_edit(struct gprovider *pp);
void gpart_create(struct gprovider *pp, char *default_type, char *default_size,
char *default_mountpoint, char **output, int interactive);
+intmax_t gpart_max_free(struct ggeom *gp, intmax_t *start);
void gpart_revert(struct gprovider *pp);
void gpart_revert_all(struct gmesh *mesh);
void gpart_commit(struct gmesh *mesh);
More information about the svn-src-user
mailing list