Blame view

block/partitions/ibm.c 6.79 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
ef1597d52   Horst Hummel   [PATCH] s390: Rem...
2
   * File...........: linux/fs/partitions/ibm.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
   *                  Volker Sameske <sameske@de.ibm.com>
   * Bugreports.to..: <Linux390@de.ibm.com>
   * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
18
19
  #include <linux/buffer_head.h>
  #include <linux/hdreg.h>
  #include <linux/slab.h>
  #include <asm/dasd.h>
  #include <asm/ebcdic.h>
  #include <asm/uaccess.h>
  #include <asm/vtoc.h>
  
  #include "check.h"
  #include "ibm.h"
  
  /*
ef1597d52   Horst Hummel   [PATCH] s390: Rem...
20
   * compute the block number from a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
   * cyl-cyl-head-head structure
   */
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
23
  static sector_t
4cd5b9f6d   Peter Oberparleiter   [PATCH] s390: cle...
24
  cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) {
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
25
26
27
28
29
30
31
32
33
34
35
  
  	sector_t cyl;
  	__u16 head;
  
  	/*decode cylinder and heads for large volumes */
  	cyl = ptr->hh & 0xFFF0;
  	cyl <<= 12;
  	cyl |= ptr->cc;
  	head = ptr->hh & 0x000F;
  	return cyl * geo->heads * geo->sectors +
  	       head * geo->sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  /*
ef1597d52   Horst Hummel   [PATCH] s390: Rem...
38
   * compute the block number from a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
   * cyl-cyl-head-head-block structure
   */
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
41
  static sector_t
4cd5b9f6d   Peter Oberparleiter   [PATCH] s390: cle...
42
  cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
43
44
45
46
47
48
49
50
51
52
53
  
  	sector_t cyl;
  	__u16 head;
  
  	/*decode cylinder and heads for large volumes */
  	cyl = ptr->hh & 0xFFF0;
  	cyl <<= 12;
  	cyl |= ptr->cc;
  	head = ptr->hh & 0x000F;
  	return	cyl * geo->heads * geo->sectors +
  		head * geo->sectors +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
  		ptr->b;
  }
  
  /*
   */
1493bf217   Tejun Heo   block: use struct...
59
  int ibm_partition(struct parsed_partitions *state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  {
1493bf217   Tejun Heo   block: use struct...
61
  	struct block_device *bdev = state->bdev;
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
62
63
  	int blocksize, res;
  	loff_t i_size, offset, size, fmt_size;
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
64
  	dasd_information2_t *info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
  	struct hd_geometry *geo;
  	char type[5] = {0,};
  	char name[7] = {0,};
56dc6a88e   Peter Oberparleiter   [PATCH] s390: cms...
68
  	union label_t {
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
69
70
  		struct vtoc_volume_label_cdl vol;
  		struct vtoc_volume_label_ldl lnx;
56dc6a88e   Peter Oberparleiter   [PATCH] s390: cms...
71
72
  		struct vtoc_cms_label cms;
  	} *label;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
  	unsigned char *data;
  	Sector sect;
cffab6bc5   Peter Oberparleiter   [S390] dasd: use ...
75
  	sector_t labelsect;
9c867fbe0   Alexey Dobriyan   partitions: fix s...
76
  	char tmp[64];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77

57881dd9d   Suzuki K P   [PATCH] Fix check...
78
  	res = 0;
e1defc4ff   Martin K. Petersen   block: Do away wi...
79
  	blocksize = bdev_logical_block_size(bdev);
90f0094dc   Horst Hummel   [PATCH] s390: das...
80
  	if (blocksize <= 0)
57881dd9d   Suzuki K P   [PATCH] Fix check...
81
  		goto out_exit;
90f0094dc   Horst Hummel   [PATCH] s390: das...
82
83
  	i_size = i_size_read(bdev->bd_inode);
  	if (i_size == 0)
57881dd9d   Suzuki K P   [PATCH] Fix check...
84
  		goto out_exit;
90f0094dc   Horst Hummel   [PATCH] s390: das...
85

bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
86
87
  	info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
  	if (info == NULL)
57881dd9d   Suzuki K P   [PATCH] Fix check...
88
  		goto out_exit;
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
89
90
  	geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL);
  	if (geo == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  		goto out_nogeo;
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
92
93
  	label = kmalloc(sizeof(union label_t), GFP_KERNEL);
  	if (label == NULL)
56dc6a88e   Peter Oberparleiter   [PATCH] s390: cms...
94
  		goto out_nolab;
ef1597d52   Horst Hummel   [PATCH] s390: Rem...
95

bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
96
  	if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  	    ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
57881dd9d   Suzuki K P   [PATCH] Fix check...
98
  		goto out_freeall;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
  
  	/*
cffab6bc5   Peter Oberparleiter   [S390] dasd: use ...
101
102
103
104
105
106
107
108
109
110
  	 * Special case for FBA disks: label sector does not depend on
  	 * blocksize.
  	 */
  	if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) ||
  	    (info->cu_type == 0x3880 && info->dev_type == 0x3370))
  		labelsect = info->label_block;
  	else
  		labelsect = info->label_block * (blocksize >> 9);
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
  	 * Get volume label, extract name and type.
  	 */
