forked from pool/s390-tools
Marcus Meissner
9b729e2acc
New package per "Factory first" policy. Please list me as bug owner and maintainer, if possible. OBS-URL: https://build.opensuse.org/request/show/459343 OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=1
267 lines
9.0 KiB
Diff
267 lines
9.0 KiB
Diff
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
|
|
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
|
|
|
|
Summary: dasdfmt: Add new formatting modes
|
|
Description: Introduce new formatting modes 'quick' and 'expand' to either
|
|
format an earlier formatted DASD that could potentially be
|
|
re-initialized very easily or format unformatted tracks at the
|
|
end of a device that was previously extended.
|
|
|
|
Also add the command line argument --check to provide a function
|
|
that checks a DASD volume for correct formatting.
|
|
Upstream-ID: -
|
|
Problem-ID: LS1501
|
|
|
|
Upstream-Description:
|
|
|
|
dasdfmt: Add expand format mode
|
|
|
|
If a DASD was extended, the format of the first part of the disk
|
|
can be assumed to be correct. Usually, a full format would be necessary
|
|
to ensure a fully functional disk. However, this would also format
|
|
the already formatted part resulting in the loss of the data stored in
|
|
that part.
|
|
|
|
Add an expand mode which will search for the start of the unformatted
|
|
area and begin formatting from there.
|
|
|
|
The mode is being specified by --mode=expand (or -M expand for short).
|
|
|
|
Furthermore:
|
|
- Add string array for the individual modes for output purposes
|
|
- Avoid writing labels when EXPAND mode is active since they can be
|
|
assumed to be correct
|
|
- Add man page description
|
|
|
|
|
|
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
|
|
---
|
|
dasdfmt/dasdfmt.8 | 7 +++
|
|
dasdfmt/dasdfmt.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++-----
|
|
dasdfmt/dasdfmt.h | 5 ++
|
|
3 files changed, 123 insertions(+), 9 deletions(-)
|
|
|
|
--- a/dasdfmt/dasdfmt.8
|
|
+++ b/dasdfmt/dasdfmt.8
|
|
@@ -118,6 +118,13 @@ Format the first two tracks and write la
|
|
this option if you are sure that the target DASD already contains a regular
|
|
format with the specified blocksize. A blocksize can optionally be specified
|
|
using \fB-b\fR (\fB--blocksize\fR).
|
|
+.IP expand
|
|
+Format all unformatted tracks at the end of the target DASD. This mode assumes
|
|
+that tracks at the beginning of the DASD volume have already been correctly
|
|
+formatted, while a consecutive set of tracks at the end are unformatted. You can
|
|
+use this mode to make added space available for Linux use after dynamically
|
|
+increasing the size of a DASD volume. A blocksize can optionally be specified
|
|
+using \fB-b\fR (\fB--blocksize\fR).
|
|
.RE
|
|
|
|
.TP
|
|
--- a/dasdfmt/dasdfmt.c
|
|
+++ b/dasdfmt/dasdfmt.c
|
|
@@ -88,7 +88,9 @@ static void exit_usage(int exitcode)
|
|
" <device> device node of the device to format\n"
|
|
" <mode> is either\n"
|
|
" 'full' to fully format the device (default)\n"
|
|
- " 'quick' to format only the first two tracks\n");
|
|
+ " 'quick' to format only the first two tracks\n"
|
|
+ " 'expand' to format only the unformatted end"
|
|
+ " of a device\n");
|
|
exit(exitcode);
|
|
}
|
|
|
|
@@ -791,8 +793,11 @@ static format_check_t check_track_format
|
|
if (errno == ENOTTY) {
|
|
ERRMSG("%s: Missing kernel support for format checking",
|
|
prog_name);
|
|
- if (!info->check)
|
|
+ if (mode == EXPAND) {
|
|
+ ERRMSG(". Mode 'expand' cannot be used");
|
|
+ } else if (!info->check) {
|
|
ERRMSG(" (--force to override)");
|
|
+ }
|
|
ERRMSG_EXIT(EXIT_FAILURE, ".\n");
|
|
}
|
|
ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n",
|
|
@@ -957,8 +962,7 @@ static void dasdfmt_print_info(dasdfmt_i
|
|
printf(" Compatible Disk Layout : %s\n",
|
|
(p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
|
|
printf(" Blocksize : %d\n", p->blksize);
|
|
- printf(" Mode : %s\n",
|
|
- (mode == FULL) ? "Full" : "Quick");
|
|
+ printf(" Mode : %s\n", mode_str[mode]);
|
|
|
|
if (info->testmode)
|
|
printf("Test mode active, omitting ioctl.\n");
|
|
@@ -1169,6 +1173,60 @@ static void dasdfmt_write_labels(dasdfmt
|
|
}
|
|
|
|
/*
|
|
+ * This function will search for the beginning of an unformatted area
|
|
+ * on the device. It checks selected tracks beforehand and makes sure
|
|
+ * that the device is formatted to a certain extent. Otherwise the
|
|
+ * process is terminated.
|
|
+ */
|
|
+static void dasdfmt_find_start(dasdfmt_info_t *info, unsigned int cylinders,
|
|
+ unsigned heads, format_data_t *format_params)
|
|
+{
|
|
+ format_check_t cdata;
|
|
+ unsigned int middle;
|
|
+ unsigned int left = 2;
|
|
+ unsigned int right = (cylinders * heads) - 1;
|
|
+ unsigned int first = left;
|
|
+
|
|
+ check_blocksize(info, format_params->blksize);
|
|
+
|
|
+ format_params->start_unit = 0;
|
|
+ format_params->stop_unit = 4;
|
|
+ cdata = check_track_format(info, format_params);
|
|
+
|
|
+ if (cdata.result) {
|
|
+ evaluate_format_error(info, &cdata, heads);
|
|
+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform a "
|
|
+ "clean format.\n");
|
|
+ }
|
|
+
|
|
+ printf("Expansion mode active. Searching for starting position...\n");
|
|
+
|
|
+ while (left <= right) {
|
|
+ /* new track number to look at */
|
|
+ middle = left + ((right - left) / 2);
|
|
+
|
|
+ format_params->start_unit = middle;
|
|
+ format_params->stop_unit = middle;
|
|
+ cdata = check_track_format(info, format_params);
|
|
+ if (cdata.blksize != format_params->blksize) {
|
|
+ first = middle;
|
|
+ right = middle - 1;
|
|
+ } else {
|
|
+ left = middle + 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (first == 2 && cdata.blksize == format_params->blksize)
|
|
+ ERRMSG_EXIT(EXIT_FAILURE,
|
|
+ "No unformatted part found, aborting.\n");
|
|
+
|
|
+ printf("Done. Unformatted part starts at track %d.\n", first);
|
|
+
|
|
+ /* return format_params with start_unit set to the correct value */
|
|
+ format_params->start_unit = first;
|
|
+}
|
|
+
|
|
+/*
|
|
* formats the disk cylinderwise
|
|
*/
|
|
static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
|
|
@@ -1239,6 +1297,40 @@ static void dasdfmt_prepare_and_format(d
|
|
}
|
|
|
|
/*
|
|
+ * This function will start the expand format process.
|
|
+ */
|
|
+static void dasdfmt_expand_format(dasdfmt_info_t *info, unsigned int cylinders,
|
|
+ unsigned int heads, format_data_t *p)
|
|
+{
|
|
+ if (!((info->withoutprompt) && (info->verbosity < 1)))
|
|
+ printf("Formatting the device. This may take a while "
|
|
+ "(get yourself a coffee).\n");
|
|
+
|
|
+ if (info->verbosity > 0)
|
|
+ printf("Detaching the device...\n");
|
|
+
|
|
+ if (ioctl(filedes, BIODASDDISABLE, p) != 0)
|
|
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
|
|
+ "BIODASDDISABLE failed. (%s)\n", prog_name,
|
|
+ strerror(errno));
|
|
+ disk_disabled = 1;
|
|
+
|
|
+ dasdfmt_format(info, cylinders, heads, p);
|
|
+
|
|
+ if (info->verbosity > 0)
|
|
+ printf("Formatting tracks complete...\n");
|
|
+
|
|
+ if (info->verbosity > 0)
|
|
+ printf("Re-accessing the device...\n");
|
|
+
|
|
+ if (ioctl(filedes, BIODASDENABLE, p) != 0)
|
|
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
|
|
+ "BIODASDENABLE failed. (%s)\n", prog_name,
|
|
+ strerror(errno));
|
|
+ disk_disabled = 0;
|
|
+}
|
|
+
|
|
+/*
|
|
* This function will only format the first two tracks of a DASD.
|
|
* The rest of the DASD is untouched and left as is.
|
|
*/
|
|
@@ -1310,6 +1402,10 @@ static void do_format_dasd(dasdfmt_info_
|
|
case QUICK: /* just the first two */
|
|
p->stop_unit = 1;
|
|
break;
|
|
+ case EXPAND: /* only the end of the disk */
|
|
+ dasdfmt_find_start(info, cylinders, heads, p);
|
|
+ p->stop_unit = (cylinders * heads) - 1;
|
|
+ break;
|
|
}
|
|
|
|
if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
|
|
@@ -1338,10 +1434,12 @@ static void do_format_dasd(dasdfmt_info_
|
|
|
|
if (!info->testmode) {
|
|
if (!info->withoutprompt) {
|
|
- printf("\n--->> ATTENTION! <<---\n");
|
|
- printf("All data of that device will be lost.\nType "
|
|
- "\"yes\" to continue, no will leave the disk "
|
|
- "untouched: ");
|
|
+ printf("\n");
|
|
+ if (mode != EXPAND)
|
|
+ printf("--->> ATTENTION! <<---\nAll data of "
|
|
+ "that device will be lost.\n");
|
|
+ printf("Type \"yes\" to continue, no will leave the "
|
|
+ "disk untouched: ");
|
|
if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
|
|
return;
|
|
if (strcasecmp(inp_buffer, "yes") &&
|
|
@@ -1359,12 +1457,14 @@ static void do_format_dasd(dasdfmt_info_
|
|
case QUICK:
|
|
dasdfmt_quick_format(info, cylinders, heads, p);
|
|
break;
|
|
+ case EXPAND:
|
|
+ dasdfmt_expand_format(info, cylinders, heads, p);
|
|
}
|
|
|
|
if (!info->yast_mode)
|
|
printf("Finished formatting the device.\n");
|
|
|
|
- if (!info->writenolabel)
|
|
+ if (!(info->writenolabel || mode == EXPAND))
|
|
dasdfmt_write_labels(info, vlabel, cylinders, heads);
|
|
|
|
if (!info->yast_mode)
|
|
@@ -1526,6 +1626,8 @@ int main(int argc, char *argv[])
|
|
mode = FULL;
|
|
else if (strcasecmp(optarg, "quick") == 0)
|
|
mode = QUICK;
|
|
+ else if (strcasecmp(optarg, "expand") == 0)
|
|
+ mode = EXPAND;
|
|
else
|
|
ERRMSG_EXIT(EXIT_FAILURE,
|
|
"%s: The specified mode '%s' is "
|
|
--- a/dasdfmt/dasdfmt.h
|
|
+++ b/dasdfmt/dasdfmt.h
|
|
@@ -150,8 +150,13 @@ struct dasd_eckd_characteristics {
|
|
typedef enum format_mode_t {
|
|
FULL, /* default mode */
|
|
QUICK, /* format only the first 2 tracks */
|
|
+ EXPAND, /* search for unformatted area and format only that part*/
|
|
} format_mode_t;
|
|
|
|
+static const char mode_str[3][10] = {
|
|
+ "Full", "Quick", "Expand"
|
|
+};
|
|
+
|
|
/*
|
|
* struct format_data_t
|
|
* represents all data necessary to format a dasd
|