summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2010-03-23 14:32:35 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2010-03-23 14:32:35 +0000
commit2ed309b1014e684597eec0cce043ee97e24b285e (patch)
tree870147da1992f9674995201992754f8215f7a094
parent057d9e8cb62e8e79b31cf4ce1af53e06c3d9e371 (diff)
introducing 'R': interactive command to customize auto allocated labels,
by growing or shrinking them as desired. can use some tweaks, but committing now to be able to work in-tree; ok krw@ lum@
-rw-r--r--sbin/disklabel/disklabel.89
-rw-r--r--sbin/disklabel/editor.c143
2 files changed, 141 insertions, 11 deletions
diff --git a/sbin/disklabel/disklabel.8 b/sbin/disklabel/disklabel.8
index ac65da571d8..e46b2562f6a 100644
--- a/sbin/disklabel/disklabel.8
+++ b/sbin/disklabel/disklabel.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: disklabel.8,v 1.86 2009/07/27 12:39:50 jmc Exp $
+.\" $OpenBSD: disklabel.8,v 1.87 2010/03/23 14:32:34 otto Exp $
.\" $NetBSD: disklabel.8,v 1.9 1995/03/18 14:54:38 cgd Exp $
.\"
.\" Copyright (c) 1987, 1988, 1991, 1993
@@ -33,7 +33,7 @@
.\"
.\" @(#)disklabel.8 8.2 (Berkeley) 4/19/94
.\"
-.Dd $Mdocdate: July 27 2009 $
+.Dd $Mdocdate: March 23 2010 $
.Dt DISKLABEL 8
.Os
.Sh NAME
@@ -422,6 +422,11 @@ partition.
Quit the editor.
If any changes have been made, the user will be
asked whether or not to save the changes to the on-disk label.
+.It Cm R Op Ar part
+Resize a partition in an auto allocated label,
+compacting unused space between partitions with a higher offset.
+The last partition will be shrunk if needed.
+Works only for auto allocated labels with no spoofed partitions.
.It Cm r
Recalculate free space.
This command displays all the free areas on the disk and the total
diff --git a/sbin/disklabel/editor.c b/sbin/disklabel/editor.c
index 3a9a47a81b9..c45ef1322eb 100644
--- a/sbin/disklabel/editor.c
+++ b/sbin/disklabel/editor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: editor.c,v 1.226 2010/03/20 16:53:20 otto Exp $ */
+/* $OpenBSD: editor.c,v 1.227 2010/03/23 14:32:34 otto Exp $ */
/*
* Copyright (c) 1997-2000 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -113,6 +113,7 @@ const struct {
};
void edit_parms(struct disklabel *);
+void editor_resize(struct disklabel *, char *);
void editor_add(struct disklabel *, char *);
void editor_change(struct disklabel *, char *);
u_int64_t editor_countfree(struct disklabel *);
@@ -148,6 +149,7 @@ void display_edit(struct disklabel *, char, u_int64_t);
static u_int64_t starting_sector;
static u_int64_t ending_sector;
static int expert;
+static int spoofed;
/*
* Simple partition editor.
@@ -369,6 +371,15 @@ editor(struct disklabel *lp, int f)
/* NOTREACHED */
break;
+ case 'R':
+ if (aflag && !spoofed)
+ editor_resize(&label, arg);
+ else
+ fputs("Resize only implemented for auto "
+ "allocated labels without spoofed "
+ "partitions\n", stderr);
+ break;
+
case 'r': {
struct diskchunk *chunks;
int i;
@@ -512,6 +523,11 @@ editor_allocspace(struct disklabel *lp_org)
int i, j, lastalloc, index = 0, fragsize;
int64_t physmem;
+ spoofed = 0;
+ for (i = 0; i < MAXPARTITIONS; i++)
+ if (i != RAW_PART && DL_GETPSIZE(&lp_org->d_partitions[i]) != 0)
+ spoofed = 1;
+
physmem = getphysmem() / lp_org->d_secsize;
/* How big is the OpenBSD portion of the disk? */
@@ -653,6 +669,104 @@ cylinderalign:
}
/*
+ * Resize a partition, moving all subsequent partitions
+ */
+void
+editor_resize(struct disklabel *lp, char *p)
+{
+ struct disklabel label;
+ struct partition *pp, *prev;
+ daddr64_t secs, sz, off;
+#ifdef SUN_CYLCHECK
+ daddr64_t cylsecs;
+#endif
+ int partno, i;
+
+ label = *lp;
+
+ /* Change which partition? */
+ if (p == NULL) {
+ p = getstring("partition to resize",
+ "The letter of the partition to name, a - p.", NULL);
+ }
+ if (p == NULL) {
+ fputs("Command aborted\n", stderr);
+ return;
+ }
+ partno = p[0] - 'a';
+ if (partno < 0 || partno == RAW_PART || partno >= lp->d_npartitions) {
+ fprintf(stderr, "Partition must be between 'a' and '%c' "
+ "(excluding 'c').\n", 'a' + lp->d_npartitions - 1);
+ return;
+ }
+
+ pp = &label.d_partitions[partno];
+ sz = editor_countfree(lp);
+ secs = getuint(lp, "resize", "amount to grow (+) or shrink (-)",
+ 0, sz, 0, DO_CONVERSIONS);
+
+ if (secs == 0) {
+ fputs("Command aborted\n", stderr);
+ return;
+ }
+
+#ifdef SUN_CYLCHECK
+ cylsecs = lp->d_secpercyl;
+ if (secs > 0)
+ secs = ((secs + cylsecs - 1) / cylsecs) * cylsecs;
+ else
+ secs = ((secs - cylsecs + 1) / cylsecs) * cylsecs;
+#endif
+
+ sz = DL_GETPSIZE(pp);
+ if (sz == 0) {
+ fputs("No such parititon\n", stderr);
+ return;
+ }
+ if (DL_GETPOFFSET(pp) + sz + secs > ending_sector) {
+ fputs("Amount too big\n", stderr);
+ return;
+ }
+ if (sz + secs < 0) {
+ fputs("Amount too small\n", stderr);
+ return;
+ }
+
+ DL_SETPSIZE(pp, sz + secs);
+
+ /*
+ * Pack partitions above the resized partition, leaving unused
+ * partions alone.
+ */
+ prev = pp;
+ for (i = partno + 1; i < MAXPARTITIONS; i++) {
+ if (i == RAW_PART)
+ continue;
+ sz = DL_GETPSIZE(&label.d_partitions[i]);
+ if (sz == 0)
+ continue;
+
+ pp = &label.d_partitions[i];
+ off = DL_GETPOFFSET(prev) + DL_GETPSIZE(prev);
+
+ if (off < ending_sector) {
+ DL_SETPOFFSET(pp, off);
+ if (off + DL_GETPSIZE(pp) > ending_sector) {
+ DL_SETPSIZE(pp, ending_sector - off);
+ fprintf(stderr,
+ "Partition %c shrunk to make room\n",
+ i + 'a');
+ }
+ } else {
+ fputs("No room left for all partitions\n", stderr);
+ return;
+ }
+ prev = pp;
+ }
+ *lp = label;
+}
+
+/*
* Add a new partition.
*/
void
@@ -1637,6 +1751,11 @@ editor_help(char *arg)
"letter, you will be prompted for it; the next available letter will be the\n"
"default answer\n");
break;
+ case 'A':
+ puts(
+"The 'A' command clears the existing partitions and creates a new label\n"
+"based on the size of the disk\n");
+ break;
case 'b':
puts(
"The 'b' command is used to change the boundaries of the OpenBSD portion of\n"
@@ -1697,6 +1816,12 @@ editor_help(char *arg)
"not specify a partition letter, you will be prompted for one. This option\n"
"is only valid if disklabel was invoked with the -f flag.\n");
break;
+ case 'R':
+ puts(
+"Resize a a partition, compacting unused space between partitions\n"
+"with a higher offset. The last partition will be shrunk if needed.\n"
+"Works only for auto allocated labels with no spoofed partitions\n");
+ break;
case 'r':
puts(
"The 'r' command is used to recalculate and display details about\n"
@@ -1746,15 +1871,15 @@ editor_help(char *arg)
" ? [cmd] - show help n [part] - set mount point\n"
" A - auto partition all space p [unit] - print partitions\n"
" a [part] - add partition q - quit & save changes\n"
-" b - set OpenBSD boundaries s [path] - save label to file\n"
+" b - set OpenBSD boundaries R [part] - resize a partition\n"
" c [part] - change partition size r - display free space\n"
-" D - reset label to default U - undo all changes\n"
-" d [part] - delete partition u - undo last change\n"
-" e - edit drive parameters w - write label to disk\n"
-" g [d|u] - [d]isk or [u]ser geometry X - toggle expert mode\n"
-" l [unit] - print disk label header x - exit & lose changes\n"
-" M - disklabel(8) man page z - delete all partitions\n"
-" m [part] - modify partition\n"
+" D - reset label to default s [path] - save label to file\n"
+" d [part] - delete partition U - undo all changes\n"
+" e - edit drive parameters u - undo last change\n"
+" g [d|u] - [d]isk or [u]ser geometry w - write label to disk\n"
+" l [unit] - print disk label header X - toggle expert mode\n"
+" M - disklabel(8) man page x - exit & lose changes\n"
+" m [part] - modify partition z - delete all partitions\n"
"\n"
"Suffixes can be used to indicate units other than sectors:\n"
"\t'b' (bytes), 'k' (kilobytes), 'm' (megabytes), 'g' (gigabytes)\n"