aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Haberland <stefan.haberland@de.ibm.com>2012-09-20 12:37:36 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-09-26 09:45:26 -0400
commit3bc9fef9cc1e4047c3a3c51d84cc1c5d2ef03cea (patch)
tree54a33b235bc5e19f2074fce702ddbcf73f8af6e3
parent72abaadf25f2bc6098740622e4ed526775b197f9 (diff)
s390/dasd: check count address during online setting
A common way to prepare a z/VM mini disk is to format the real device with a z/VM tool like CPFMTXA and then define a mini disk that excludes the first cylinder, i.e. the cylinder 0 of the virtual disk is located at cylinder 1 of the real device. The DASD device driver will recognize such a mini disk as formatted, as the uniform record layout on the disk matches that of an LDL formatted device. However, the cylinder value in the 'count' field of the ECKD records matches the geometry of the real device, and not that of the mini disk, so I/O requests will fail with 'record not found' errors. To make the mini disk usable, it needs to be formatted with a tool like dasdfmt. To enable tools like distribution installation tools to recognize this situation, the DASD device driver should report such a mini disk as 'not formatted'. To this end we need to extend the device recognition code to check not just for proper record sizes, but also for proper cylinder/head/record values. Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Reviewed-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/block/dasd_eckd.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index e1bb930124d..108332b44d9 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -139,6 +139,10 @@ dasd_eckd_set_online(struct ccw_device *cdev)
139static const int sizes_trk0[] = { 28, 148, 84 }; 139static const int sizes_trk0[] = { 28, 148, 84 };
140#define LABEL_SIZE 140 140#define LABEL_SIZE 140
141 141
142/* head and record addresses of count_area read in analysis ccw */
143static const int count_area_head[] = { 0, 0, 0, 0, 2 };
144static const int count_area_rec[] = { 1, 2, 3, 4, 1 };
145
142static inline unsigned int 146static inline unsigned int
143round_up_multiple(unsigned int no, unsigned int mult) 147round_up_multiple(unsigned int no, unsigned int mult)
144{ 148{
@@ -1939,7 +1943,10 @@ static int dasd_eckd_end_analysis(struct dasd_block *block)
1939 count_area = NULL; 1943 count_area = NULL;
1940 for (i = 0; i < 3; i++) { 1944 for (i = 0; i < 3; i++) {
1941 if (private->count_area[i].kl != 4 || 1945 if (private->count_area[i].kl != 4 ||
1942 private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4) { 1946 private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4 ||
1947 private->count_area[i].cyl != 0 ||
1948 private->count_area[i].head != count_area_head[i] ||
1949 private->count_area[i].record != count_area_rec[i]) {
1943 private->uses_cdl = 0; 1950 private->uses_cdl = 0;
1944 break; 1951 break;
1945 } 1952 }
@@ -1951,7 +1958,10 @@ static int dasd_eckd_end_analysis(struct dasd_block *block)
1951 for (i = 0; i < 5; i++) { 1958 for (i = 0; i < 5; i++) {
1952 if ((private->count_area[i].kl != 0) || 1959 if ((private->count_area[i].kl != 0) ||
1953 (private->count_area[i].dl != 1960 (private->count_area[i].dl !=
1954 private->count_area[0].dl)) 1961 private->count_area[0].dl) ||
1962 private->count_area[i].cyl != 0 ||
1963 private->count_area[i].head != count_area_head[i] ||
1964 private->count_area[i].record != count_area_rec[i])
1955 break; 1965 break;
1956 } 1966 }
1957 if (i == 5) 1967 if (i == 5)