diff options
Diffstat (limited to 'block/partitions/ibm.c')
-rw-r--r-- | block/partitions/ibm.c | 455 |
1 files changed, 272 insertions, 183 deletions
diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c index 1104acac780b..47a61474e795 100644 --- a/block/partitions/ibm.c +++ b/block/partitions/ibm.c | |||
@@ -1,9 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/fs/partitions/ibm.c | ||
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 2 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Volker Sameske <sameske@de.ibm.com> | 3 | * Volker Sameske <sameske@de.ibm.com> |
5 | * Bugreports.to..: <Linux390@de.ibm.com> | 4 | * Bugreports.to..: <Linux390@de.ibm.com> |
6 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 | 5 | * Copyright IBM Corp. 1999, 2012 |
7 | */ | 6 | */ |
8 | 7 | ||
9 | #include <linux/buffer_head.h> | 8 | #include <linux/buffer_head.h> |
@@ -17,17 +16,23 @@ | |||
17 | #include "check.h" | 16 | #include "check.h" |
18 | #include "ibm.h" | 17 | #include "ibm.h" |
19 | 18 | ||
19 | |||
20 | union label_t { | ||
21 | struct vtoc_volume_label_cdl vol; | ||
22 | struct vtoc_volume_label_ldl lnx; | ||
23 | struct vtoc_cms_label cms; | ||
24 | }; | ||
25 | |||
20 | /* | 26 | /* |
21 | * compute the block number from a | 27 | * compute the block number from a |
22 | * cyl-cyl-head-head structure | 28 | * cyl-cyl-head-head structure |
23 | */ | 29 | */ |
24 | static sector_t | 30 | static sector_t cchh2blk(struct vtoc_cchh *ptr, struct hd_geometry *geo) |
25 | cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { | 31 | { |
26 | |||
27 | sector_t cyl; | 32 | sector_t cyl; |
28 | __u16 head; | 33 | __u16 head; |
29 | 34 | ||
30 | /*decode cylinder and heads for large volumes */ | 35 | /* decode cylinder and heads for large volumes */ |
31 | cyl = ptr->hh & 0xFFF0; | 36 | cyl = ptr->hh & 0xFFF0; |
32 | cyl <<= 12; | 37 | cyl <<= 12; |
33 | cyl |= ptr->cc; | 38 | cyl |= ptr->cc; |
@@ -40,13 +45,12 @@ cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { | |||
40 | * compute the block number from a | 45 | * compute the block number from a |
41 | * cyl-cyl-head-head-block structure | 46 | * cyl-cyl-head-head-block structure |
42 | */ | 47 | */ |
43 | static sector_t | 48 | static sector_t cchhb2blk(struct vtoc_cchhb *ptr, struct hd_geometry *geo) |
44 | cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { | 49 | { |
45 | |||
46 | sector_t cyl; | 50 | sector_t cyl; |
47 | __u16 head; | 51 | __u16 head; |
48 | 52 | ||
49 | /*decode cylinder and heads for large volumes */ | 53 | /* decode cylinder and heads for large volumes */ |
50 | cyl = ptr->hh & 0xFFF0; | 54 | cyl = ptr->hh & 0xFFF0; |
51 | cyl <<= 12; | 55 | cyl <<= 12; |
52 | cyl |= ptr->cc; | 56 | cyl |= ptr->cc; |
@@ -56,26 +60,243 @@ cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { | |||
56 | ptr->b; | 60 | ptr->b; |
57 | } | 61 | } |
58 | 62 | ||
63 | static int find_label(struct parsed_partitions *state, | ||
64 | dasd_information2_t *info, | ||
65 | struct hd_geometry *geo, | ||
66 | int blocksize, | ||
67 | sector_t *labelsect, | ||
68 | char name[], | ||
69 | char type[], | ||
70 | union label_t *label) | ||
71 | { | ||
72 | Sector sect; | ||
73 | unsigned char *data; | ||
74 | sector_t testsect[3]; | ||
75 | unsigned char temp[5]; | ||
76 | int found = 0; | ||
77 | int i, testcount; | ||
78 | |||
79 | /* There a three places where we may find a valid label: | ||
80 | * - on an ECKD disk it's block 2 | ||
81 | * - on an FBA disk it's block 1 | ||
82 | * - on an CMS formatted FBA disk it is sector 1, even if the block size | ||
83 | * is larger than 512 bytes (possible if the DIAG discipline is used) | ||
84 | * If we have a valid info structure, then we know exactly which case we | ||
85 | * have, otherwise we just search through all possebilities. | ||
86 | */ | ||
87 | if (info) { | ||
88 | if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) || | ||
89 | (info->cu_type == 0x3880 && info->dev_type == 0x3370)) | ||
90 | testsect[0] = info->label_block; | ||
91 | else | ||
92 | testsect[0] = info->label_block * (blocksize >> 9); | ||
93 | testcount = 1; | ||
94 | } else { | ||
95 | testsect[0] = 1; | ||
96 | testsect[1] = (blocksize >> 9); | ||
97 | testsect[2] = 2 * (blocksize >> 9); | ||
98 | testcount = 3; | ||
99 | } | ||
100 | for (i = 0; i < testcount; ++i) { | ||
101 | data = read_part_sector(state, testsect[i], §); | ||
102 | if (data == NULL) | ||
103 | continue; | ||
104 | memcpy(label, data, sizeof(*label)); | ||
105 | memcpy(temp, data, 4); | ||
106 | temp[4] = 0; | ||
107 | EBCASC(temp, 4); | ||
108 | put_dev_sector(sect); | ||
109 | if (!strcmp(temp, "VOL1") || | ||
110 | !strcmp(temp, "LNX1") || | ||
111 | !strcmp(temp, "CMS1")) { | ||
112 | if (!strcmp(temp, "VOL1")) { | ||
113 | strncpy(type, label->vol.vollbl, 4); | ||
114 | strncpy(name, label->vol.volid, 6); | ||
115 | } else { | ||
116 | strncpy(type, label->lnx.vollbl, 4); | ||
117 | strncpy(name, label->lnx.volid, 6); | ||
118 | } | ||
119 | EBCASC(type, 4); | ||
120 | EBCASC(name, 6); | ||
121 | *labelsect = testsect[i]; | ||
122 | found = 1; | ||
123 | break; | ||
124 | } | ||
125 | } | ||
126 | if (!found) | ||
127 | memset(label, 0, sizeof(*label)); | ||
128 | |||
129 | return found; | ||
130 | } | ||
131 | |||
132 | static int find_vol1_partitions(struct parsed_partitions *state, | ||
133 | struct hd_geometry *geo, | ||
134 | int blocksize, | ||
135 | char name[], | ||
136 | union label_t *label) | ||
137 | { | ||
138 | sector_t blk; | ||
139 | int counter; | ||
140 | char tmp[64]; | ||
141 | Sector sect; | ||
142 | unsigned char *data; | ||
143 | loff_t offset, size; | ||
144 | struct vtoc_format1_label f1; | ||
145 | int secperblk; | ||
146 | |||
147 | snprintf(tmp, sizeof(tmp), "VOL1/%8s:", name); | ||
148 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
149 | /* | ||
150 | * get start of VTOC from the disk label and then search for format1 | ||
151 | * and format8 labels | ||
152 | */ | ||
153 | secperblk = blocksize >> 9; | ||
154 | blk = cchhb2blk(&label->vol.vtoc, geo) + 1; | ||
155 | counter = 0; | ||
156 | data = read_part_sector(state, blk * secperblk, §); | ||
157 | while (data != NULL) { | ||
158 | memcpy(&f1, data, sizeof(struct vtoc_format1_label)); | ||
159 | put_dev_sector(sect); | ||
160 | /* skip FMT4 / FMT5 / FMT7 labels */ | ||
161 | if (f1.DS1FMTID == _ascebc['4'] | ||
162 | || f1.DS1FMTID == _ascebc['5'] | ||
163 | || f1.DS1FMTID == _ascebc['7'] | ||
164 | || f1.DS1FMTID == _ascebc['9']) { | ||
165 | blk++; | ||
166 | data = read_part_sector(state, blk * secperblk, §); | ||
167 | continue; | ||
168 | } | ||
169 | /* only FMT1 and 8 labels valid at this point */ | ||
170 | if (f1.DS1FMTID != _ascebc['1'] && | ||
171 | f1.DS1FMTID != _ascebc['8']) | ||
172 | break; | ||
173 | /* OK, we got valid partition data */ | ||
174 | offset = cchh2blk(&f1.DS1EXT1.llimit, geo); | ||
175 | size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - | ||
176 | offset + geo->sectors; | ||
177 | offset *= secperblk; | ||
178 | size *= secperblk; | ||
179 | if (counter >= state->limit) | ||
180 | break; | ||
181 | put_partition(state, counter + 1, offset, size); | ||
182 | counter++; | ||
183 | blk++; | ||
184 | data = read_part_sector(state, blk * secperblk, §); | ||
185 | } | ||
186 | strlcat(state->pp_buf, "\n", PAGE_SIZE); | ||
187 | |||
188 | if (!data) | ||
189 | return -1; | ||
190 | |||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | static int find_lnx1_partitions(struct parsed_partitions *state, | ||
195 | struct hd_geometry *geo, | ||
196 | int blocksize, | ||
197 | char name[], | ||
198 | union label_t *label, | ||
199 | sector_t labelsect, | ||
200 | loff_t i_size, | ||
201 | dasd_information2_t *info) | ||
202 | { | ||
203 | loff_t offset, geo_size, size; | ||
204 | char tmp[64]; | ||
205 | int secperblk; | ||
206 | |||
207 | snprintf(tmp, sizeof(tmp), "LNX1/%8s:", name); | ||
208 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
209 | secperblk = blocksize >> 9; | ||
210 | if (label->lnx.ldl_version == 0xf2) { | ||
211 | size = label->lnx.formatted_blocks * secperblk; | ||
212 | } else { | ||
213 | /* | ||
214 | * Formated w/o large volume support. If the sanity check | ||
215 | * 'size based on geo == size based on i_size' is true, then | ||
216 | * we can safely assume that we know the formatted size of | ||
217 | * the disk, otherwise we need additional information | ||
218 | * that we can only get from a real DASD device. | ||
219 | */ | ||
220 | geo_size = geo->cylinders * geo->heads | ||
221 | * geo->sectors * secperblk; | ||
222 | size = i_size >> 9; | ||
223 | if (size != geo_size) { | ||
224 | if (!info) { | ||
225 | strlcat(state->pp_buf, "\n", PAGE_SIZE); | ||
226 | return 1; | ||
227 | } | ||
228 | if (!strcmp(info->type, "ECKD")) | ||
229 | if (geo_size < size) | ||
230 | size = geo_size; | ||
231 | /* else keep size based on i_size */ | ||
232 | } | ||
233 | } | ||
234 | /* first and only partition starts in the first block after the label */ | ||
235 | offset = labelsect + secperblk; | ||
236 | put_partition(state, 1, offset, size - offset); | ||
237 | strlcat(state->pp_buf, "\n", PAGE_SIZE); | ||
238 | return 1; | ||
239 | } | ||
240 | |||
241 | static int find_cms1_partitions(struct parsed_partitions *state, | ||
242 | struct hd_geometry *geo, | ||
243 | int blocksize, | ||
244 | char name[], | ||
245 | union label_t *label, | ||
246 | sector_t labelsect) | ||
247 | { | ||
248 | loff_t offset, size; | ||
249 | char tmp[64]; | ||
250 | int secperblk; | ||
251 | |||
252 | /* | ||
253 | * VM style CMS1 labeled disk | ||
254 | */ | ||
255 | blocksize = label->cms.block_size; | ||
256 | secperblk = blocksize >> 9; | ||
257 | if (label->cms.disk_offset != 0) { | ||
258 | snprintf(tmp, sizeof(tmp), "CMS1/%8s(MDSK):", name); | ||
259 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
260 | /* disk is reserved minidisk */ | ||
261 | offset = label->cms.disk_offset * secperblk; | ||
262 | size = (label->cms.block_count - 1) * secperblk; | ||
263 | } else { | ||
264 | snprintf(tmp, sizeof(tmp), "CMS1/%8s:", name); | ||
265 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
266 | /* | ||
267 | * Special case for FBA devices: | ||
268 | * If an FBA device is CMS formatted with blocksize > 512 byte | ||
269 | * and the DIAG discipline is used, then the CMS label is found | ||
270 | * in sector 1 instead of block 1. However, the partition is | ||
271 | * still supposed to start in block 2. | ||
272 | */ | ||
273 | if (labelsect == 1) | ||
274 | offset = 2 * secperblk; | ||
275 | else | ||
276 | offset = labelsect + secperblk; | ||
277 | size = label->cms.block_count * secperblk; | ||
278 | } | ||
279 | |||
280 | put_partition(state, 1, offset, size-offset); | ||
281 | strlcat(state->pp_buf, "\n", PAGE_SIZE); | ||
282 | return 1; | ||
283 | } | ||
284 | |||
285 | |||
59 | /* | 286 | /* |
287 | * This is the main function, called by check.c | ||
60 | */ | 288 | */ |
61 | int ibm_partition(struct parsed_partitions *state) | 289 | int ibm_partition(struct parsed_partitions *state) |
62 | { | 290 | { |
63 | struct block_device *bdev = state->bdev; | 291 | struct block_device *bdev = state->bdev; |
64 | int blocksize, res; | 292 | int blocksize, res; |
65 | loff_t i_size, offset, size, fmt_size; | 293 | loff_t i_size, offset, size; |
66 | dasd_information2_t *info; | 294 | dasd_information2_t *info; |
67 | struct hd_geometry *geo; | 295 | struct hd_geometry *geo; |
68 | char type[5] = {0,}; | 296 | char type[5] = {0,}; |
69 | char name[7] = {0,}; | 297 | char name[7] = {0,}; |
70 | union label_t { | ||
71 | struct vtoc_volume_label_cdl vol; | ||
72 | struct vtoc_volume_label_ldl lnx; | ||
73 | struct vtoc_cms_label cms; | ||
74 | } *label; | ||
75 | unsigned char *data; | ||
76 | Sector sect; | ||
77 | sector_t labelsect; | 298 | sector_t labelsect; |
78 | char tmp[64]; | 299 | union label_t *label; |
79 | 300 | ||
80 | res = 0; | 301 | res = 0; |
81 | blocksize = bdev_logical_block_size(bdev); | 302 | blocksize = bdev_logical_block_size(bdev); |
@@ -84,7 +305,6 @@ int ibm_partition(struct parsed_partitions *state) | |||
84 | i_size = i_size_read(bdev->bd_inode); | 305 | i_size = i_size_read(bdev->bd_inode); |
85 | if (i_size == 0) | 306 | if (i_size == 0) |
86 | goto out_exit; | 307 | goto out_exit; |
87 | |||
88 | info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); | 308 | info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); |
89 | if (info == NULL) | 309 | if (info == NULL) |
90 | goto out_exit; | 310 | goto out_exit; |
@@ -94,176 +314,45 @@ int ibm_partition(struct parsed_partitions *state) | |||
94 | label = kmalloc(sizeof(union label_t), GFP_KERNEL); | 314 | label = kmalloc(sizeof(union label_t), GFP_KERNEL); |
95 | if (label == NULL) | 315 | if (label == NULL) |
96 | goto out_nolab; | 316 | goto out_nolab; |
97 | 317 | if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) | |
98 | if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 || | ||
99 | ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) | ||
100 | goto out_freeall; | 318 | goto out_freeall; |
101 | 319 | if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0) { | |
102 | /* | 320 | kfree(info); |
103 | * Special case for FBA disks: label sector does not depend on | 321 | info = NULL; |
104 | * blocksize. | ||
105 | */ | ||
106 | if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) || | ||
107 | (info->cu_type == 0x3880 && info->dev_type == 0x3370)) | ||
108 | labelsect = info->label_block; | ||
109 | else | ||
110 | labelsect = info->label_block * (blocksize >> 9); | ||
111 | |||
112 | /* | ||
113 | * Get volume label, extract name and type. | ||
114 | */ | ||
115 | data = read_part_sector(state, labelsect, §); | ||
116 | if (data == NULL) | ||
117 | goto out_readerr; | ||
118 | |||
119 | memcpy(label, data, sizeof(union label_t)); | ||
120 | put_dev_sector(sect); | ||
121 | |||
122 | if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { | ||
123 | strncpy(type, label->vol.vollbl, 4); | ||
124 | strncpy(name, label->vol.volid, 6); | ||
125 | } else { | ||
126 | strncpy(type, label->lnx.vollbl, 4); | ||
127 | strncpy(name, label->lnx.volid, 6); | ||
128 | } | 322 | } |
129 | EBCASC(type, 4); | ||
130 | EBCASC(name, 6); | ||
131 | |||
132 | res = 1; | ||
133 | 323 | ||
134 | /* | 324 | if (find_label(state, info, geo, blocksize, &labelsect, name, type, |
135 | * Three different formats: LDL, CDL and unformated disk | 325 | label)) { |
136 | * | 326 | if (!strncmp(type, "VOL1", 4)) { |
137 | * identified by info->format | 327 | res = find_vol1_partitions(state, geo, blocksize, name, |
138 | * | 328 | label); |
139 | * unformated disks we do not have to care about | 329 | } else if (!strncmp(type, "LNX1", 4)) { |
140 | */ | 330 | res = find_lnx1_partitions(state, geo, blocksize, name, |
141 | if (info->format == DASD_FORMAT_LDL) { | 331 | label, labelsect, i_size, |
142 | if (strncmp(type, "CMS1", 4) == 0) { | 332 | info); |
143 | /* | 333 | } else if (!strncmp(type, "CMS1", 4)) { |
144 | * VM style CMS1 labeled disk | 334 | res = find_cms1_partitions(state, geo, blocksize, name, |
145 | */ | 335 | label, labelsect); |
146 | blocksize = label->cms.block_size; | ||
147 | if (label->cms.disk_offset != 0) { | ||
148 | snprintf(tmp, sizeof(tmp), "CMS1/%8s(MDSK):", name); | ||
149 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
150 | /* disk is reserved minidisk */ | ||
151 | offset = label->cms.disk_offset; | ||
152 | size = (label->cms.block_count - 1) | ||
153 | * (blocksize >> 9); | ||
154 | } else { | ||
155 | snprintf(tmp, sizeof(tmp), "CMS1/%8s:", name); | ||
156 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
157 | offset = (info->label_block + 1); | ||
158 | size = label->cms.block_count | ||
159 | * (blocksize >> 9); | ||
160 | } | ||
161 | put_partition(state, 1, offset*(blocksize >> 9), | ||
162 | size-offset*(blocksize >> 9)); | ||
163 | } else { | ||
164 | if (strncmp(type, "LNX1", 4) == 0) { | ||
165 | snprintf(tmp, sizeof(tmp), "LNX1/%8s:", name); | ||
166 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
167 | if (label->lnx.ldl_version == 0xf2) { | ||
168 | fmt_size = label->lnx.formatted_blocks | ||
169 | * (blocksize >> 9); | ||
170 | } else if (!strcmp(info->type, "ECKD")) { | ||
171 | /* formated w/o large volume support */ | ||
172 | fmt_size = geo->cylinders * geo->heads | ||
173 | * geo->sectors * (blocksize >> 9); | ||
174 | } else { | ||
175 | /* old label and no usable disk geometry | ||
176 | * (e.g. DIAG) */ | ||
177 | fmt_size = i_size >> 9; | ||
178 | } | ||
179 | size = i_size >> 9; | ||
180 | if (fmt_size < size) | ||
181 | size = fmt_size; | ||
182 | offset = (info->label_block + 1); | ||
183 | } else { | ||
184 | /* unlabeled disk */ | ||
185 | strlcat(state->pp_buf, "(nonl)", PAGE_SIZE); | ||
186 | size = i_size >> 9; | ||
187 | offset = (info->label_block + 1); | ||
188 | } | ||
189 | put_partition(state, 1, offset*(blocksize >> 9), | ||
190 | size-offset*(blocksize >> 9)); | ||
191 | } | 336 | } |
192 | } else if (info->format == DASD_FORMAT_CDL) { | 337 | } else if (info) { |
193 | /* | ||
194 | * New style CDL formatted disk | ||
195 | */ | ||
196 | sector_t blk; | ||
197 | int counter; | ||
198 | |||
199 | /* | 338 | /* |
200 | * check if VOL1 label is available | 339 | * ugly but needed for backward compatibility: |
201 | * if not, something is wrong, skipping partition detection | 340 | * If the block device is a DASD (i.e. BIODASDINFO2 works), |
341 | * then we claim it in any case, even though it has no valid | ||
342 | * label. If it has the LDL format, then we simply define a | ||
343 | * partition as if it had an LNX1 label. | ||
202 | */ | 344 | */ |
203 | if (strncmp(type, "VOL1", 4) == 0) { | 345 | res = 1; |
204 | snprintf(tmp, sizeof(tmp), "VOL1/%8s:", name); | 346 | if (info->format == DASD_FORMAT_LDL) { |
205 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | 347 | strlcat(state->pp_buf, "(nonl)", PAGE_SIZE); |
206 | /* | 348 | size = i_size >> 9; |
207 | * get block number and read then go through format1 | 349 | offset = (info->label_block + 1) * (blocksize >> 9); |
208 | * labels | 350 | put_partition(state, 1, offset, size-offset); |
209 | */ | 351 | strlcat(state->pp_buf, "\n", PAGE_SIZE); |
210 | blk = cchhb2blk(&label->vol.vtoc, geo) + 1; | 352 | } |
211 | counter = 0; | 353 | } else |
212 | data = read_part_sector(state, blk * (blocksize/512), | 354 | res = 0; |
213 | §); | ||
214 | while (data != NULL) { | ||
215 | struct vtoc_format1_label f1; | ||
216 | |||
217 | memcpy(&f1, data, | ||
218 | sizeof(struct vtoc_format1_label)); | ||
219 | put_dev_sector(sect); | ||
220 | |||
221 | /* skip FMT4 / FMT5 / FMT7 labels */ | ||
222 | if (f1.DS1FMTID == _ascebc['4'] | ||
223 | || f1.DS1FMTID == _ascebc['5'] | ||
224 | || f1.DS1FMTID == _ascebc['7'] | ||
225 | || f1.DS1FMTID == _ascebc['9']) { | ||
226 | blk++; | ||
227 | data = read_part_sector(state, | ||
228 | blk * (blocksize/512), §); | ||
229 | continue; | ||
230 | } | ||
231 | |||
232 | /* only FMT1 and 8 labels valid at this point */ | ||
233 | if (f1.DS1FMTID != _ascebc['1'] && | ||
234 | f1.DS1FMTID != _ascebc['8']) | ||
235 | break; | ||
236 | |||
237 | /* OK, we got valid partition data */ | ||
238 | offset = cchh2blk(&f1.DS1EXT1.llimit, geo); | ||
239 | size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - | ||
240 | offset + geo->sectors; | ||
241 | if (counter >= state->limit) | ||
242 | break; | ||
243 | put_partition(state, counter + 1, | ||
244 | offset * (blocksize >> 9), | ||
245 | size * (blocksize >> 9)); | ||
246 | counter++; | ||
247 | blk++; | ||
248 | data = read_part_sector(state, | ||
249 | blk * (blocksize/512), §); | ||
250 | } | ||
251 | |||
252 | if (!data) | ||
253 | /* Are we not supposed to report this ? */ | ||
254 | goto out_readerr; | ||
255 | } else | ||
256 | printk(KERN_INFO "Expected Label VOL1 not " | ||
257 | "found, treating as CDL formated Disk"); | ||
258 | |||
259 | } | ||
260 | |||
261 | strlcat(state->pp_buf, "\n", PAGE_SIZE); | ||
262 | goto out_freeall; | ||
263 | |||
264 | 355 | ||
265 | out_readerr: | ||
266 | res = -1; | ||
267 | out_freeall: | 356 | out_freeall: |
268 | kfree(label); | 357 | kfree(label); |
269 | out_nolab: | 358 | out_nolab: |