File s390-tools-fdasd-0001-add-f-flag.patch of Package s390-tools
From a7d2e82f12bfa5cd15c703fcdcb695d8fad3082e Mon Sep 17 00:00:00 2001
From: Alexander Graf <agraf@suse.de>
Date: Tue, 19 Apr 2011 18:29:04 +0200
Subject: [PATCH] fdasd: add -f flag
This patch adds a force flag to fdasd, allowing it to work on
non-dasd disks as well.
Signed-off-by: Alexander Graf <agraf@suse.de>
Acked-by: John Jolly <jjolly@suse.de>
---
fdasd/fdasd.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
fdasd/fdasd.h | 3 +-
2 files changed, 72 insertions(+), 12 deletions(-)
Index: s390-tools-1.15.0/fdasd/fdasd.c
===================================================================
--- s390-tools-1.15.0.orig/fdasd/fdasd.c
+++ s390-tools-1.15.0/fdasd/fdasd.c
@@ -16,6 +16,8 @@
struct hd_geometry geo;
char line_buffer[LINE_LENGTH];
char *line_ptr = line_buffer;
+int force;
+int fake_dasd;
/* Full tool name */
static const char tool_name[] = "fdasd: zSeries DASD partitioning program";
@@ -98,6 +100,29 @@ static void get_addr_of_highest_f1_f8_la
vtoc_set_cchhb(addr, VTOC_START_CC, VTOC_START_HH, record);
}
+static inline off_t get_cyl(int fd)
+{
+ struct stat stat;
+ struct hd_geometry geo;
+ int r;
+ off_t size;
+
+ r = ioctl(fd, HDIO_GETGEO, &geo);
+ if (!r) {
+ /* real disk */
+ size = geo.heads * geo.sectors * geo.cylinders;
+ } else {
+ /* image file */
+ r = fstat(fd, &stat);
+ if (!r)
+ size = stat.st_size / 4096;
+ else
+ size = 0x1000;
+ }
+
+ return size / 15 / 12;
+}
+
/*
* Check for valid volume serial characters (max. 6) - remove invalid.
* If volser is empty, fill with default volser.
@@ -353,7 +378,8 @@ fdasd_usage (void)
"using information\n"
" found in CONFIGFILE\n"
"-i, --volser Print volume serial\n"
- "-p, --table Print partition table\n");
+ "-p, --table Print partition table\n"
+ "-f, --force Force creation on non-DASD device\n");
}
@@ -514,6 +540,9 @@ fdasd_parse_options (fdasd_anchor_t *anc
case 'k':
anc->keep_volser++;
break;
+ case 'f':
+ force = 1;
+ break;
case -1:
/* End of options string - start of devices list */
break;
@@ -772,7 +801,7 @@ fdasd_verify_device (fdasd_anchor_t *anc
fdasd_error(anc, device_verification_failed, err_str);
}
- if (!(S_ISBLK (dst.st_mode))) {
+ if (!(S_ISBLK (dst.st_mode)) && !force) {
snprintf(err_str, ERROR_STRING_SIZE,
"Device '%s' (%d/%d) is not a block device\n", name,
(unsigned short) major(dst.st_rdev),
@@ -1040,6 +1069,7 @@ fdasd_get_volser(fdasd_anchor_t *anc, ch
int fd;
volume_label_t vlabel;
char err_str[ERROR_STRING_SIZE];
+ int r;
if ((fd = open(devname, O_RDONLY)) == -1) {
snprintf(err_str, ERROR_STRING_SIZE,
@@ -1048,13 +1078,23 @@ fdasd_get_volser(fdasd_anchor_t *anc, ch
fdasd_error(anc, unable_to_open_disk, err_str);
}
- if (ioctl(fd, BIODASDINFO, &dasd_info) != 0) {
+ r = ioctl(fd, BIODASDINFO, &dasd_info);
+ if ((r != 0) && force) {
+ fake_dasd = 1;
+ memset(&dasd_info, 0, sizeof(dasd_info));
+ memcpy(dasd_info.type, "ECKD", 4);
+ dasd_info.cu_type = 0;
+ dasd_info.label_block = 2;
+ } else if ((r != 0)) {
close(fd);
fdasd_error(anc, unable_to_ioctl,
"Could not retrieve disk information.");
}
- if (ioctl(fd, BLKSSZGET, &blksize) != 0) {
+ r = ioctl(fd, BLKSSZGET, &blksize);
+ if ((r != 0) && fake_dasd) {
+ blksize = 4096;
+ } else if (r != 0) {
close(fd);
fdasd_error(anc, unable_to_ioctl,
"Could not retrieve blocksize information.");
@@ -1988,7 +2028,7 @@ fdasd_check_disk_access (fdasd_anchor_t
{
char err_str[ERROR_STRING_SIZE];
format1_label_t f1;
- int fd, pos, ro;
+ int fd, pos, ro = 0;
if ((fd = open(options.device, O_RDONLY)) == -1) {
snprintf(err_str, ERROR_STRING_SIZE,
@@ -2021,7 +2061,7 @@ fdasd_check_disk_access (fdasd_anchor_t
fdasd_error(anc, unable_to_seek_disk, err_str);
}
- if (ioctl(fd, BLKROGET, &ro) != 0) {
+ if (!fake_dasd && ioctl(fd, BLKROGET, &ro) != 0) {
snprintf(err_str, ERROR_STRING_SIZE,
"Could not get read-only status for device '%s'.",
options.device);
@@ -2042,7 +2082,7 @@ fdasd_check_disk_access (fdasd_anchor_t
static void
fdasd_get_geometry (fdasd_anchor_t *anc)
{
- int fd, blksize = 0;
+ int fd, blksize = 0, r;
dasd_information_t dasd_info;
char err_str[ERROR_STRING_SIZE];
struct dasd_eckd_characteristics *characteristics;
@@ -2054,21 +2094,36 @@ fdasd_get_geometry (fdasd_anchor_t *anc)
fdasd_error(anc, unable_to_open_disk, err_str);
}
- if (ioctl(fd, HDIO_GETGEO, &geo) != 0) {
+ r = ioctl(fd, HDIO_GETGEO, &geo);
+ if (force) {
+ fake_dasd = 1;
+ geo.heads = 15;
+ geo.sectors = 12;
+ geo.cylinders = get_cyl(fd);
+ } else if (r != 0) {
close(fd);
fdasd_error(anc, unable_to_ioctl,
"Could not retrieve disk geometry information.");
}
- if (ioctl(fd, BLKSSZGET, &blksize) != 0) {
+ if (fake_dasd) {
+ blksize = 4096;
+ } else if (ioctl(fd, BLKSSZGET, &blksize) != 0) {
close(fd);
fdasd_error(anc, unable_to_ioctl,
"Could not retrieve blocksize information.");
}
/* get disk type */
- if (ioctl(fd, BIODASDINFO, &dasd_info) != 0) {
- close(fd);
+ r = ioctl(fd, BIODASDINFO, &dasd_info);
+ if ((r != 0) && force) {
+ fake_dasd = 1;
+ memset(&dasd_info, 0, sizeof(dasd_info));
+ memcpy(dasd_info.type, "ECKD", 4);
+ dasd_info.cu_type = 0;
+ dasd_info.label_block = 2;
+ } else if ((r != 0)) {
+ close(fd);
fdasd_error(anc, unable_to_ioctl,
"Could not retrieve disk information.");
}
@@ -2081,6 +2136,10 @@ fdasd_get_geometry (fdasd_anchor_t *anc)
else
anc->hw_cylinders = characteristics->no_cyl;
+ if (fake_dasd) {
+ anc->hw_cylinders = geo.cylinders;
+ }
+
close(fd);
if (strncmp(dasd_info.type, "ECKD", 4) != 0) {
Index: s390-tools-1.15.0/fdasd/fdasd.h
===================================================================
--- s390-tools-1.15.0.orig/fdasd/fdasd.h
+++ s390-tools-1.15.0/fdasd/fdasd.h
@@ -166,11 +166,12 @@ static struct option fdasd_long_options[
{ "table", no_argument, NULL, 'p'},
{ "volser", no_argument, NULL, 'i'},
{ "keep_volser", no_argument, NULL, 'k'},
+ { "force", no_argument, NULL, 'f'},
{ 0, 0, 0, 0 }
};
/* Command line option abbreviations */
-static const char option_string[] = "vasrl:c:hpik";
+static const char option_string[] = "vasrl:c:hpikf";
struct fdasd_options {
char *device;