SHA256
1
0
forked from pool/s390-tools
s390-tools/s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch
2017-02-21 11:14:26 +00:00

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