--- linux/fs/partitions/msdos.c.orig	Tue Oct  2 15:28:17 2001
+++ linux/fs/partitions/msdos.c	Tue Oct  2 15:28:33 2001
@@ -574,7 +574,7 @@
 	for (i=1 ; i<=4 ; i++,p++) {
 		/* If this is an EFI GPT disk, msdos should ignore it. */
 		if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
-			bforget(bh);
+			put_dev_sector(sect);
 			return 0;
 		}
 	}
--- linux/fs/partitions/efi.h~	Mon Oct  1 16:02:13 2001
+++ linux/fs/partitions/efi.h	Mon Oct  1 16:03:17 2001
@@ -124,7 +124,7 @@
 
 /* Functions */
 extern int
-efi_partition(struct gendisk *hd, kdev_t dev,
+efi_partition(struct gendisk *hd, struct block_device *bdev,
               unsigned long first_sector, int first_part_minor);
 
 
--- linux/fs/partitions/efi.c.orig	Wed Oct  3 15:33:24 2001
+++ linux/fs/partitions/efi.c	Wed Oct  3 16:43:17 2001
@@ -27,13 +27,15 @@
  *
  *
  * TODO:
- * - Change read_lba() when 64-bit block addressing is allowed.
  * - printing of 64-bit values on a 32-bit system is broken.  %llx should
  *   work on both ia64 and ia32 to print a u64, but if -Wall is used,
  *   gcc complains.
  *
  * Changelog:
  * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Change read_lba() to use the page cache per Al Viro's work.
+ *
+ * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com>
  * - Style cleanups
  * - made most functions static
  * - Endianness addition
@@ -199,7 +201,7 @@ is_pmbr_valid(LegacyMBR_t *mbr)
  * last_lba()
  * Requires:
  *  - struct gendisk hd
- *  - kdev_t dev
+ *  - struct block_device *bdev
  * Modifies: nothing
  * Returns:
  *  Last LBA value on success.  This is stored (by sd and
@@ -209,9 +211,11 @@ is_pmbr_valid(LegacyMBR_t *mbr)
  *  0 on error
  ************************************************************/
 static u64
-last_lba(struct gendisk *hd, kdev_t dev)
+last_lba(struct gendisk *hd, struct block_device *bdev)
 {
-  if (!hd || !hd->part) return 0;
+        kdev_t dev;
+        if (!hd || !hd->part || !bdev) return 0;
+        dev = to_kdev_t(bdev->bd_dev);
   return hd->part[MINOR(dev)].nr_sects - 1;
 }
 
@@ -220,7 +224,7 @@ last_lba(struct gendisk *hd, kdev_t dev)
  * read_lba()
  * Requires:
  *  - hd is our disk device.
- *  - dev is our device major number
+ *  - bdev is our device major number
  *  - lba is the logical block address desired (disk hardsector number)
  *  - buffer is a buffer of size size into which data copied
  *  - size_t count is size of the read (in bytes)
@@ -229,51 +233,40 @@ last_lba(struct gendisk *hd, kdev_t dev)
  * Returns:
  *  - count of bytes read
  *  - 0 on error
- * Bugs:
- *  - bread() takes second argument as a signed int, not a u64.
- *    This is because getblk() takes the block number as a signed int.
- *    This overflow is known on l-k.   We overflow at about 1TB.
- *
  ************************************************************/
 
 static size_t
-read_lba(struct gendisk *hd, kdev_t dev, u64 _lba, u8 *buffer, size_t count)
+read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba, u8 *buffer, size_t count)
 {
-	struct buffer_head *bh;
-	size_t totalreadcount = 0, bytesread;
-	int lba = (_lba & 0x7FFFFFFF), i, blockstoread, blocksize;
-	debug_printk(efi_printk_level "read_lba(%p,%s,%x,%p,%x)\n",
-		     hd, kdevname(dev), lba, buffer, count);
-
-	if (!hd || !buffer || !count) return 0;
 
+	size_t totalreadcount = 0;
+        unsigned long bytesread=0, blocksize;
+	int i;
+        Sector sect;
+        unsigned char *data=NULL;
 
-	blocksize = get_hardsect_size(dev);
-	blockstoread = count / blocksize;
-	if (count % blocksize) blockstoread += 1;
-	debug_printk(efi_printk_level "about to read %d blocks\n",
-		     blockstoread);
+	if (!hd || !buffer || !count) return 0;
 
+	blocksize = get_hardsect_size(to_kdev_t(bdev->bd_dev));
+        if (!blocksize) blocksize = 512;
 
-	for (i=0; i<blockstoread; i++) {
-		bh = bread(dev, lba+i, blocksize);
-		if (!bh) {
-			/* We hit the end of the disk */
-			debug_printk(efi_printk_level
-				     "bread returned NULL.\n");
+	for (i=0; count > 0; i++) {
+                data = read_dev_sector(bdev, lba, &sect);
+                if (!data) {
+                        put_dev_sector(sect);
 			return totalreadcount;
 		}
-
-		bytesread = (count > bh->b_size ? bh->b_size : count);
-		memcpy(buffer, bh->b_data, bytesread);
+                /* first determine how much of this page we're going to use */
+                bytesread = PAGE_CACHE_SIZE - (data - (unsigned char *)page_address(sect.v));
+		bytesread = min(bytesread, count);
+		memcpy(buffer, data, bytesread);
+                put_dev_sector(sect);
 
 		buffer += bytesread;         /* Advance the buffer pointer */
 		totalreadcount += bytesread; /* Advance the total read count */
 		count -= bytesread;         /* Subtract bytesread from count */
-
-		brelse(bh);
+                lba += (bytesread / blocksize);
 	}
-
 	return totalreadcount;
 }
 
@@ -318,7 +311,7 @@ print_gpt_header(GuidPartitionTableHeade
 /************************************************************
  * alloc_read_gpt_entries()
  * Requires:
- *  - hd, dev, gpt
+ *  - hd, bdev, gpt
  * Modifies:
  *  - nothing
  * Returns:
@@ -327,7 +320,7 @@ print_gpt_header(GuidPartitionTableHeade
  * Notes: remember to free pte when you're done!
  ************************************************************/
 static GuidPartitionEntry_t *
-alloc_read_gpt_entries(struct gendisk *hd, kdev_t dev,
+alloc_read_gpt_entries(struct gendisk *hd, struct block_device *bdev,
 			 GuidPartitionTableHeader_t *gpt)
 {
         u32 i, j;
@@ -343,7 +336,7 @@ alloc_read_gpt_entries(struct gendisk *h
 	if (!pte)  return NULL;
 	memset(pte, 0, count);
 
-	if (read_lba(hd, dev, gpt->PartitionEntryLBA, (u8 *)pte,
+	if (read_lba(hd, bdev, gpt->PartitionEntryLBA, (u8 *)pte,
 		    count) < count) {
 		kfree(pte);
 		return NULL;
@@ -381,7 +374,7 @@ alloc_read_gpt_entries(struct gendisk *h
  ************************************************************/
 
 static GuidPartitionTableHeader_t *
-alloc_read_gpt_header(struct gendisk *hd, kdev_t dev, u64 lba)
+alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
 
 {
 	GuidPartitionTableHeader_t *gpt;
@@ -392,7 +385,7 @@ alloc_read_gpt_header(struct gendisk *hd
 	memset(gpt, 0, sizeof(GuidPartitionTableHeader_t));
 
 	debug_printk(efi_printk_level "GPTH() calling read_lba().\n");
-	if (read_lba(hd, dev, lba, (u8 *)gpt,
+	if (read_lba(hd, bdev, lba, (u8 *)gpt,
 		    sizeof(GuidPartitionTableHeader_t)) <
 	    sizeof(GuidPartitionTableHeader_t)) {
 		debug_printk(efi_printk_level "ReadGPTH(%lx) read failed.\n",
@@ -439,14 +432,14 @@ alloc_read_gpt_header(struct gendisk *hd
  *   0 on error
  ************************************************************/
 static int
-is_gpt_valid(struct gendisk *hd, kdev_t dev, u64 lba,
+is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
 			  GuidPartitionTableHeader_t **gpt,
 			  GuidPartitionEntry_t **ptes)
 {
 	u32 crc, origcrc;
 
 	if (!hd || !gpt || !ptes) return 0;
-	if (!(*gpt = alloc_read_gpt_header(hd, dev, lba))) return 0;
+	if (!(*gpt = alloc_read_gpt_header(hd, bdev, lba))) return 0;
 
 	/* Check the GUID Partition Table Signature */
 	if ((*gpt)->Signature != GPT_HEADER_SIGNATURE) {
@@ -479,7 +472,7 @@ is_gpt_valid(struct gendisk *hd, kdev_t 
 		return 0;
 	}
 
-	if (!(*ptes = alloc_read_gpt_entries(hd, dev, *gpt))) {
+	if (!(*ptes = alloc_read_gpt_entries(hd, bdev, *gpt))) {
 		debug_printk(efi_printk_level "read PTEs failed.\n");
 		kfree(*gpt);
 		*gpt = NULL;
@@ -521,7 +514,7 @@ is_gpt_valid(struct gendisk *hd, kdev_t 
  *   0 on error
  ************************************************************/
 static int
-find_valid_gpt(struct gendisk *hd, kdev_t dev,
+find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
 	     GuidPartitionTableHeader_t **gpt,
 	     GuidPartitionEntry_t **ptes)
 {
@@ -532,12 +525,12 @@ find_valid_gpt(struct gendisk *hd, kdev_
 	u64 lastlba;
 	if (!hd || !gpt || !ptes) return 0;
 
-	lastlba = last_lba(hd, dev);
+	lastlba = last_lba(hd, bdev);
 	/* Check the Primary GPT */
-	good_pgpt = is_gpt_valid(hd, dev, 1, &pgpt, &pptes);
+	good_pgpt = is_gpt_valid(hd, bdev, 1, &pgpt, &pptes);
 	if (good_pgpt) {
 		/* Primary GPT is OK, check the alternate and warn if bad */
-		good_agpt= is_gpt_valid(hd, dev, pgpt->AlternateLBA,
+		good_agpt= is_gpt_valid(hd, bdev, pgpt->AlternateLBA,
 					       &agpt, &aptes);
 		if (!good_agpt){
 			printk(KERN_WARNING "Alternate GPT is invalid, using primary GPT.\n");
@@ -550,7 +543,7 @@ find_valid_gpt(struct gendisk *hd, kdev_
 	} /* if primary is valid */
 	else {
 		/* Primary GPT is bad, check the Alternate GPT */
-		good_agpt = is_gpt_valid(hd, dev, lastlba,
+		good_agpt = is_gpt_valid(hd, bdev, lastlba,
 					       &agpt, &aptes);
 		if (good_agpt) {
 			/* Primary is bad, alternate is good.
@@ -568,7 +561,7 @@ find_valid_gpt(struct gendisk *hd, kdev_
                 legacyMbr = kmalloc(sizeof(*legacyMbr), GFP_KERNEL);
                 if (legacyMbr) {
                         memset(legacyMbr, 0, sizeof(*legacyMbr));
-                        read_lba(hd, dev, 0, (u8 *)legacyMbr, sizeof(*legacyMbr));
+                        read_lba(hd, bdev, 0, (u8 *)legacyMbr, sizeof(*legacyMbr));
                         good_pmbr = is_pmbr_valid(legacyMbr);
                         kfree(legacyMbr);
                 }
@@ -635,7 +628,7 @@ static void set_partition_guid (struct g
  */
 
 static int
-add_gpt_partitions(struct gendisk *hd, kdev_t dev, int nextminor)
+add_gpt_partitions(struct gendisk *hd, struct block_device *bdev, int nextminor)
 {
 	GuidPartitionTableHeader_t *gpt = NULL;
 	GuidPartitionEntry_t *ptes = NULL;
@@ -648,7 +641,7 @@ add_gpt_partitions(struct gendisk *hd, k
 
 	if (!hd) return -1;
 
-	if (!find_valid_gpt(hd, dev, &gpt, &ptes) ||
+	if (!find_valid_gpt(hd, bdev, &gpt, &ptes) ||
 	    !gpt || !ptes) {
 		if (gpt) kfree(gpt);
 		if (ptes) kfree(ptes);
@@ -676,7 +669,7 @@ add_gpt_partitions(struct gendisk *hd, k
 		/* If there's this is a RAID volume, tell md */
 #if CONFIG_BLK_DEV_MD
 		if (!efi_guidcmp(raidGuid, ptes[i].PartitionTypeGuid)) {
-			md_autodetect_dev(MKDEV(MAJOR(dev),nextminor));
+			md_autodetect_dev(MKDEV(MAJOR(to_kdev_t(bdev->bd_dev)),nextminor));
 		}
 #endif
 		nummade++;
@@ -706,27 +699,9 @@ add_gpt_partitions(struct gendisk *hd, k
  */
 
 int
-efi_partition(struct gendisk *hd, kdev_t dev,
+efi_partition(struct gendisk *hd, struct block_device *bdev,
 	      unsigned long first_sector, int first_part_minor) {
-	int hardblocksize = get_hardsect_size(dev);
-	int orig_blksize_size = BLOCK_SIZE;
-	int rc = 0;
-
-	/* Need to change the block size that the block layer uses */
-	if (blksize_size[MAJOR(dev)]){
-		orig_blksize_size = blksize_size[MAJOR(dev)][MINOR(dev)];
-	}
-
-	if (orig_blksize_size != hardblocksize)
-		set_blocksize(dev, hardblocksize);
-
-	rc = add_gpt_partitions(hd, dev, first_part_minor);
-
-	/* change back */
-	if (orig_blksize_size != hardblocksize)
-		set_blocksize(dev, orig_blksize_size);
-
-	return rc;
+	return add_gpt_partitions(hd, bdev, first_part_minor);
 }
 
 
