Skip to content

Commit

Permalink
fs/partitions/msdos: add support for large disks
Browse files Browse the repository at this point in the history
In order to use disks larger than 2TiB on Windows XP, it is necessary to
use 4096-byte logical sectors in an MBR.

Although the kernel storage and functions called from msdos.c used
"sector_t" internally, msdos.c still used u32 variables, which results in
the ability to handle XP-compatible large disks.

This patch changes the internal variables to "sector_t".

Daniel said: "In the near future, WD will be releasing products that need
this patch".

[hirofumi@mail.parknet.co.jp: tweaks and fix]
Signed-off-by: Daniel Taylor <daniel.taylor@wdc.com>
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Daniel Taylor authored and torvalds committed Mar 24, 2010
1 parent b5c26f9 commit 3fbf586
Showing 1 changed file with 38 additions and 34 deletions.
72 changes: 38 additions & 34 deletions fs/partitions/msdos.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,17 @@
*/
#include <asm/unaligned.h>

#define SYS_IND(p) (get_unaligned(&p->sys_ind))
#define NR_SECTS(p) ({ __le32 __a = get_unaligned(&p->nr_sects); \
le32_to_cpu(__a); \
})
#define SYS_IND(p) get_unaligned(&p->sys_ind)

#define START_SECT(p) ({ __le32 __a = get_unaligned(&p->start_sect); \
le32_to_cpu(__a); \
})
static inline sector_t nr_sects(struct partition *p)
{
return (sector_t)get_unaligned_le32(&p->nr_sects);
}

static inline sector_t start_sect(struct partition *p)
{
return (sector_t)get_unaligned_le32(&p->start_sect);
}

static inline int is_extended_partition(struct partition *p)
{
Expand Down Expand Up @@ -104,13 +107,13 @@ static int aix_magic_present(unsigned char *p, struct block_device *bdev)

static void
parse_extended(struct parsed_partitions *state, struct block_device *bdev,
u32 first_sector, u32 first_size)
sector_t first_sector, sector_t first_size)
{
struct partition *p;
Sector sect;
unsigned char *data;
u32 this_sector, this_size;
int sector_size = bdev_logical_block_size(bdev) / 512;
sector_t this_sector, this_size;
sector_t sector_size = bdev_logical_block_size(bdev) / 512;
int loopct = 0; /* number of links followed
without finding a data partition */
int i;
Expand Down Expand Up @@ -145,14 +148,14 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
* First process the data partition(s)
*/
for (i=0; i<4; i++, p++) {
u32 offs, size, next;
if (!NR_SECTS(p) || is_extended_partition(p))
sector_t offs, size, next;
if (!nr_sects(p) || is_extended_partition(p))
continue;

/* Check the 3rd and 4th entries -
these sometimes contain random garbage */
offs = START_SECT(p)*sector_size;
size = NR_SECTS(p)*sector_size;
offs = start_sect(p)*sector_size;
size = nr_sects(p)*sector_size;
next = this_sector + offs;
if (i >= 2) {
if (offs + size > this_size)
Expand All @@ -179,13 +182,13 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
*/
p -= 4;
for (i=0; i<4; i++, p++)
if (NR_SECTS(p) && is_extended_partition(p))
if (nr_sects(p) && is_extended_partition(p))
break;
if (i == 4)
goto done; /* nothing left to do */

this_sector = first_sector + START_SECT(p) * sector_size;
this_size = NR_SECTS(p) * sector_size;
this_sector = first_sector + start_sect(p) * sector_size;
this_size = nr_sects(p) * sector_size;
put_dev_sector(sect);
}
done:
Expand All @@ -197,7 +200,7 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,

static void
parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
sector_t offset, sector_t size, int origin)
{
#ifdef CONFIG_SOLARIS_X86_PARTITION
Sector sect;
Expand Down Expand Up @@ -244,7 +247,7 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
*/
static void
parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin, char *flavour,
sector_t offset, sector_t size, int origin, char *flavour,
int max_partitions)
{
Sector sect;
Expand All @@ -263,7 +266,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
if (le16_to_cpu(l->d_npartitions) < max_partitions)
max_partitions = le16_to_cpu(l->d_npartitions);
for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
u32 bsd_start, bsd_size;
sector_t bsd_start, bsd_size;

if (state->next == state->limit)
break;
Expand All @@ -290,7 +293,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev,

static void
parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
sector_t offset, sector_t size, int origin)
{
#ifdef CONFIG_BSD_DISKLABEL
parse_bsd(state, bdev, offset, size, origin,
Expand All @@ -300,7 +303,7 @@ parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,

static void
parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
sector_t offset, sector_t size, int origin)
{
#ifdef CONFIG_BSD_DISKLABEL
parse_bsd(state, bdev, offset, size, origin,
Expand All @@ -310,7 +313,7 @@ parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,

static void
parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
sector_t offset, sector_t size, int origin)
{
#ifdef CONFIG_BSD_DISKLABEL
parse_bsd(state, bdev, offset, size, origin,
Expand All @@ -324,7 +327,7 @@ parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
*/
static void
parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
sector_t offset, sector_t size, int origin)
{
#ifdef CONFIG_UNIXWARE_DISKLABEL
Sector sect;
Expand All @@ -348,7 +351,8 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev,

if (p->s_label != UNIXWARE_FS_UNUSED)
put_partition(state, state->next++,
START_SECT(p), NR_SECTS(p));
le32_to_cpu(p->start_sect),
le32_to_cpu(p->nr_sects));
p++;
}
put_dev_sector(sect);
Expand All @@ -363,7 +367,7 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
*/
static void
parse_minix(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
sector_t offset, sector_t size, int origin)
{
#ifdef CONFIG_MINIX_SUBPARTITION
Sector sect;
Expand All @@ -390,7 +394,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev,
/* add each partition in use */
if (SYS_IND(p) == MINIX_PARTITION)
put_partition(state, state->next++,
START_SECT(p), NR_SECTS(p));
start_sect(p), nr_sects(p));
}
printk(" >\n");
}
Expand All @@ -401,7 +405,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev,
static struct {
unsigned char id;
void (*parse)(struct parsed_partitions *, struct block_device *,
u32, u32, int);
sector_t, sector_t, int);
} subtypes[] = {
{FREEBSD_PARTITION, parse_freebsd},
{NETBSD_PARTITION, parse_netbsd},
Expand All @@ -415,7 +419,7 @@ static struct {

int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int sector_size = bdev_logical_block_size(bdev) / 512;
sector_t sector_size = bdev_logical_block_size(bdev) / 512;
Sector sect;
unsigned char *data;
struct partition *p;
Expand Down Expand Up @@ -483,8 +487,8 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)

state->next = 5;
for (slot = 1 ; slot <= 4 ; slot++, p++) {
u32 start = START_SECT(p)*sector_size;
u32 size = NR_SECTS(p)*sector_size;
sector_t start = start_sect(p)*sector_size;
sector_t size = nr_sects(p)*sector_size;
if (!size)
continue;
if (is_extended_partition(p)) {
Expand Down Expand Up @@ -513,16 +517,16 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned char id = SYS_IND(p);
int n;

if (!NR_SECTS(p))
if (!nr_sects(p))
continue;

for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
;

if (!subtypes[n].parse)
continue;
subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
NR_SECTS(p)*sector_size, slot);
subtypes[n].parse(state, bdev, start_sect(p)*sector_size,
nr_sects(p)*sector_size, slot);
}
put_dev_sector(sect);
return 1;
Expand Down

0 comments on commit 3fbf586

Please sign in to comment.