[PATCH] track largest ext3 LBA to prevent wild LBA seeks and reads

Doug Maxey dwm at enoyolf.org
Sat Dec 30 03:34:37 EST 2006


>From 670d43caef7ac4477f56bd54810f5064d78bab5d Mon Sep 17 00:00:00 2001
From: Doug Maxey <dwm at austin.ibm.com>
Date: Thu, 28 Dec 2006 21:15:49 -0600
Subject: [PATCH] track largest ext3 LBA to prevent wild LBA seeks and reads

In partition_fdisk_lookup(), keep track of the last LBA referenced
from the parition table.  Use the last LBA in linux_read_blks().

This is needed as linux_read_blk() in fs_ext2.c calculates some
offsets to read that are an order of magnitude larger than the size of
the actual disk.

Normally this is not a performance issue, other than maybe a message
"Request exceed total sectors" from OFW.  The delay is not noticeable
with locally attached disk.

However, on a Netapp serving an iSCSI target disk, the request past
the last LBA of the lun causes an undeflow, which takes 30 seconds or
so for the target to recover.  The net effect is to add 5+ minutes to
the boot while the OFW does polling transfers over the net.

Remove the file local def of swab32() and use the one defined in
local byteswap.h, along with the lexx_to_cpu macros().

Signed-off-by: Doug Maxey <dwm at austin.ibm.com>
---
This has been tested on js20 for iboot and sundry other ppc64 for 
normal local disk boot.

Oh, and this is on top of the other iboot patches.

++doug
---
 include/partition.h |    3 +++
 second/fs_ext2.c    |   14 +++++++++++++-
 second/partition.c  |   23 ++++++++++-------------
 3 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/include/partition.h b/include/partition.h
index 23c99ba..ed6cdee 100644
--- a/include/partition.h
+++ b/include/partition.h
@@ -47,4 +47,7 @@ extern struct partition_t*	partitions_lookup(const char *device);
 extern char                     *get_part_type(char *device, int partition);
 extern void			partitions_free(struct partition_t* list);
 
+extern u32 last_start;
+extern u64 bootable_blocks;
+
 #endif
diff --git a/second/fs_ext2.c b/second/fs_ext2.c
index bffebb4..e625bd3 100644
--- a/second/fs_ext2.c
+++ b/second/fs_ext2.c
@@ -601,7 +601,19 @@ static errcode_t linux_read_blk (io_channel channel, unsigned long block, int co
      tempb = (((unsigned long long) block) *
 	      ((unsigned long long)bs)) + (unsigned long long)doff;
      size = (count < 0) ? -count : count * bs;
-     prom_lseek(cur_file->of_device, tempb);
+
+     /*
+      * Always test if the seek would place us outside the known size
+      * of the disk.  Always use 512 byte blocks.
+      *
+      * Also test return from prom_lseek.
+      */
+     if ((tempb >> 9) > bootable_blocks ||
+ 	 !prom_lseek(cur_file->of_device, tempb)) {
+	  DEBUG_F("\nSeek error on block %ld\n", block);
+	  return EXT2_ET_LLSEEK_FAILED;
+     }
+
      if (prom_read(cur_file->of_device, data, size) != size) {
 	  DEBUG_F("\nRead error on block %ld\n", block);
 	  return EXT2_ET_SHORT_READ;
diff --git a/second/partition.c b/second/partition.c
index 53c7bd0..ee1fcae 100644
--- a/second/partition.c
+++ b/second/partition.c
@@ -40,6 +40,7 @@
 #include "linux/iso_fs.h"
 #include "debug.h"
 #include "errors.h"
+#include "byteorder.h"
 
 /* We currently don't check the partition type, some users
  * are putting crap there and still expect it to work...
@@ -59,7 +60,6 @@ static const char *valid_mac_partition_types[] = {
     
 
 /* Local functions */
-static unsigned long swab32(unsigned long value);
 
 #define MAX_BLOCK_SIZE	2048
 static unsigned char block_buffer[MAX_BLOCK_SIZE];
@@ -159,11 +159,15 @@ partition_mac_lookup( const char *dev_name, prom_handle disk,
  * Same function as partition_mac_lookup(), except for fdisk
  * partitioned disks.
  */
+u32 last_start;
+u64 bootable_blocks;
+
 static void
 partition_fdisk_lookup( const char *dev_name, prom_handle disk,
                         unsigned int prom_blksize, struct partition_t** list )
 {
      int partition;
+     u32 start;
 
      /* fdisk partition tables start at offset 0x1be
       * from byte 0 of the boot drive.
@@ -181,6 +185,11 @@ partition_fdisk_lookup( const char *dev_name, prom_handle disk,
 				   swab32(*(unsigned int *)(part->size4)),
 				   512 /*blksize*/,
 				   part->sys_ind /* partition type */ );
+	       start = le32_to_cpu((u32)part->start4);
+	       if (start > last_start) {
+		       last_start = start;
+		       bootable_blocks = (start + le32_to_cpu((u32)part->size4));
+	       }
 	  }
      }
 }
@@ -432,18 +441,6 @@ partitions_free(struct partition_t* list)
 	  list = next;
      }
 }
-unsigned long
-swab32(unsigned long value)
-{
-     __u32 result;
-
-     __asm__("rlwimi %0,%1,24,16,23\n\t"
-	     "rlwimi %0,%1,8,8,15\n\t"
-	     "rlwimi %0,%1,24,0,7"
-	     : "=r" (result)
-	     : "r" (value), "0" (value >> 24));
-     return result;
-}
 
 
 /* 
-- 
1.4.4.3








More information about the Yaboot-users mailing list