fs/partitions/msdos: add support for large disks
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>
This commit is contained in:
committed by
Linus Torvalds
parent
b5c26f97ec
commit
3fbf586cf7
@@ -31,14 +31,17 @@
|
|||||||
*/
|
*/
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#define SYS_IND(p) (get_unaligned(&p->sys_ind))
|
#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 START_SECT(p) ({ __le32 __a = get_unaligned(&p->start_sect); \
|
static inline sector_t nr_sects(struct partition *p)
|
||||||
le32_to_cpu(__a); \
|
{
|
||||||
})
|
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)
|
static inline int is_extended_partition(struct partition *p)
|
||||||
{
|
{
|
||||||
@@ -104,13 +107,13 @@ static int aix_magic_present(unsigned char *p, struct block_device *bdev)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
parse_extended(struct parsed_partitions *state, struct block_device *bdev,
|
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;
|
struct partition *p;
|
||||||
Sector sect;
|
Sector sect;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
u32 this_sector, this_size;
|
sector_t this_sector, this_size;
|
||||||
int sector_size = bdev_logical_block_size(bdev) / 512;
|
sector_t sector_size = bdev_logical_block_size(bdev) / 512;
|
||||||
int loopct = 0; /* number of links followed
|
int loopct = 0; /* number of links followed
|
||||||
without finding a data partition */
|
without finding a data partition */
|
||||||
int i;
|
int i;
|
||||||
@@ -145,14 +148,14 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
* First process the data partition(s)
|
* First process the data partition(s)
|
||||||
*/
|
*/
|
||||||
for (i=0; i<4; i++, p++) {
|
for (i=0; i<4; i++, p++) {
|
||||||
u32 offs, size, next;
|
sector_t offs, size, next;
|
||||||
if (!NR_SECTS(p) || is_extended_partition(p))
|
if (!nr_sects(p) || is_extended_partition(p))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check the 3rd and 4th entries -
|
/* Check the 3rd and 4th entries -
|
||||||
these sometimes contain random garbage */
|
these sometimes contain random garbage */
|
||||||
offs = START_SECT(p)*sector_size;
|
offs = start_sect(p)*sector_size;
|
||||||
size = NR_SECTS(p)*sector_size;
|
size = nr_sects(p)*sector_size;
|
||||||
next = this_sector + offs;
|
next = this_sector + offs;
|
||||||
if (i >= 2) {
|
if (i >= 2) {
|
||||||
if (offs + size > this_size)
|
if (offs + size > this_size)
|
||||||
@@ -179,13 +182,13 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
*/
|
*/
|
||||||
p -= 4;
|
p -= 4;
|
||||||
for (i=0; i<4; i++, p++)
|
for (i=0; i<4; i++, p++)
|
||||||
if (NR_SECTS(p) && is_extended_partition(p))
|
if (nr_sects(p) && is_extended_partition(p))
|
||||||
break;
|
break;
|
||||||
if (i == 4)
|
if (i == 4)
|
||||||
goto done; /* nothing left to do */
|
goto done; /* nothing left to do */
|
||||||
|
|
||||||
this_sector = first_sector + START_SECT(p) * sector_size;
|
this_sector = first_sector + start_sect(p) * sector_size;
|
||||||
this_size = NR_SECTS(p) * sector_size;
|
this_size = nr_sects(p) * sector_size;
|
||||||
put_dev_sector(sect);
|
put_dev_sector(sect);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
@@ -197,7 +200,7 @@ done:
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
|
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
|
#ifdef CONFIG_SOLARIS_X86_PARTITION
|
||||||
Sector sect;
|
Sector sect;
|
||||||
@@ -244,7 +247,7 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
|
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)
|
int max_partitions)
|
||||||
{
|
{
|
||||||
Sector sect;
|
Sector sect;
|
||||||
@@ -263,7 +266,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
if (le16_to_cpu(l->d_npartitions) < max_partitions)
|
if (le16_to_cpu(l->d_npartitions) < max_partitions)
|
||||||
max_partitions = le16_to_cpu(l->d_npartitions);
|
max_partitions = le16_to_cpu(l->d_npartitions);
|
||||||
for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
|
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)
|
if (state->next == state->limit)
|
||||||
break;
|
break;
|
||||||
@@ -290,7 +293,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
|
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
|
#ifdef CONFIG_BSD_DISKLABEL
|
||||||
parse_bsd(state, bdev, offset, size, origin,
|
parse_bsd(state, bdev, offset, size, origin,
|
||||||
@@ -300,7 +303,7 @@ parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
|
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
|
#ifdef CONFIG_BSD_DISKLABEL
|
||||||
parse_bsd(state, bdev, offset, size, origin,
|
parse_bsd(state, bdev, offset, size, origin,
|
||||||
@@ -310,7 +313,7 @@ parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
|
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
|
#ifdef CONFIG_BSD_DISKLABEL
|
||||||
parse_bsd(state, bdev, offset, size, origin,
|
parse_bsd(state, bdev, offset, size, origin,
|
||||||
@@ -324,7 +327,7 @@ parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
|
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
|
#ifdef CONFIG_UNIXWARE_DISKLABEL
|
||||||
Sector sect;
|
Sector sect;
|
||||||
@@ -348,7 +351,8 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
|
|
||||||
if (p->s_label != UNIXWARE_FS_UNUSED)
|
if (p->s_label != UNIXWARE_FS_UNUSED)
|
||||||
put_partition(state, state->next++,
|
put_partition(state, state->next++,
|
||||||
START_SECT(p), NR_SECTS(p));
|
le32_to_cpu(p->start_sect),
|
||||||
|
le32_to_cpu(p->nr_sects));
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
put_dev_sector(sect);
|
put_dev_sector(sect);
|
||||||
@@ -363,7 +367,7 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
parse_minix(struct parsed_partitions *state, struct block_device *bdev,
|
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
|
#ifdef CONFIG_MINIX_SUBPARTITION
|
||||||
Sector sect;
|
Sector sect;
|
||||||
@@ -390,7 +394,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
/* add each partition in use */
|
/* add each partition in use */
|
||||||
if (SYS_IND(p) == MINIX_PARTITION)
|
if (SYS_IND(p) == MINIX_PARTITION)
|
||||||
put_partition(state, state->next++,
|
put_partition(state, state->next++,
|
||||||
START_SECT(p), NR_SECTS(p));
|
start_sect(p), nr_sects(p));
|
||||||
}
|
}
|
||||||
printk(" >\n");
|
printk(" >\n");
|
||||||
}
|
}
|
||||||
@@ -401,7 +405,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev,
|
|||||||
static struct {
|
static struct {
|
||||||
unsigned char id;
|
unsigned char id;
|
||||||
void (*parse)(struct parsed_partitions *, struct block_device *,
|
void (*parse)(struct parsed_partitions *, struct block_device *,
|
||||||
u32, u32, int);
|
sector_t, sector_t, int);
|
||||||
} subtypes[] = {
|
} subtypes[] = {
|
||||||
{FREEBSD_PARTITION, parse_freebsd},
|
{FREEBSD_PARTITION, parse_freebsd},
|
||||||
{NETBSD_PARTITION, parse_netbsd},
|
{NETBSD_PARTITION, parse_netbsd},
|
||||||
@@ -415,7 +419,7 @@ static struct {
|
|||||||
|
|
||||||
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
|
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;
|
Sector sect;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
struct partition *p;
|
struct partition *p;
|
||||||
@@ -483,8 +487,8 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
|
|||||||
|
|
||||||
state->next = 5;
|
state->next = 5;
|
||||||
for (slot = 1 ; slot <= 4 ; slot++, p++) {
|
for (slot = 1 ; slot <= 4 ; slot++, p++) {
|
||||||
u32 start = START_SECT(p)*sector_size;
|
sector_t start = start_sect(p)*sector_size;
|
||||||
u32 size = NR_SECTS(p)*sector_size;
|
sector_t size = nr_sects(p)*sector_size;
|
||||||
if (!size)
|
if (!size)
|
||||||
continue;
|
continue;
|
||||||
if (is_extended_partition(p)) {
|
if (is_extended_partition(p)) {
|
||||||
@@ -513,7 +517,7 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
|
|||||||
unsigned char id = SYS_IND(p);
|
unsigned char id = SYS_IND(p);
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (!NR_SECTS(p))
|
if (!nr_sects(p))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
|
for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
|
||||||
@@ -521,8 +525,8 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
|
|||||||
|
|
||||||
if (!subtypes[n].parse)
|
if (!subtypes[n].parse)
|
||||||
continue;
|
continue;
|
||||||
subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
|
subtypes[n].parse(state, bdev, start_sect(p)*sector_size,
|
||||||
NR_SECTS(p)*sector_size, slot);
|
nr_sects(p)*sector_size, slot);
|
||||||
}
|
}
|
||||||
put_dev_sector(sect);
|
put_dev_sector(sect);
|
||||||
return 1;
|
return 1;
|
||||||
|
Reference in New Issue
Block a user