[26/98] partitions: use sector size for EFI GPT

From: Greg KH
Date: Tue Jan 26 2010 - 19:01:40 EST


2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Karel Zak <kzak@xxxxxxxxxx>

commit 7d13af3279985f554784a45cc961f706dbcdbdd1 upstream.

Currently, kernel uses strictly 512-byte sectors for EFI GPT parsing.
That's wrong.

UEFI standard (version 2.3, May 2009, 5.3.1 GUID Format overview, page
95) defines that LBA is always based on the logical block size. It
means bdev_logical_block_size() (aka BLKSSZGET) for Linux.

This patch removes static sector size from EFI GPT parser.

The problem is reproducible with the latest GNU Parted:

# modprobe scsi_debug dev_size_mb=50 sector_size=4096

# ./parted /dev/sdb print
Model: Linux scsi_debug (scsi)
Disk /dev/sdb: 52.4MB
Sector size (logical/physical): 4096B/4096B
Partition Table: gpt

Number Start End Size File system Name Flags
1 24.6kB 3002kB 2978kB primary
2 3002kB 6001kB 2998kB primary
3 6001kB 9003kB 3002kB primary

# blockdev --rereadpt /dev/sdb
# dmesg | tail -1
sdb: unknown partition table <---- !!!

with this patch:

# blockdev --rereadpt /dev/sdb
# dmesg | tail -1
sdb: sdb1 sdb2 sdb3

Signed-off-by: Karel Zak <kzak@xxxxxxxxxx>
Signed-off-by: Jens Axboe <jens.axboe@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
fs/partitions/efi.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)

--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -1,7 +1,9 @@
/************************************************************
* EFI GUID Partition Table handling
- * Per Intel EFI Specification v1.02
- * http://developer.intel.com/technology/efi/efi.htm
+ *
+ * http://www.uefi.org/specs/
+ * http://www.intel.com/technology/efi/
+ *
* efi.[ch] by Matt Domsch <Matt_Domsch@xxxxxxxx>
* Copyright 2000,2001,2002,2004 Dell Inc.
*
@@ -92,6 +94,7 @@
*
************************************************************/
#include <linux/crc32.h>
+#include <linux/math64.h>
#include "check.h"
#include "efi.h"

@@ -141,7 +144,8 @@ last_lba(struct block_device *bdev)
{
if (!bdev || !bdev->bd_inode)
return 0;
- return (bdev->bd_inode->i_size >> 9) - 1ULL;
+ return div_u64(bdev->bd_inode->i_size,
+ bdev_logical_block_size(bdev)) - 1ULL;
}

static inline int
@@ -188,6 +192,7 @@ static size_t
read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count)
{
size_t totalreadcount = 0;
+ sector_t n = lba * (bdev_logical_block_size(bdev) / 512);

if (!bdev || !buffer || lba > last_lba(bdev))
return 0;
@@ -195,7 +200,7 @@ read_lba(struct block_device *bdev, u64
while (count) {
int copied = 512;
Sector sect;
- unsigned char *data = read_dev_sector(bdev, lba++, &sect);
+ unsigned char *data = read_dev_sector(bdev, n++, &sect);
if (!data)
break;
if (copied > count)
@@ -602,6 +607,7 @@ efi_partition(struct parsed_partitions *
gpt_header *gpt = NULL;
gpt_entry *ptes = NULL;
u32 i;
+ unsigned ssz = bdev_logical_block_size(bdev) / 512;

if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) {
kfree(gpt);
@@ -612,13 +618,14 @@ efi_partition(struct parsed_partitions *
pr_debug("GUID Partition Table is valid! Yea!\n");

for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
+ u64 start = le64_to_cpu(ptes[i].starting_lba);
+ u64 size = le64_to_cpu(ptes[i].ending_lba) -
+ le64_to_cpu(ptes[i].starting_lba) + 1ULL;
+
if (!is_pte_valid(&ptes[i], last_lba(bdev)))
continue;

- put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba),
- (le64_to_cpu(ptes[i].ending_lba) -
- le64_to_cpu(ptes[i].starting_lba) +
- 1ULL));
+ put_partition(state, i+1, start * ssz, size * ssz);

/* If this is a RAID volume, tell md */
if (!efi_guidcmp(ptes[i].partition_type_guid,


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/