cffab6bc5   Peter Oberparleiter   [S390] dasd: use ...
113
  	data = read_part_sector(state, labelsect, &sect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
  	if (data == NULL)
  		goto out_readerr;
56dc6a88e   Peter Oberparleiter   [PATCH] s390: cms...
116
  	memcpy(label, data, sizeof(union label_t));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  	put_dev_sector(sect);
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
118
119
120
121
122
123
124
  	if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
  		strncpy(type, label->vol.vollbl, 4);
  		strncpy(name, label->vol.volid, 6);
  	} else {
  		strncpy(type, label->lnx.vollbl, 4);
  		strncpy(name, label->lnx.volid, 6);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
  	EBCASC(type, 4);
  	EBCASC(name, 6);
57881dd9d   Suzuki K P   [PATCH] Fix check...
127
  	res = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  	/*
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
129
130
131
132
133
  	 * Three different formats: LDL, CDL and unformated disk
  	 *
  	 * identified by info->format
  	 *
  	 * unformated disks we do not have to care about
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  	 */
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
135
136
137
138
139
  	if (info->format == DASD_FORMAT_LDL) {
  		if (strncmp(type, "CMS1", 4) == 0) {
  			/*
  			 * VM style CMS1 labeled disk
  			 */
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
140
  			blocksize = label->cms.block_size;
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
141
  			if (label->cms.disk_offset != 0) {
9c867fbe0   Alexey Dobriyan   partitions: fix s...
142
143
  				snprintf(tmp, sizeof(tmp), "CMS1/%8s(MDSK):", name);
  				strlcat(state->pp_buf, tmp, PAGE_SIZE);
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
144
  				/* disk is reserved minidisk */
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
145
146
147
148
  				offset = label->cms.disk_offset;
  				size = (label->cms.block_count - 1)
  					* (blocksize >> 9);
  			} else {
9c867fbe0   Alexey Dobriyan   partitions: fix s...
149
150
  				snprintf(tmp, sizeof(tmp), "CMS1/%8s:", name);
  				strlcat(state->pp_buf, tmp, PAGE_SIZE);
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
151
  				offset = (info->label_block + 1);
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
152
153
  				size = label->cms.block_count
  					* (blocksize >> 9);
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
154
  			}
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
155
156
  			put_partition(state, 1, offset*(blocksize >> 9),
  				      size-offset*(blocksize >> 9));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  		} else {
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
158
  			if (strncmp(type, "LNX1", 4) == 0) {
9c867fbe0   Alexey Dobriyan   partitions: fix s...
159
160
  				snprintf(tmp, sizeof(tmp), "LNX1/%8s:", name);
  				strlcat(state->pp_buf, tmp, PAGE_SIZE);
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  				if (label->lnx.ldl_version == 0xf2) {
  					fmt_size = label->lnx.formatted_blocks
  						* (blocksize >> 9);
  				} else if (!strcmp(info->type, "ECKD")) {
  					/* formated w/o large volume support */
  					fmt_size = geo->cylinders * geo->heads
  					      * geo->sectors * (blocksize >> 9);
  				} else {
  					/* old label and no usable disk geometry
  					 * (e.g. DIAG) */
  					fmt_size = i_size >> 9;
  				}
  				size = i_size >> 9;
  				if (fmt_size < size)
  					size = fmt_size;
  				offset = (info->label_block + 1);
  			} else {
  				/* unlabeled disk */
2041f657a   Heiko Carstens   [S390] partitions...
179
  				strlcat(state->pp_buf, "(nonl)", PAGE_SIZE);
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
180
181
182
183
  				size = i_size >> 9;
  				offset = (info->label_block + 1);
  			}
  			put_partition(state, 1, offset*(blocksize >> 9),
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
184
  				      size-offset*(blocksize >> 9));
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
185
  		}
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
186
  	} else if (info->format == DASD_FORMAT_CDL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  		/*
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
188
  		 * New style CDL formatted disk
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  		 */
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
190
  		sector_t blk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  		int counter;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  		/*
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
193
194
  		 * check if VOL1 label is available
  		 * if not, something is wrong, skipping partition detection
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  		 */
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
196
  		if (strncmp(type, "VOL1",  4) == 0) {
9c867fbe0   Alexey Dobriyan   partitions: fix s...
197
198
  			snprintf(tmp, sizeof(tmp), "VOL1/%8s:", name);
  			strlcat(state->pp_buf, tmp, PAGE_SIZE);
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
199
200
201
202
203
204
  			/*
  			 * get block number and read then go through format1
  			 * labels
  			 */
  			blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
  			counter = 0;
1493bf217   Tejun Heo   block: use struct...
205
206
  			data = read_part_sector(state, blk * (blocksize/512),
  						&sect);
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
207
208
209
210
211
212
213
214
215
216
  			while (data != NULL) {
  				struct vtoc_format1_label f1;
  
  				memcpy(&f1, data,
  				       sizeof(struct vtoc_format1_label));
  				put_dev_sector(sect);
  
  				/* skip FMT4 / FMT5 / FMT7 labels */
  				if (f1.DS1FMTID == _ascebc['4']
  				    || f1.DS1FMTID == _ascebc['5']
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
217
218
  				    || f1.DS1FMTID == _ascebc['7']
  				    || f1.DS1FMTID == _ascebc['9']) {
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
219
  					blk++;
1493bf217   Tejun Heo   block: use struct...
220
221
  					data = read_part_sector(state,
  						blk * (blocksize/512), &sect);
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
222
223
  					continue;
  				}
b44b0ab3b   Stefan Weinhuber   [S390] dasd: add ...
224
225
226
  				/* only FMT1 and 8 labels valid at this point */
  				if (f1.DS1FMTID != _ascebc['1'] &&
  				    f1.DS1FMTID != _ascebc['8'])
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
227
228
229
230
231
232
233
234
235
236
237
238
239
  					break;
  
  				/* OK, we got valid partition data */
  				offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
  				size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
  					offset + geo->sectors;
  				if (counter >= state->limit)
  					break;
  				put_partition(state, counter + 1,
  					      offset * (blocksize >> 9),
  					      size * (blocksize >> 9));
  				counter++;
  				blk++;
1493bf217   Tejun Heo   block: use struct...
240
241
  				data = read_part_sector(state,
  						blk * (blocksize/512), &sect);
bf1a95a22   Stefan Haberland   [S390] fixed cdl-...
242
243
244
245
246
247
248
249
  			}
  
  			if (!data)
  				/* Are we not supposed to report this ? */
  				goto out_readerr;
  		} else
  			printk(KERN_WARNING "Warning, expected Label VOL1 not "
  			       "found, treating as CDL formated Disk");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  	}
9c867fbe0   Alexey Dobriyan   partitions: fix s...
251
252
  	strlcat(state->pp_buf, "
  ", PAGE_SIZE);
57881dd9d   Suzuki K P   [PATCH] Fix check...
253
  	goto out_freeall;
ef1597d52   Horst Hummel   [PATCH] s390: Rem...
254

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  out_readerr:
57881dd9d   Suzuki K P   [PATCH] Fix check...
256
257
  	res = -1;
  out_freeall:
56dc6a88e   Peter Oberparleiter   [PATCH] s390: cms...
258
259
  	kfree(label);
  out_nolab:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
  	kfree(geo);
  out_nogeo:
  	kfree(info);
57881dd9d   Suzuki K P   [PATCH] Fix check...
263
264
  out_exit:
  	return res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  }