diff options
Diffstat (limited to 'fs/partitions/msdos.c')
| -rw-r--r-- | fs/partitions/msdos.c | 85 |
1 files changed, 48 insertions, 37 deletions
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 0028d2ef0662..90be97f1f5a8 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c | |||
| @@ -31,14 +31,17 @@ | |||
| 31 | */ | 31 | */ |
| 32 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
| 33 | 33 | ||
| 34 | #define SYS_IND(p) (get_unaligned(&p->sys_ind)) | 34 | #define SYS_IND(p) get_unaligned(&p->sys_ind) |
| 35 | #define NR_SECTS(p) ({ __le32 __a = get_unaligned(&p->nr_sects); \ | ||
| 36 | le32_to_cpu(__a); \ | ||
| 37 | }) | ||
| 38 | 35 | ||
| 39 | #define START_SECT(p) ({ __le32 __a = get_unaligned(&p->start_sect); \ | 36 | static inline sector_t nr_sects(struct partition *p) |
| 40 | le32_to_cpu(__a); \ | 37 | { |
| 41 | }) | 38 | return (sector_t)get_unaligned_le32(&p->nr_sects); |
| 39 | } | ||
| 40 | |||
| 41 | static inline sector_t start_sect(struct partition *p) | ||
| 42 | { | ||
| 43 | return (sector_t)get_unaligned_le32(&p->start_sect); | ||
| 44 | } | ||
| 42 | 45 | ||
| 43 | static inline int is_extended_partition(struct partition *p) | 46 | static inline int is_extended_partition(struct partition *p) |
| 44 | { | 47 | { |
| @@ -104,13 +107,13 @@ static int aix_magic_present(unsigned char *p, struct block_device *bdev) | |||
| 104 | 107 | ||
| 105 | static void | 108 | static void |
| 106 | parse_extended(struct parsed_partitions *state, struct block_device *bdev, | 109 | parse_extended(struct parsed_partitions *state, struct block_device *bdev, |
| 107 | u32 first_sector, u32 first_size) | 110 | sector_t first_sector, sector_t first_size) |
| 108 | { | 111 | { |
| 109 | struct partition *p; | 112 | struct partition *p; |
| 110 | Sector sect; | 113 | Sector sect; |
| 111 | unsigned char *data; | 114 | unsigned char *data; |
| 112 | u32 this_sector, this_size; | 115 | sector_t this_sector, this_size; |
| 113 | int sector_size = bdev_logical_block_size(bdev) / 512; | 116 | sector_t sector_size = bdev_logical_block_size(bdev) / 512; |
| 114 | int loopct = 0; /* number of links followed | 117 | int loopct = 0; /* number of links followed |
| 115 | without finding a data partition */ | 118 | without finding a data partition */ |
| 116 | int i; | 119 | int i; |
| @@ -145,14 +148,14 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev, | |||
| 145 | * First process the data partition(s) | 148 | * First process the data partition(s) |
| 146 | */ | 149 | */ |
| 147 | for (i=0; i<4; i++, p++) { | 150 | for (i=0; i<4; i++, p++) { |
| 148 | u32 offs, size, next; | 151 | sector_t offs, size, next; |
| 149 | if (!NR_SECTS(p) || is_extended_partition(p)) | 152 | if (!nr_sects(p) || is_extended_partition(p)) |
| 150 | continue; | 153 | continue; |
| 151 | 154 | ||
| 152 | /* Check the 3rd and 4th entries - | 155 | /* Check the 3rd and 4th entries - |
| 153 | these sometimes contain random garbage */ | 156 | these sometimes contain random garbage */ |
| 154 | offs = START_SECT(p)*sector_size; | 157 | offs = start_sect(p)*sector_size; |
| 155 | size = NR_SECTS(p)*sector_size; | 158 | size = nr_sects(p)*sector_size; |
| 156 | next = this_sector + offs; | 159 | next = this_sector + offs; |
| 157 | if (i >= 2) { | 160 | if (i >= 2) { |
| 158 | if (offs + size > this_size) | 161 | if (offs + size > this_size) |
| @@ -179,13 +182,13 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev, | |||
| 179 | */ | 182 | */ |
| 180 | p -= 4; | 183 | p -= 4; |
| 181 | for (i=0; i<4; i++, p++) | 184 | for (i=0; i<4; i++, p++) |
| 182 | if (NR_SECTS(p) && is_extended_partition(p)) | 185 | if (nr_sects(p) && is_extended_partition(p)) |
| 183 | break; | 186 | break; |
| 184 | if (i == 4) | 187 | if (i == 4) |
| 185 | goto done; /* nothing left to do */ | 188 | goto done; /* nothing left to do */ |
| 186 | 189 | ||
| 187 | this_sector = first_sector + START_SECT(p) * sector_size; | 190 | this_sector = first_sector + start_sect(p) * sector_size; |
| 188 | this_size = NR_SECTS(p) * sector_size; | 191 | this_size = nr_sects(p) * sector_size; |
| 189 | put_dev_sector(sect); | 192 | put_dev_sector(sect); |
| 190 | } | 193 | } |
| 191 | done: | 194 | done: |
| @@ -197,7 +200,7 @@ done: | |||
| 197 | 200 | ||
| 198 | static void | 201 | static void |
| 199 | parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev, | 202 | parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev, |
| 200 | u32 offset, u32 size, int origin) | 203 | sector_t offset, sector_t size, int origin) |
| 201 | { | 204 | { |
| 202 | #ifdef CONFIG_SOLARIS_X86_PARTITION | 205 | #ifdef CONFIG_SOLARIS_X86_PARTITION |
| 203 | Sector sect; | 206 | Sector sect; |
| @@ -244,7 +247,7 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev, | |||
| 244 | */ | 247 | */ |
| 245 | static void | 248 | static void |
| 246 | parse_bsd(struct parsed_partitions *state, struct block_device *bdev, | 249 | parse_bsd(struct parsed_partitions *state, struct block_device *bdev, |
| 247 | u32 offset, u32 size, int origin, char *flavour, | 250 | sector_t offset, sector_t size, int origin, char *flavour, |
| 248 | int max_partitions) | 251 | int max_partitions) |
| 249 | { | 252 | { |
| 250 | Sector sect; | 253 | Sector sect; |
| @@ -263,7 +266,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev, | |||
| 263 | if (le16_to_cpu(l->d_npartitions) < max_partitions) | 266 | if (le16_to_cpu(l->d_npartitions) < max_partitions) |
| 264 | max_partitions = le16_to_cpu(l->d_npartitions); | 267 | max_partitions = le16_to_cpu(l->d_npartitions); |
| 265 | for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) { | 268 | for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) { |
| 266 | u32 bsd_start, bsd_size; | 269 | sector_t bsd_start, bsd_size; |
| 267 | 270 | ||
| 268 | if (state->next == state->limit) | 271 | if (state->next == state->limit) |
| 269 | break; | 272 | break; |
| @@ -290,7 +293,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev, | |||
| 290 | 293 | ||
| 291 | static void | 294 | static void |
| 292 | parse_freebsd(struct parsed_partitions *state, struct block_device *bdev, | 295 | parse_freebsd(struct parsed_partitions *state, struct block_device *bdev, |
| 293 | u32 offset, u32 size, int origin) | 296 | sector_t offset, sector_t size, int origin) |
| 294 | { | 297 | { |
| 295 | #ifdef CONFIG_BSD_DISKLABEL | 298 | #ifdef CONFIG_BSD_DISKLABEL |
| 296 | parse_bsd(state, bdev, offset, size, origin, | 299 | parse_bsd(state, bdev, offset, size, origin, |
| @@ -300,7 +303,7 @@ parse_freebsd(struct parsed_partitions *state, struct block_device *bdev, | |||
| 300 | 303 | ||
| 301 | static void | 304 | static void |
| 302 | parse_netbsd(struct parsed_partitions *state, struct block_device *bdev, | 305 | parse_netbsd(struct parsed_partitions *state, struct block_device *bdev, |
| 303 | u32 offset, u32 size, int origin) | 306 | sector_t offset, sector_t size, int origin) |
| 304 | { | 307 | { |
| 305 | #ifdef CONFIG_BSD_DISKLABEL | 308 | #ifdef CONFIG_BSD_DISKLABEL |
| 306 | parse_bsd(state, bdev, offset, size, origin, | 309 | parse_bsd(state, bdev, offset, size, origin, |
| @@ -310,7 +313,7 @@ parse_netbsd(struct parsed_partitions *state, struct block_device *bdev, | |||
| 310 | 313 | ||
| 311 | static void | 314 | static void |
| 312 | parse_openbsd(struct parsed_partitions *state, struct block_device *bdev, | 315 | parse_openbsd(struct parsed_partitions *state, struct block_device *bdev, |
| 313 | u32 offset, u32 size, int origin) | 316 | sector_t offset, sector_t size, int origin) |
| 314 | { | 317 | { |
| 315 | #ifdef CONFIG_BSD_DISKLABEL | 318 | #ifdef CONFIG_BSD_DISKLABEL |
| 316 | parse_bsd(state, bdev, offset, size, origin, | 319 | parse_bsd(state, bdev, offset, size, origin, |
| @@ -324,7 +327,7 @@ parse_openbsd(struct parsed_partitions *state, struct block_device *bdev, | |||
| 324 | */ | 327 | */ |
| 325 | static void | 328 | static void |
| 326 | parse_unixware(struct parsed_partitions *state, struct block_device *bdev, | 329 | parse_unixware(struct parsed_partitions *state, struct block_device *bdev, |
| 327 | u32 offset, u32 size, int origin) | 330 | sector_t offset, sector_t size, int origin) |
| 328 | { | 331 | { |
| 329 | #ifdef CONFIG_UNIXWARE_DISKLABEL | 332 | #ifdef CONFIG_UNIXWARE_DISKLABEL |
| 330 | Sector sect; | 333 | Sector sect; |
| @@ -348,7 +351,8 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev, | |||
| 348 | 351 | ||
| 349 | if (p->s_label != UNIXWARE_FS_UNUSED) | 352 | if (p->s_label != UNIXWARE_FS_UNUSED) |
| 350 | put_partition(state, state->next++, | 353 | put_partition(state, state->next++, |
| 351 | START_SECT(p), NR_SECTS(p)); | 354 | le32_to_cpu(p->start_sect), |
| 355 | le32_to_cpu(p->nr_sects)); | ||
| 352 | p++; | 356 | p++; |
| 353 | } | 357 | } |
| 354 | put_dev_sector(sect); | 358 | put_dev_sector(sect); |
| @@ -363,7 +367,7 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev, | |||
| 363 | */ | 367 | */ |
| 364 | static void | 368 | static void |
| 365 | parse_minix(struct parsed_partitions *state, struct block_device *bdev, | 369 | parse_minix(struct parsed_partitions *state, struct block_device *bdev, |
| 366 | u32 offset, u32 size, int origin) | 370 | sector_t offset, sector_t size, int origin) |
| 367 | { | 371 | { |
| 368 | #ifdef CONFIG_MINIX_SUBPARTITION | 372 | #ifdef CONFIG_MINIX_SUBPARTITION |
| 369 | Sector sect; | 373 | Sector sect; |
| @@ -390,7 +394,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev, | |||
| 390 | /* add each partition in use */ | 394 | /* add each partition in use */ |
| 391 | if (SYS_IND(p) == MINIX_PARTITION) | 395 | if (SYS_IND(p) == MINIX_PARTITION) |
| 392 | put_partition(state, state->next++, | 396 | put_partition(state, state->next++, |
| 393 | START_SECT(p), NR_SECTS(p)); | 397 | start_sect(p), nr_sects(p)); |
| 394 | } | 398 | } |
| 395 | printk(" >\n"); | 399 | printk(" >\n"); |
| 396 | } | 400 | } |
| @@ -401,7 +405,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev, | |||
| 401 | static struct { | 405 | static struct { |
| 402 | unsigned char id; | 406 | unsigned char id; |
| 403 | void (*parse)(struct parsed_partitions *, struct block_device *, | 407 | void (*parse)(struct parsed_partitions *, struct block_device *, |
| 404 | u32, u32, int); | 408 | sector_t, sector_t, int); |
| 405 | } subtypes[] = { | 409 | } subtypes[] = { |
| 406 | {FREEBSD_PARTITION, parse_freebsd}, | 410 | {FREEBSD_PARTITION, parse_freebsd}, |
| 407 | {NETBSD_PARTITION, parse_netbsd}, | 411 | {NETBSD_PARTITION, parse_netbsd}, |
| @@ -415,7 +419,7 @@ static struct { | |||
| 415 | 419 | ||
| 416 | int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) | 420 | int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) |
| 417 | { | 421 | { |
| 418 | int sector_size = bdev_logical_block_size(bdev) / 512; | 422 | sector_t sector_size = bdev_logical_block_size(bdev) / 512; |
| 419 | Sector sect; | 423 | Sector sect; |
| 420 | unsigned char *data; | 424 | unsigned char *data; |
| 421 | struct partition *p; | 425 | struct partition *p; |
| @@ -483,14 +487,21 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
| 483 | 487 | ||
| 484 | state->next = 5; | 488 | state->next = 5; |
| 485 | for (slot = 1 ; slot <= 4 ; slot++, p++) { | 489 | for (slot = 1 ; slot <= 4 ; slot++, p++) { |
| 486 | u32 start = START_SECT(p)*sector_size; | 490 | sector_t start = start_sect(p)*sector_size; |
| 487 | u32 size = NR_SECTS(p)*sector_size; | 491 | sector_t size = nr_sects(p)*sector_size; |
| 488 | if (!size) | 492 | if (!size) |
| 489 | continue; | 493 | continue; |
| 490 | if (is_extended_partition(p)) { | 494 | if (is_extended_partition(p)) { |
| 491 | /* prevent someone doing mkfs or mkswap on an | 495 | /* |
| 492 | extended partition, but leave room for LILO */ | 496 | * prevent someone doing mkfs or mkswap on an |
| 493 | put_partition(state, slot, start, size == 1 ? 1 : 2); | 497 | * extended partition, but leave room for LILO |
| 498 | * FIXME: this uses one logical sector for > 512b | ||
| 499 | * sector, although it may not be enough/proper. | ||
| 500 | */ | ||
| 501 | sector_t n = 2; | ||
| 502 | n = min(size, max(sector_size, n)); | ||
| 503 | put_partition(state, slot, start, n); | ||
| 504 | |||
| 494 | printk(" <"); | 505 | printk(" <"); |
| 495 | parse_extended(state, bdev, start, size); | 506 | parse_extended(state, bdev, start, size); |
| 496 | printk(" >"); | 507 | printk(" >"); |
| @@ -513,7 +524,7 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
| 513 | unsigned char id = SYS_IND(p); | 524 | unsigned char id = SYS_IND(p); |
| 514 | int n; | 525 | int n; |
| 515 | 526 | ||
| 516 | if (!NR_SECTS(p)) | 527 | if (!nr_sects(p)) |
| 517 | continue; | 528 | continue; |
| 518 | 529 | ||
| 519 | for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++) | 530 | for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++) |
| @@ -521,8 +532,8 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
| 521 | 532 | ||
| 522 | if (!subtypes[n].parse) | 533 | if (!subtypes[n].parse) |
| 523 | continue; | 534 | continue; |
| 524 | subtypes[n].parse(state, bdev, START_SECT(p)*sector_size, | 535 | subtypes[n].parse(state, bdev, start_sect(p)*sector_size, |
| 525 | NR_SECTS(p)*sector_size, slot); | 536 | nr_sects(p)*sector_size, slot); |
| 526 | } | 537 | } |
| 527 | put_dev_sector(sect); | 538 | put_dev_sector(sect); |
| 528 | return 1; | 539 | return 1; |
