From: Paul Nasrat Date: Thu, 15 Feb 2007 12:24:28 +0000 (+0000) Subject: Determine last ext3 LBA to fix wild LBA reads X-Git-Tag: yaboot-1.3.14rc2~19 X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=commitdiff_plain;h=3a57377b5279a98ad98ef4b535eb0516099bc737 Determine last ext3 LBA to fix wild LBA reads Signed-off-by: Doug Maxey Cc: Ben Herrenschmidt --- diff --git a/second/fs_ext2.c b/second/fs_ext2.c index 729e2f4..3240ce2 100644 --- a/second/fs_ext2.c +++ b/second/fs_ext2.c @@ -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) { diff --git a/second/partition.c b/second/partition.c index 12942a9..0cb8ae8 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... @@ -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; -} /*