Determine last ext3 LBA to fix wild LBA reads
authorPaul Nasrat <pnasrat@redhat.com>
Thu, 15 Feb 2007 12:24:28 +0000 (12:24 +0000)
committerPaul Nasrat <pauln@enki.eridu>
Thu, 15 Feb 2007 12:24:28 +0000 (12:24 +0000)
Signed-off-by: Doug Maxey <dwm@austin.ibm.com>
Cc: Ben Herrenschmidt <benh@kernel.crashing.org>
second/fs_ext2.c
second/partition.c

index 729e2f4a64b55a7c90a920e013be2eab32128cc0..3240ce215ac802c6164f459f2f06df7e67c937d0 100644 (file)
@@ -93,6 +93,7 @@ static io_manager linux_io_manager = &struct_linux_manager;
 static int opened = 0;         /* We can't open twice ! */
 static unsigned int bs;                /* Blocksize */
 static unsigned long long doff;        /* Byte offset where partition starts */
+static unsigned long long dend;        /* Byte offset where partition ends */
 static ino_t root,cwd;
 static ext2_filsys fs = 0;
 static struct boot_file_t* cur_file;
@@ -149,13 +150,23 @@ ext2_open(        struct boot_file_t*     file,
       * compatible with older versions of OF
       */
      bs = 1024;
-     doff = 0;
-     if (part)
+
+     /*
+      * On the other hand, we do care about the actual size of the
+      * partition, reads or seeks past the end may cause undefined
+      * behavior on some devices.  A netapp that tries to seek and
+      * read past the end of the lun takes ~30 secs to recover per
+      * attempt.
+      */
+     doff = dend = 0;
+     if (part) {
          doff = (unsigned long long)(part->part_start) * part->blocksize;
+         dend = doff + (unsigned long long)part->part_size * part->blocksize;
+     }
      cur_file = file;
 
 
-     DEBUG_F("partition offset: %Lu\n", doff);
+     DEBUG_F("partition offset: %Lx, end: %Lx\n", doff, dend);
 
      /* Open the OF device for the entire disk */
      strncpy(buffer, dev_name, 1020);
@@ -582,6 +593,7 @@ static errcode_t linux_close (io_channel channel)
 
 static errcode_t linux_set_blksize (io_channel channel, int blksize)
 {
+     DEBUG_F("bs set to 0x%x\n", blksize);
      channel->block_size = bs = blksize;
      if (block_buffer) {
          free(block_buffer);
@@ -600,6 +612,15 @@ 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;
+     /*
+      * Only test tempb exceeding dend if dend is set to allow things
+      * like boot: hd:0,\xxxx
+      */
+     if (dend && tempb > dend) {
+         DEBUG_F("\nSeek error on block %lx, tempb=%Lx\n", block, tempb >> 9);
+         return EXT2_ET_LLSEEK_FAILED;
+     }
+
      size = (count < 0) ? -count : count * bs;
      prom_lseek(cur_file->of_device, tempb);
      if (prom_read(cur_file->of_device, data, size) != size) {
index 12942a94cf6b4aacf1b240f3d55d58c4d1de643a..0cb8ae85f1768bb7aef755c6ef37f64b64f5f168 100644 (file)
@@ -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...
@@ -58,9 +59,6 @@ static const char *valid_mac_partition_types[] = {
 #endif
 
 
-/* Local functions */
-static unsigned long swab32(unsigned long value);
-
 #define MAX_BLOCK_SIZE 2048
 static unsigned char block_buffer[MAX_BLOCK_SIZE];
 
@@ -177,8 +175,8 @@ partition_fdisk_lookup( const char *dev_name, prom_handle disk,
                                   partition,
                                   "Linux", /* type */
                                   '\0', /* name */
-                                  swab32(*(unsigned int *)(part->start4)),
-                                  swab32(*(unsigned int *)(part->size4)),
+                                  le32_to_cpu(*(unsigned int *)part->start4),
+                                  le32_to_cpu(*(unsigned int *)part->size4),
                                   512 /*blksize*/,
                                   part->sys_ind /* partition type */ );
          }
@@ -434,18 +432,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;
-}
 
 
 /*