Determine last ext3 LBA to fix wild LBA reads
[yaboot.git] / second / fs_reiserfs.c
index f28680fb69514a3bc9636263f7bd60cb8685559a..4ad1c2ec176dbb9bb7495e9550e0d4312c40643e 100644 (file)
@@ -1,49 +1,51 @@
-/* ReiserFS filesystem
-   
-   Copyright (C) 2001 Jeffrey Mahoney (jeffm@suse.com)
-
-   Adapted from GRUB
-
-   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+/*
+ *  fs_reiserfs.c - an implementation for the Reiser filesystem
+ *
+ *  Copyright (C) 2001 Jeffrey Mahoney (jeffm@suse.com)
+ *
+ *  Adapted from Grub
+ *
+ *  Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
 
-*/
 #include "types.h"
 #include "ctype.h"
 #include "string.h"
 #include "stdlib.h"
 #include "fs.h"
+#include "errors.h"
+#include "debug.h"
 #include "reiserfs/reiserfs.h"
 
-
 /* Exported in struct fs_t */
 static int reiserfs_open( struct boot_file_t *file, const char *dev_name,
-    struct partition_t *part, const char *file_name );
+                         struct partition_t *part, const char *file_name );
 static int reiserfs_read( struct boot_file_t *file, unsigned int size,
 
-    void *buffer );
+                         void *buffer );
 static int reiserfs_seek( struct boot_file_t *file, unsigned int newpos );
 static int reiserfs_close( struct boot_file_t *file );
 
 struct fs_t reiserfs_filesystem = {
-    name:"reiserfs",
-    open:reiserfs_open,
-    read:reiserfs_read,
-    seek:reiserfs_seek,
-    close:reiserfs_close
+     name:"reiserfs",
+     open:reiserfs_open,
+     read:reiserfs_read,
+     seek:reiserfs_seek,
+     close:reiserfs_close
 };
 
 static int reiserfs_read_super( void );
@@ -63,202 +65,207 @@ static int
 reiserfs_open( struct boot_file_t *file, const char *dev_name,
                struct partition_t *part, const char *file_name )
 {
-    static char buffer[1024];
-
-    DEBUG_ENTER;
-    DEBUG_OPEN;
-
-    memset( INFO, 0, sizeof(struct reiserfs_state) );
-    INFO->file = file;
-
-    if (part)
-    {
-        DEBUG_F( "Determining offset for partition %d\n", part->part_number );
-        INFO->partition_offset = ((__u64)(part->part_start)) * ((__u64)part->blocksize);
-        DEBUG_F( "%Lu = %lu * %hu\n", INFO->partition_offset,
-                                     part->part_start,
-                                     part->blocksize );
-    }
-    else
-        INFO->partition_offset = 0;
-
-    sprintf( buffer, "%s:%d", dev_name, /*part ? part->part_number :*/ 0 );
-    file->of_device = prom_open( buffer );
-    DEBUG_F( "Trying to open dev_name=%s; filename=%s; partition offset=%Lu\n",
-             buffer, file_name, INFO->partition_offset );
-
-    if ( file->of_device == PROM_INVALID_HANDLE || file->of_device == NULL )
-    {
-       DEBUG_F( "Can't open device %s\n", file->of_device );
-        DEBUG_LEAVE(FILE_ERR_NOTFOUND);
-       return FILE_ERR_NOTFOUND;
-    }
-
-    DEBUG_F( "%s was successfully opened\n" );
-
-    if ( reiserfs_read_super() != 1 )
-    {
-       DEBUG_F( "Couldn't open ReiserFS @ %s/%Lu\n", buffer, INFO->partition_offset );
-       prom_close( file->of_device );
-        DEBUG_LEAVE(FILE_ERR_NOTFOUND);
-       return FILE_ERR_NOTFOUND;
-    }
-
-    DEBUG_F( "Attempting to open %s\n", file_name );
-    strcpy(buffer, file_name); /* reiserfs_open_file modifies argument */
-    if( reiserfs_open_file(buffer) == 0 )
-    {
-        DEBUG_F( "reiserfs_open_file failed. errnum = %d\n", errnum );
-        prom_close( file->of_device );
-        DEBUG_LEAVE(FILE_ERR_NOTFOUND);
-        return FILE_ERR_NOTFOUND;
-    }
-
-    DEBUG_F( "Successfully opened %s\n", file_name );
-
-    DEBUG_LEAVE(FILE_ERR_OK);
-    return FILE_ERR_OK;
+     static char buffer[1024];
+
+     DEBUG_ENTER;
+     DEBUG_OPEN;
+
+     memset( INFO, 0, sizeof(struct reiserfs_state) );
+     INFO->file = file;
+
+     if (part)
+     {
+         DEBUG_F( "Determining offset for partition %d\n", part->part_number );
+         INFO->partition_offset = ((uint64_t)part->part_start) * part->blocksize;
+         DEBUG_F( "%Lu = %lu * %hu\n", INFO->partition_offset,
+                  part->part_start,
+                  part->blocksize );
+     }
+     else
+         INFO->partition_offset = 0;
+
+     sprintf( buffer, "%s:%d", dev_name, 0 ); /* 0 is full disk in OF */
+     file->of_device = prom_open( buffer );
+     DEBUG_F( "Trying to open dev_name=%s; filename=%s; partition offset=%Lu\n",
+             buffer, file_name, INFO->partition_offset );
+
+     if ( file->of_device == PROM_INVALID_HANDLE || file->of_device == NULL )
+     {
+         DEBUG_F( "Can't open device %p\n", file->of_device );
+         DEBUG_LEAVE(FILE_ERR_BADDEV);
+         return FILE_ERR_BADDEV;
+     }
+
+     DEBUG_F("%p was successfully opened\n", file->of_device);
+
+     if ( reiserfs_read_super() != 1 )
+     {
+         DEBUG_F( "Couldn't open ReiserFS @ %s/%Lu\n", buffer, INFO->partition_offset );
+         prom_close( file->of_device );
+         DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+         return FILE_ERR_BAD_FSYS;
+     }
+
+     DEBUG_F( "Attempting to open %s\n", file_name );
+     strcpy(buffer, file_name); /* reiserfs_open_file modifies argument */
+     if (reiserfs_open_file(buffer) == 0)
+     {
+         DEBUG_F( "reiserfs_open_file failed. errnum = %d\n", errnum );
+         prom_close( file->of_device );
+         DEBUG_LEAVE_F(errnum);
+         return errnum;
+     }
+
+     DEBUG_F( "Successfully opened %s\n", file_name );
+
+     DEBUG_LEAVE(FILE_ERR_OK);
+     DEBUG_SLEEP;
+     return FILE_ERR_OK;
 }
 
 static int
 reiserfs_read( struct boot_file_t *file, unsigned int size, void *buffer )
 {
-    return reiserfs_read_data( buffer, size );
+     return reiserfs_read_data( buffer, size );
 }
 
 static int
 reiserfs_seek( struct boot_file_t *file, unsigned int newpos )
 {
-    file->pos = newpos;
-    return FILE_ERR_OK;
+     file->pos = newpos;
+     return FILE_ERR_OK;
 }
 
 static int
 reiserfs_close( struct boot_file_t *file )
 {
-    if( file->of_device )
-    {
-        prom_close(file->of_device);
-        file->of_device = 0;
-    }
-    return FILE_ERR_OK;
+     if( file->of_device )
+     {
+         prom_close(file->of_device);
+         file->of_device = 0;
+         DEBUG_F("reiserfs_close called\n");
+     }
+     return FILE_ERR_OK;
 }
 
 
 static __inline__ __u32
 log2( __u32 word )
 {
-    int i = 0;
-    while( word && (word & (1 << ++i)) == 0 );
-    return i;
+     int i = 0;
+     while( word && (word & (1 << ++i)) == 0 );
+     return i;
 }
 
 static __inline__ int
 is_power_of_two( unsigned long word )
 {
-    return ( word & -word ) == word;
+     return ( word & -word ) == word;
 }
 
 static int
 read_disk_block( struct boot_file_t *file, __u32 block, __u32 start,
                  __u32 length, void *buf )
 {
-    __u16 fs_blocksize = INFO->blocksize == 0 ? REISERFS_OLD_BLOCKSIZE
-                                              : INFO->blocksize;
-    unsigned long long pos = block * fs_blocksize;
-    pos += INFO->partition_offset + start;
-    DEBUG_F( "Reading %lu bytes, starting at block %lu, disk offset %Lu\n",
-             length, block, pos );
-    prom_lseek( file->of_device, pos );
-    return prom_read( file->of_device, buf, length );
+     __u16 fs_blocksize = INFO->blocksize == 0 ? REISERFS_OLD_BLOCKSIZE
+         : INFO->blocksize;
+     unsigned long long pos = (unsigned long long)block * (unsigned long long)fs_blocksize;
+     pos += (unsigned long long)INFO->partition_offset + (unsigned long long)start;
+     DEBUG_F( "Reading %u bytes, starting at block %u, disk offset %Lu\n",
+             length, block, pos );
+     if (!prom_lseek( file->of_device, pos )) {
+         DEBUG_F("prom_lseek failed\n");
+         return 0;
+     }
+     return prom_read( file->of_device, buf, length );
 }
 
 
 static int
 journal_read( __u32 block, __u32 len, char *buffer )
 {
-    return read_disk_block( INFO->file,
-                      (INFO->journal_block + block), 0,
-                       len, buffer );
+     return read_disk_block( INFO->file,
+                            (INFO->journal_block + block), 0,
+                            len, buffer );
 }
 
 /* Read a block from ReiserFS file system, taking the journal into
  * account.  If the block nr is in the journal, the block from the
- * journal taken.  
+ * journal taken.
  */
 static int
 block_read( __u32 blockNr, __u32 start, __u32 len, char *buffer )
 {
-    __u32 transactions = INFO->journal_transactions;
-    __u32 desc_block = INFO->journal_first_desc;
-    __u32 journal_mask = INFO->journal_block_count - 1;
-    __u32 translatedNr = blockNr;
-    __u32 *journal_table = JOURNAL_START;
+     __u32 transactions = INFO->journal_transactions;
+     __u32 desc_block = INFO->journal_first_desc;
+     __u32 journal_mask = INFO->journal_block_count - 1;
+     __u32 translatedNr = blockNr;
+     __u32 *journal_table = JOURNAL_START;
 
 //    DEBUG_F( "block_read( %u, %u, %u, ..)\n", blockNr, start, len );
 
-    while ( transactions-- > 0 )
-    {
-       int i = 0;
-       int j_len;
-
-       if ( *journal_table != 0xffffffff )
-       {
-           /* Search for the blockNr in cached journal */
-           j_len = le32_to_cpu(*journal_table++);
-           while ( i++ < j_len )
-           {
-               if ( le32_to_cpu(*journal_table++) == blockNr )
-               {
-                   journal_table += j_len - i;
-                   goto found;
-               }
-           }
-       }
-       else
-       {
-           /* This is the end of cached journal marker.  The remaining
-            * transactions are still on disk. */
-           struct reiserfs_journal_desc desc;
-           struct reiserfs_journal_commit commit;
-
-           if ( !journal_read( desc_block, sizeof(desc), (char *) &desc ) )
-               return 0;
-
-           j_len = le32_to_cpu(desc.j_len);
-           while ( i < j_len && i < JOURNAL_TRANS_HALF )
-               if ( le32_to_cpu(desc.j_realblock[i++]) == blockNr )
-                   goto found;
+     while ( transactions-- > 0 )
+     {
+         int i = 0;
+         int j_len;
+
+         if ( *journal_table != 0xffffffff )
+         {
+              /* Search for the blockNr in cached journal */
+              j_len = le32_to_cpu(*journal_table++);
+              while ( i++ < j_len )
+              {
+                   if ( le32_to_cpu(*journal_table++) == blockNr )
+                   {
+                        journal_table += j_len - i;
+                        goto found;
+                   }
+              }
+         }
+         else
+         {
+              /* This is the end of cached journal marker.  The remaining
+               * transactions are still on disk. */
+              struct reiserfs_journal_desc desc;
+              struct reiserfs_journal_commit commit;
+
+              if ( !journal_read( desc_block, sizeof(desc), (char *) &desc ) )
+                   return 0;
 
-           if ( j_len >= JOURNAL_TRANS_HALF )
-           {
-               int commit_block = ( desc_block + 1 + j_len ) & journal_mask;
+              j_len = le32_to_cpu(desc.j_len);
+              while ( i < j_len && i < JOURNAL_TRANS_HALF )
+                   if ( le32_to_cpu(desc.j_realblock[i++]) == blockNr )
+                        goto found;
 
-               if ( !journal_read( commit_block,
-                       sizeof(commit), (char *) &commit ) )
-                   return 0;
+              if ( j_len >= JOURNAL_TRANS_HALF )
+              {
+                   int commit_block = ( desc_block + 1 + j_len ) & journal_mask;
+
+                   if ( !journal_read( commit_block,
+                                       sizeof(commit), (char *) &commit ) )
+                        return 0;
 
-               while ( i < j_len )
-                   if ( le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr )
-                       goto found;
-           }
-       }
-       goto not_found;
+                   while ( i < j_len )
+                        if ( le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr )
+                             goto found;
+              }
+         }
+         goto not_found;
 
-      found:
-       translatedNr =
-           INFO->journal_block + ( ( desc_block + i ) & journal_mask );
+     found:
+         translatedNr =
+              INFO->journal_block + ( ( desc_block + i ) & journal_mask );
 
-       DEBUG_F( "block_read: block %u is mapped to journal block %u.\n",
-           blockNr, translatedNr - INFO->journal_block );
+         DEBUG_F( "block_read: block %u is mapped to journal block %u.\n",
+                  blockNr, translatedNr - INFO->journal_block );
 
-       /* We must continue the search, as this block may be overwritten in 
-        * later transactions. */
-      not_found:
-       desc_block = (desc_block + 2 + j_len) & journal_mask;
-    }
+         /* We must continue the search, as this block may be overwritten in
+          * later transactions. */
+     not_found:
+         desc_block = (desc_block + 2 + j_len) & journal_mask;
+     }
 
-    return read_disk_block( INFO->file, translatedNr, start, len, buffer );
+     return read_disk_block( INFO->file, translatedNr, start, len, buffer );
 }
 
 /* Init the journal data structure.  We try to cache as much as
@@ -266,221 +273,228 @@ block_read( __u32 blockNr, __u32 start, __u32 len, char *buffer )
  * we can still read the rest from the disk on demand.
  *
  * The first number of valid transactions and the descriptor block of the
- * first valid transaction are held in INFO.  The transactions are all 
- * adjacent, but we must take care of the journal wrap around. 
+ * first valid transaction are held in INFO.  The transactions are all
+ * adjacent, but we must take care of the journal wrap around.
  */
 static int
 journal_init( void )
 {
-    struct reiserfs_journal_header header;
-    struct reiserfs_journal_desc desc;
-    struct reiserfs_journal_commit commit;
-    __u32 block_count = INFO->journal_block_count;
-    __u32 desc_block;
-    __u32 commit_block;
-    __u32 next_trans_id;
-    __u32 *journal_table = JOURNAL_START;
-
-    journal_read( block_count, sizeof ( header ), ( char * ) &header );
-    desc_block = le32_to_cpu(header.j_first_unflushed_offset);
-    if ( desc_block >= block_count )
-       return 0;
-
-    INFO->journal_transactions = 0;
-    INFO->journal_first_desc = desc_block;
-    next_trans_id = le32_to_cpu(header.j_last_flush_trans_id) + 1;
-
-    DEBUG_F( "journal_init: last flushed %u\n", le32_to_cpu(header.j_last_flush_trans_id) );
-
-    while ( 1 )
-    {
-       journal_read( desc_block, sizeof(desc), (char *) &desc );
-       if ( strcmp( JOURNAL_DESC_MAGIC, desc.j_magic ) != 0
-           || desc.j_trans_id != next_trans_id
-           || desc.j_mount_id != header.j_mount_id )
-           /* no more valid transactions */
-           break;
-
-       commit_block = ( desc_block + le32_to_cpu(desc.j_len) + 1 ) & ( block_count - 1 );
-       journal_read( commit_block, sizeof(commit), (char *) &commit );
-       if ( desc.j_trans_id != commit.j_trans_id
-           || desc.j_len != commit.j_len )
-           /* no more valid transactions */
-           break;
-
-
-       DEBUG_F( "Found valid transaction %u/%u at %u.\n",
-           le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
-            desc_block );
-
-
-       next_trans_id++;
-       if ( journal_table < JOURNAL_END )
-       {
-           if ( ( journal_table + 1 + le32_to_cpu(desc.j_len) ) >= JOURNAL_END )
-           {
-               /* The table is almost full; mark the end of the cached * *
-                * journal. */
-               *journal_table = 0xffffffff;
-               journal_table = JOURNAL_END;
-           }
-           else
-           {
-               int i;
-
-               /* Cache the length and the realblock numbers in the table. * 
-                * The block number of descriptor can easily be computed. *
-                * and need not to be stored here. */
-               *journal_table++ = desc.j_len;
-               for ( i = 0; i < le32_to_cpu(desc.j_len) && i < JOURNAL_TRANS_HALF; i++ )
-               {
-                   *journal_table++ = desc.j_realblock[i];
-
-                   DEBUG_F( "block %u is in journal %u.\n",
-                       le32_to_cpu(desc.j_realblock[i]), desc_block );
-
-               }
-               for ( ; i < le32_to_cpu(desc.j_len); i++ )
-               {
-                   *journal_table++ =
-                       commit.j_realblock[i - JOURNAL_TRANS_HALF];
-
-                   DEBUG_F( "block %u is in journal %u.\n",
-                       le32_to_cpu(commit.j_realblock[i - JOURNAL_TRANS_HALF]),
-                       desc_block );
-
-               }
-           }
-       }
-       desc_block = (commit_block + 1) & (block_count - 1);
-    }
-
-    DEBUG_F( "Transaction %u/%u at %u isn't valid.\n",
-       le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
-        desc_block );
-
-
-    INFO->journal_transactions
-       = next_trans_id - le32_to_cpu(header.j_last_flush_trans_id) - 1;
-    return errnum == 0;
+     struct reiserfs_journal_header header;
+     struct reiserfs_journal_desc desc;
+     struct reiserfs_journal_commit commit;
+     __u32 block_count = INFO->journal_block_count;
+     __u32 desc_block;
+     __u32 commit_block;
+     __u32 next_trans_id;
+     __u32 *journal_table = JOURNAL_START;
+
+     journal_read( block_count, sizeof ( header ), ( char * ) &header );
+     desc_block = le32_to_cpu(header.j_first_unflushed_offset);
+     if ( desc_block >= block_count )
+         return 0;
+
+     INFO->journal_transactions = 0;
+     INFO->journal_first_desc = desc_block;
+     next_trans_id = le32_to_cpu(header.j_last_flush_trans_id) + 1;
+
+     DEBUG_F( "journal_init: last flushed %u\n", le32_to_cpu(header.j_last_flush_trans_id) );
+
+     while ( 1 )
+     {
+         journal_read( desc_block, sizeof(desc), (char *) &desc );
+         if ( strcmp( JOURNAL_DESC_MAGIC, desc.j_magic ) != 0
+              || desc.j_trans_id != next_trans_id
+              || desc.j_mount_id != header.j_mount_id )
+              /* no more valid transactions */
+              break;
+
+         commit_block = ( desc_block + le32_to_cpu(desc.j_len) + 1 ) & ( block_count - 1 );
+         journal_read( commit_block, sizeof(commit), (char *) &commit );
+         if ( desc.j_trans_id != commit.j_trans_id
+              || desc.j_len != commit.j_len )
+              /* no more valid transactions */
+              break;
+
+
+         DEBUG_F( "Found valid transaction %u/%u at %u.\n",
+                  le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
+                  desc_block );
+
+
+         next_trans_id++;
+         if ( journal_table < JOURNAL_END )
+         {
+              if ( ( journal_table + 1 + le32_to_cpu(desc.j_len) ) >= JOURNAL_END )
+              {
+                   /* The table is almost full; mark the end of the cached * *
+                    * journal. */
+                   *journal_table = 0xffffffff;
+                   journal_table = JOURNAL_END;
+              }
+              else
+              {
+                   int i;
+
+                   /* Cache the length and the realblock numbers in the table. *
+                    * The block number of descriptor can easily be computed. *
+                    * and need not to be stored here. */
+                   *journal_table++ = desc.j_len;
+                   for ( i = 0; i < le32_to_cpu(desc.j_len) && i < JOURNAL_TRANS_HALF; i++ )
+                   {
+                        *journal_table++ = desc.j_realblock[i];
+
+                        DEBUG_F( "block %u is in journal %u.\n",
+                                 le32_to_cpu(desc.j_realblock[i]), desc_block );
+
+                   }
+                   for ( ; i < le32_to_cpu(desc.j_len); i++ )
+                   {
+                        *journal_table++ =
+                             commit.j_realblock[i - JOURNAL_TRANS_HALF];
+
+                        DEBUG_F( "block %u is in journal %u.\n",
+                                 le32_to_cpu(commit.j_realblock[i - JOURNAL_TRANS_HALF]),
+                                 desc_block );
+
+                   }
+              }
+         }
+         desc_block = (commit_block + 1) & (block_count - 1);
+     }
+
+     DEBUG_F( "Transaction %u/%u at %u isn't valid.\n",
+             le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
+             desc_block );
+
+
+     INFO->journal_transactions
+         = next_trans_id - le32_to_cpu(header.j_last_flush_trans_id) - 1;
+     return (errnum == 0);
 }
 
 /* check filesystem types and read superblock into memory buffer */
 static int
 reiserfs_read_super( void )
 {
-    struct reiserfs_super_block super;
-    __u64 superblock = REISERFS_SUPERBLOCK_BLOCK;
-
-    read_disk_block( INFO->file, superblock, 0, sizeof(super), &super );
-
-    DEBUG_F( "Found super->magic %s\n", super.s_magic );
-
-    if( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
-        strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
-    {
-       /* Try old super block position */
-       superblock = REISERFS_OLD_SUPERBLOCK_BLOCK;
-       read_disk_block( INFO->file, superblock, 0, sizeof (super),  &super );
-
-       if ( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
-             strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
-       {
-           /* pre journaling super block - untested */
-           if ( strcmp( REISERFS_SUPER_MAGIC_STRING,
-                    (char *) ((__u32) &super + 20 ) ) != 0 )
-               return 0;
-
-           super.s_blocksize = cpu_to_le16(REISERFS_OLD_BLOCKSIZE);
-           super.s_journal_block = 0;
-           super.s_version = 0;
-       }
-    }
-
-    DEBUG_F( "ReiserFS superblock data:\n" );
-    DEBUG_F( "Block count: %lu\n", le32_to_cpu(super.s_block_count) )
-    DEBUG_F( "Free blocks: %lu\n", le32_to_cpu(super.s_free_blocks) );
-    DEBUG_F( "Journal block: %lu\n", le32_to_cpu(super.s_journal_block) );
-    DEBUG_F( "Journal size (in blocks): %lu\n",
-                                    le32_to_cpu(super.s_orig_journal_size) );
-    DEBUG_F( "Root block: %lu\n\n", le32_to_cpu(super.s_root_block) );
-
-
-    INFO->version = le16_to_cpu(super.s_version);
-    INFO->blocksize = le16_to_cpu(super.s_blocksize);
-    INFO->blocksize_shift = log2( INFO->blocksize );
-
-    INFO->journal_block = le32_to_cpu(super.s_journal_block);
-    INFO->journal_block_count = le32_to_cpu(super.s_orig_journal_size);
-
-    INFO->cached_slots = (FSYSREISER_CACHE_SIZE >> INFO->blocksize_shift) - 1;
-
-    /* At this point, we've found a valid superblock. If we run into problems
-     * mounting the FS, the user should probably know. */
-
-    /* A few sanity checks ... */
-    if ( INFO->version > REISERFS_MAX_SUPPORTED_VERSION )
-    {
-        prom_printf( "ReiserFS: Unsupported version field: %u\n",
-                     INFO->version );
-       return 0;
-    }
-
-    if ( INFO->blocksize < FSYSREISER_MIN_BLOCKSIZE
-       || INFO->blocksize > FSYSREISER_MAX_BLOCKSIZE )
-    {
-        prom_printf( "ReiserFS: Unsupported block size: %u\n",
-                     INFO->blocksize );
-       return 0;
-    }
-
-    /* Setup the journal.. */
-    if ( INFO->journal_block != 0 )
-    {
-       if ( !is_power_of_two( INFO->journal_block_count ) )
-        {
-            prom_printf( "ReiserFS: Unsupported journal size, "
-                         "not a power of 2: %lu\n",
-                         INFO->journal_block_count );
-           return 0;
-        }
-
-       journal_init();
-       /* Read in super block again, maybe it is in the journal */
-       block_read( superblock, 0, sizeof (struct reiserfs_super_block),
-                    (char *) &super );
-    }
-
-    /* Read in the root block */
-    if ( !block_read( le32_to_cpu(super.s_root_block), 0,
-            INFO->blocksize, ROOT ) )
-    {
-        prom_printf( "ReiserFS: Failed to read in root block\n" );
-       return 0;
-    }
-
-    /* The root node is always the "deepest", so we can
-       determine the hieght of the tree using it. */
-    INFO->tree_depth = blkh_level(BLOCKHEAD(ROOT));
-
-
-    DEBUG_F( "root read_in: block=%u, depth=%u\n",
-       le32_to_cpu(super.s_root_block), INFO->tree_depth );
-
-    if ( INFO->tree_depth >= REISERFS_MAX_TREE_HEIGHT )
-    {
-        prom_printf( "ReiserFS: Unsupported tree depth (too deep): %u\n",
-                 INFO->tree_depth );
-       return 0;
-    }
-
-    if ( INFO->tree_depth == BLKH_LEVEL_LEAF )
-    {
-       /* There is only one node in the whole filesystem, which is
-          simultanously leaf and root */
-       memcpy( LEAF, ROOT, INFO->blocksize );
-    }
-    return 1;
+     struct reiserfs_super_block super;
+     __u64 superblock = REISERFS_SUPERBLOCK_BLOCK;
+
+     if (read_disk_block(INFO->file, superblock, 0, sizeof(super), &super) != sizeof(super)) {
+         DEBUG_F("read_disk_block failed!\n");
+         return 0;
+     }
+
+     DEBUG_F( "Found super->magic: \"%s\"\n", super.s_magic );
+
+     if( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
+        strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
+     {
+         /* Try old super block position */
+         superblock = REISERFS_OLD_SUPERBLOCK_BLOCK;
+
+         if (read_disk_block( INFO->file, superblock, 0, sizeof (super),  &super ) != sizeof(super)) {
+              DEBUG_F("read_disk_block failed!\n");
+              return 0;
+         }
+
+         if ( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
+              strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
+         {
+              /* pre journaling super block - untested */
+              if ( strcmp( REISERFS_SUPER_MAGIC_STRING,
+                           (char *) ((__u32) &super + 20 ) ) != 0 )
+                   return 0;
+
+              super.s_blocksize = cpu_to_le16(REISERFS_OLD_BLOCKSIZE);
+              super.s_journal_block = 0;
+              super.s_version = 0;
+         }
+     }
+
+     DEBUG_F( "ReiserFS superblock data:\n" );
+     DEBUG_F( "Block count: %u\n", le32_to_cpu(super.s_block_count) )
+         DEBUG_F( "Free blocks: %u\n", le32_to_cpu(super.s_free_blocks) );
+     DEBUG_F( "Journal block: %u\n", le32_to_cpu(super.s_journal_block) );
+     DEBUG_F( "Journal size (in blocks): %u\n",
+             le32_to_cpu(super.s_orig_journal_size) );
+     DEBUG_F( "Root block: %u\n\n", le32_to_cpu(super.s_root_block) );
+
+
+     INFO->version = le16_to_cpu(super.s_version);
+     INFO->blocksize = le16_to_cpu(super.s_blocksize);
+     INFO->blocksize_shift = log2( INFO->blocksize );
+
+     INFO->journal_block = le32_to_cpu(super.s_journal_block);
+     INFO->journal_block_count = le32_to_cpu(super.s_orig_journal_size);
+
+     INFO->cached_slots = (FSYSREISER_CACHE_SIZE >> INFO->blocksize_shift) - 1;
+
+     /* At this point, we've found a valid superblock. If we run into problems
+      * mounting the FS, the user should probably know. */
+
+     /* A few sanity checks ... */
+     if ( INFO->version > REISERFS_MAX_SUPPORTED_VERSION )
+     {
+         prom_printf( "ReiserFS: Unsupported version field: %u\n",
+                      INFO->version );
+         return 0;
+     }
+
+     if ( INFO->blocksize < FSYSREISER_MIN_BLOCKSIZE
+         || INFO->blocksize > FSYSREISER_MAX_BLOCKSIZE )
+     {
+         prom_printf( "ReiserFS: Unsupported block size: %u\n",
+                      INFO->blocksize );
+         return 0;
+     }
+
+     /* Setup the journal.. */
+     if ( INFO->journal_block != 0 )
+     {
+         if ( !is_power_of_two( INFO->journal_block_count ) )
+         {
+              prom_printf( "ReiserFS: Unsupported journal size, "
+                           "not a power of 2: %u\n",
+                           INFO->journal_block_count );
+              return 0;
+         }
+
+         journal_init();
+         /* Read in super block again, maybe it is in the journal */
+         block_read( superblock, 0, sizeof (struct reiserfs_super_block),
+                     (char *) &super );
+     }
+
+     /* Read in the root block */
+     if ( !block_read( le32_to_cpu(super.s_root_block), 0,
+                      INFO->blocksize, ROOT ) )
+     {
+         prom_printf( "ReiserFS: Failed to read in root block\n" );
+         return 0;
+     }
+
+     /* The root node is always the "deepest", so we can
+       determine the hieght of the tree using it. */
+     INFO->tree_depth = blkh_level(BLOCKHEAD(ROOT));
+
+
+     DEBUG_F( "root read_in: block=%u, depth=%u\n",
+             le32_to_cpu(super.s_root_block), INFO->tree_depth );
+
+     if ( INFO->tree_depth >= REISERFS_MAX_TREE_HEIGHT )
+     {
+         prom_printf( "ReiserFS: Unsupported tree depth (too deep): %u\n",
+                      INFO->tree_depth );
+         return 0;
+     }
+
+     if ( INFO->tree_depth == BLKH_LEVEL_LEAF )
+     {
+         /* There is only one node in the whole filesystem, which is
+            simultanously leaf and root */
+         memcpy( LEAF, ROOT, INFO->blocksize );
+     }
+     return 1;
 }
 
 /***************** TREE ACCESSING METHODS *****************************/
@@ -491,7 +505,7 @@ reiserfs_read_super( void )
  * My tree node cache is organized as following
  *   0   ROOT node
  *   1   LEAF node  (if the ROOT is also a LEAF it is copied here
- *   2-n other nodes on current path from bottom to top.  
+ *   2-n other nodes on current path from bottom to top.
  *       if there is not enough space in the cache, the top most are
  *       omitted.
  *
@@ -501,7 +515,7 @@ reiserfs_read_super( void )
  *   next_key() gets the next key in tree order.
  *
  * This means, that I can only sequential reads of files are
- * efficient, but this really doesn't hurt for grub.  
+ * efficient, but this really doesn't hurt for grub.
  */
 
 /* Read in the node at the current path and depth into the node cache.
@@ -510,140 +524,141 @@ reiserfs_read_super( void )
 static char *
 read_tree_node( __u32 blockNr, __u16 depth )
 {
-    char *cache = CACHE(depth);
-    int num_cached = INFO->cached_slots;
-
-    if ( depth < num_cached )
-    {
-       /* This is the cached part of the path.
-           Check if same block is needed. */
-       if ( blockNr == INFO->blocks[depth] )
-           return cache;
-    }
-    else
-       cache = CACHE(num_cached);
-
-    DEBUG_F( "  next read_in: block=%u (depth=%u)\n", blockNr, depth );
-
-    if ( !block_read( blockNr, 0, INFO->blocksize, cache ) )
-    {
-        DEBUG_F( "block_read failed\n" );
-       return 0;
-    }
-
-    DEBUG_F( "FOUND: blk_level=%u, blk_nr_item=%u, blk_free_space=%u\n",
-            blkh_level(BLOCKHEAD(cache)),
-            blkh_nr_item(BLOCKHEAD(cache)),
-            le16_to_cpu(BLOCKHEAD(cache)->blk_free_space) );
-
-    /* Make sure it has the right node level */
-    if ( blkh_level(BLOCKHEAD(cache)) != depth )
-    {
-        DEBUG_F( "depth = %u != %u\n", blkh_level(BLOCKHEAD(cache)), depth );
-        DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
-       errnum = FILE_ERR_BAD_FSYS;
-       return 0;
-    }
-
-    INFO->blocks[depth] = blockNr;
-    return cache;
+     char *cache = CACHE(depth);
+     int num_cached = INFO->cached_slots;
+     errnum = 0;
+
+     if ( depth < num_cached )
+     {
+         /* This is the cached part of the path.
+            Check if same block is needed. */
+         if ( blockNr == INFO->blocks[depth] )
+              return cache;
+     }
+     else
+         cache = CACHE(num_cached);
+
+     DEBUG_F( "  next read_in: block=%u (depth=%u)\n", blockNr, depth );
+
+     if ( !block_read( blockNr, 0, INFO->blocksize, cache ) )
+     {
+         DEBUG_F( "block_read failed\n" );
+         return 0;
+     }
+
+     DEBUG_F( "FOUND: blk_level=%u, blk_nr_item=%u, blk_free_space=%u\n",
+             blkh_level(BLOCKHEAD(cache)),
+             blkh_nr_item(BLOCKHEAD(cache)),
+             le16_to_cpu(BLOCKHEAD(cache)->blk_free_space) );
+
+     /* Make sure it has the right node level */
+     if ( blkh_level(BLOCKHEAD(cache)) != depth )
+     {
+         DEBUG_F( "depth = %u != %u\n", blkh_level(BLOCKHEAD(cache)), depth );
+         DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+         errnum = FILE_ERR_BAD_FSYS;
+         return 0;
+     }
+
+     INFO->blocks[depth] = blockNr;
+     return cache;
 }
 
 /* Get the next key, i.e. the key following the last retrieved key in
- * tree order.  INFO->current_ih and 
+ * tree order.  INFO->current_ih and
  * INFO->current_info are adapted accordingly.  */
 static int
 next_key( void )
 {
-    __u16 depth;
-    struct item_head *ih = INFO->current_ih + 1;
-    char *cache;
-
-
-    DEBUG_F( "next_key:\n  old ih: key %u:%u:%u:%u version:%u\n",
-       le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
-       le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
-       le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
-       le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
-       ih_version(INFO->current_ih) );
-
-
-    if ( ih == &ITEMHEAD[blkh_nr_item(BLOCKHEAD( LEAF ))] )
-    {
-       depth = BLKH_LEVEL_LEAF;
-       /* The last item, was the last in the leaf node. * Read in the next
-        * * block */
-       do
-       {
-           if ( depth == INFO->tree_depth )
-           {
-               /* There are no more keys at all. * Return a dummy item with
-                * * MAX_KEY */
-               ih =
-                   ( struct item_head * )
-                   &BLOCKHEAD( LEAF )->blk_right_delim_key;
-               goto found;
-           }
-           depth++;
-
-           DEBUG_F( "  depth=%u, i=%u\n", depth, INFO->next_key_nr[depth] );
-
-       }
-       while ( INFO->next_key_nr[depth] == 0 );
-
-       if ( depth == INFO->tree_depth )
-           cache = ROOT;
-       else if ( depth <= INFO->cached_slots )
-           cache = CACHE( depth );
-       else
-       {
-           cache = read_tree_node( INFO->blocks[depth], --depth );
-           if ( !cache )
-               return 0;
-       }
-
-       do
-       {
-           __u16 nr_item = blkh_nr_item(BLOCKHEAD( cache ));
-           int key_nr = INFO->next_key_nr[depth]++;
-
-
-           DEBUG_F( "  depth=%u, i=%u/%u\n", depth, key_nr, nr_item );
-
-           if ( key_nr == nr_item )
-               /* This is the last item in this block, set the next_key_nr * 
-                * to 0 */
-               INFO->next_key_nr[depth] = 0;
-
-           cache =
-               read_tree_node( dc_block_number( &(DC( cache )[key_nr])),
-               --depth );
-           if ( !cache )
-               return 0;
-       }
-       while ( depth > BLKH_LEVEL_LEAF );
-
-       ih = ITEMHEAD;
-    }
-  found:
-    INFO->current_ih = ih;
-    INFO->current_item = &LEAF[ih_location(ih)];
-
-    DEBUG_F( "  new ih: key %u:%u:%u:%u version:%u\n",
-       le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
-       le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
-       le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
-       le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
-       ih_version(INFO->current_ih) );
-
-    return 1;
+     __u16 depth;
+     struct item_head *ih = INFO->current_ih + 1;
+     char *cache;
+
+
+     DEBUG_F( "next_key:\n  old ih: key %u:%u:%u:%u version:%u\n",
+             le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
+             le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
+             le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
+             le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
+             ih_version(INFO->current_ih) );
+
+
+     if ( ih == &ITEMHEAD[blkh_nr_item(BLOCKHEAD( LEAF ))] )
+     {
+         depth = BLKH_LEVEL_LEAF;
+         /* The last item, was the last in the leaf node. * Read in the next
+          * * block */
+         do
+         {
+              if ( depth == INFO->tree_depth )
+              {
+                   /* There are no more keys at all. * Return a dummy item with
+                    * * MAX_KEY */
+                   ih =
+                        ( struct item_head * )
+                        &BLOCKHEAD( LEAF )->blk_right_delim_key;
+                   goto found;
+              }
+              depth++;
+
+              DEBUG_F( "  depth=%u, i=%u\n", depth, INFO->next_key_nr[depth] );
+
+         }
+         while ( INFO->next_key_nr[depth] == 0 );
+
+         if ( depth == INFO->tree_depth )
+              cache = ROOT;
+         else if ( depth <= INFO->cached_slots )
+              cache = CACHE( depth );
+         else
+         {
+              cache = read_tree_node( INFO->blocks[depth], --depth );
+              if ( !cache )
+                   return 0;
+         }
+
+         do
+         {
+              __u16 nr_item = blkh_nr_item(BLOCKHEAD( cache ));
+              int key_nr = INFO->next_key_nr[depth]++;
+
+
+              DEBUG_F( "  depth=%u, i=%u/%u\n", depth, key_nr, nr_item );
+
+              if ( key_nr == nr_item )
+                   /* This is the last item in this block, set the next_key_nr *
+                    * to 0 */
+                   INFO->next_key_nr[depth] = 0;
+
+              cache =
+                   read_tree_node( dc_block_number( &(DC( cache )[key_nr])),
+                                   --depth );
+              if ( !cache )
+                   return 0;
+         }
+         while ( depth > BLKH_LEVEL_LEAF );
+
+         ih = ITEMHEAD;
+     }
+found:
+     INFO->current_ih = ih;
+     INFO->current_item = &LEAF[ih_location(ih)];
+
+     DEBUG_F( "  new ih: key %u:%u:%u:%u version:%u\n",
+             le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
+             le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
+             le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
+             le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
+             ih_version(INFO->current_ih) );
+
+     return 1;
 }
 
-/* preconditions: reiserfs_read_super already executed, therefore 
+/* preconditions: reiserfs_read_super already executed, therefore
  *   INFO block is valid
- * returns: 0 if error (errnum is set), 
+ * returns: 0 if error (errnum is set),
  *   nonzero iff we were able to find the key successfully.
- * postconditions: on a nonzero return, the current_ih and 
+ * postconditions: on a nonzero return, the current_ih and
  *   current_item fields describe the key that equals the
  *   searched key.  INFO->next_key contains the next key after
  *   the searched key.
@@ -652,374 +667,389 @@ next_key( void )
 static int
 search_stat( __u32 dir_id, __u32 objectid )
 {
-    char *cache;
-    int depth;
-    int nr_item;
-    int i;
-    struct item_head *ih;
-
-
-    DEBUG_F( "search_stat:\n  key %u:%u:0:0\n", le32_to_cpu(dir_id),
-            le32_to_cpu(objectid) );
-
-
-    depth = INFO->tree_depth;
-    cache = ROOT;
-
-    DEBUG_F( "depth = %d\n", depth );
-    while ( depth > BLKH_LEVEL_LEAF )
-    {
-       struct key *key;
-
-       nr_item = blkh_nr_item(BLOCKHEAD( cache ));
+     char *cache;
+     int depth;
+     int nr_item;
+     int i;
+     struct item_head *ih;
+     errnum = 0;
+
+     DEBUG_F( "search_stat:\n  key %u:%u:0:0\n", le32_to_cpu(dir_id),
+             le32_to_cpu(objectid) );
+
+
+     depth = INFO->tree_depth;
+     cache = ROOT;
+
+     DEBUG_F( "depth = %d\n", depth );
+     while ( depth > BLKH_LEVEL_LEAF )
+     {
+         struct key *key;
+
+         nr_item = blkh_nr_item(BLOCKHEAD( cache ));
+
+         key = KEY( cache );
+
+         for ( i = 0; i < nr_item; i++ )
+         {
+              if (le32_to_cpu(key->k_dir_id) > le32_to_cpu(dir_id)
+                  || (key->k_dir_id == dir_id
+                      && (le32_to_cpu(key->k_objectid) > le32_to_cpu(objectid)
+                          || (key->k_objectid == objectid
+                              && (key->u.k_offset_v1.k_offset
+                                  | key->u.k_offset_v1.k_uniqueness) > 0))))
+                   break;
+              key++;
+         }
+
+
+         DEBUG_F( "  depth=%d, i=%d/%d\n", depth, i, nr_item );
+
+         INFO->next_key_nr[depth] = ( i == nr_item ) ? 0 : i + 1;
+         cache = read_tree_node( dc_block_number(&(DC(cache)[i])), --depth );
+         if ( !cache )
+              return 0;
+     }
+
+     /* cache == LEAF */
+     nr_item = blkh_nr_item(BLOCKHEAD(LEAF));
+     ih = ITEMHEAD;
+     DEBUG_F( "nr_item = %d\n", nr_item );
+     for ( i = 0; i < nr_item; i++ )
+     {
+         if ( ih->ih_key.k_dir_id == dir_id
+              && ih->ih_key.k_objectid == objectid
+              && ih->ih_key.u.k_offset_v1.k_offset == 0
+              && ih->ih_key.u.k_offset_v1.k_uniqueness == 0 )
+         {
+
+              DEBUG_F( "  depth=%d, i=%d/%d\n", depth, i, nr_item );
+
+              INFO->current_ih = ih;
+              INFO->current_item = &LEAF[ih_location(ih)];
+
+              return 1;
+         }
+
+         ih++;
+     }
+
+     DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+     errnum = FILE_ERR_BAD_FSYS;
+     return 0;
+}
 
-       key = KEY( cache );
+static int
+reiserfs_read_data( char *buf, __u32 len )
+{
+     __u32 blocksize;
+     __u32 offset;
+     __u32 to_read;
+     char *prev_buf = buf;
+     errnum = 0;
 
-       for ( i = 0; i < nr_item; i++ )
-       {
-          if (le32_to_cpu(key->k_dir_id) > le32_to_cpu(dir_id)
-              || (key->k_dir_id == dir_id
-                  && (le32_to_cpu(key->k_objectid) > le32_to_cpu(objectid)
-                      || (key->k_objectid == objectid
-                          && (key->u.k_offset_v1.k_offset
-                              | key->u.k_offset_v1.k_uniqueness) > 0))))
-               break;
-           key++;
-       }
+     DEBUG_F( "reiserfs_read_data: INFO->file->pos=%Lu len=%u, offset=%Lu\n",
+             INFO->file->pos, len, (__u64) IH_KEY_OFFSET(INFO->current_ih) - 1 );
 
 
-       DEBUG_F( "  depth=%d, i=%d/%d\n", depth, i, nr_item );
+     if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
+         || IH_KEY_OFFSET( INFO->current_ih ) > INFO->file->pos + 1 )
+     {
+         search_stat( INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid );
+         goto get_next_key;
+     }
 
-       INFO->next_key_nr[depth] = ( i == nr_item ) ? 0 : i + 1;
-       cache = read_tree_node( dc_block_number(&(DC(cache)[i])), --depth );
-       if ( !cache )
-           return 0;
-    }
+     while ( errnum == 0 )
+     {
+         if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid )
+              break;
 
-    /* cache == LEAF */
-    nr_item = blkh_nr_item(BLOCKHEAD(LEAF));
-    ih = ITEMHEAD;
-    DEBUG_F( "nr_item = %d\n", nr_item );
-    for ( i = 0; i < nr_item; i++ )
-    {
-       if ( ih->ih_key.k_dir_id == dir_id
-           && ih->ih_key.k_objectid == objectid
-           && ih->ih_key.u.k_offset_v1.k_offset == 0
-           && ih->ih_key.u.k_offset_v1.k_uniqueness == 0 )
-       {
+         offset = INFO->file->pos - IH_KEY_OFFSET( INFO->current_ih ) + 1;
+         blocksize = ih_item_len(INFO->current_ih);
 
-           DEBUG_F( "  depth=%d, i=%d/%d\n", depth, i, nr_item );
 
-           INFO->current_ih = ih;
-           INFO->current_item = &LEAF[ih_location(ih)];
+         DEBUG_F( "  loop: INFO->file->pos=%Lu len=%u, offset=%u blocksize=%u\n",
+                  INFO->file->pos, len, offset, blocksize );
 
-           return 1;
-       }
 
-       ih++;
-    }
+         if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_DIRECT )
+              && offset < blocksize )
+         {
+              to_read = blocksize - offset;
+              if ( to_read > len )
+                   to_read = len;
 
-    DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
-    errnum = FILE_ERR_BAD_FSYS;
-    return 0;
+              memcpy( buf, INFO->current_item + offset, to_read );
+              goto update_buf_len;
+         }
+         else if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_INDIRECT ) )
+         {
+              blocksize = ( blocksize >> 2 ) << INFO->blocksize_shift;
+
+              while ( offset < blocksize )
+              {
+                   __u32 blocknr = le32_to_cpu(((__u32 *)
+                                                INFO->current_item)[offset >> INFO->blocksize_shift]);
+
+                   int blk_offset = offset & (INFO->blocksize - 1);
+
+                   to_read = INFO->blocksize - blk_offset;
+                   if ( to_read > len )
+                        to_read = len;
+
+                   /* Journal is only for meta data.
+                      Data blocks can be read directly without using block_read */
+                   read_disk_block( INFO->file, blocknr, blk_offset, to_read,
+                                    buf );
+
+              update_buf_len:
+                   len -= to_read;
+                   buf += to_read;
+                   offset += to_read;
+                   INFO->file->pos += to_read;
+                   if ( len == 0 )
+                        goto done;
+              }
+         }
+     get_next_key:
+         next_key();
+     }
+done:
+     return (errnum != 0) ? 0 : buf - prev_buf;
 }
 
+
+/* preconditions: reiserfs_read_super already executed, therefore
+ *   INFO block is valid
+ * returns: 0 if error, nonzero iff we were able to find the file successfully
+ * postconditions: on a nonzero return, INFO->fileinfo contains the info
+ *   of the file we were trying to look up, filepos is 0 and filemax is
+ *   the size of the file.
+ */
 static int
-reiserfs_read_data( char *buf, __u32 len )
+reiserfs_open_file( char *dirname )
 {
-    __u32 blocksize;
-    __u32 offset;
-    __u32 to_read;
-    char *prev_buf = buf;
-
+     struct reiserfs_de_head *de_head;
+     char *rest, ch;
+     __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
 
-    DEBUG_F( "reiserfs_read_data: INFO->file->pos=%Lu len=%u, offset=%Lu\n",
-       INFO->file->pos, len, (__u64) IH_KEY_OFFSET(INFO->current_ih) - 1 );
+     char linkbuf[PATH_MAX];   /* buffer for following symbolic links */
+     int link_count = 0;
+     int mode;
+     errnum = 0;
 
+     dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
+     objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
 
-    if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
-       || IH_KEY_OFFSET( INFO->current_ih ) > INFO->file->pos + 1 )
-    {
-       search_stat( INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid );
-       goto get_next_key;
-    }
+     while ( 1 )
+     {
 
-    while ( errnum == 0 )
-    {
-       if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid )
-           break;
+         DEBUG_F( "dirname=%s\n", dirname );
 
-       offset = INFO->file->pos - IH_KEY_OFFSET( INFO->current_ih ) + 1;
-       blocksize = ih_item_len(INFO->current_ih);
+         /* Search for the stat info first. */
+         if ( !search_stat( dir_id, objectid ) )
+              return 0;
 
 
-       DEBUG_F( "  loop: INFO->file->pos=%Lu len=%u, offset=%u blocksize=%u\n",
-           INFO->file->pos, len, offset, blocksize );
+         DEBUG_F( "sd_mode=0%o sd_size=%Lu\n",
+                  sd_mode((struct stat_data *) INFO->current_item ),
+                  sd_size(INFO->current_ih, INFO->current_item ));
 
 
-       if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_DIRECT )
-           && offset < blocksize )
-       {
-           to_read = blocksize - offset;
-           if ( to_read > len )
-               to_read = len;
+         mode = sd_mode((struct stat_data *)INFO->current_item);
 
-            memcpy( buf, INFO->current_item + offset, to_read );
-           goto update_buf_len;
-       }
-       else if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_INDIRECT ) )
-       {
-           blocksize = ( blocksize >> 2 ) << INFO->blocksize_shift;
+         /* If we've got a symbolic link, then chase it. */
+         if ( S_ISLNK( mode ) )
+         {
+              int len = 0;
 
-           while ( offset < blocksize )
-           {
-               __u32 blocknr = le32_to_cpu(((__u32 *)
-                    INFO->current_item)[offset >> INFO->blocksize_shift]);
-
-               int blk_offset = offset & (INFO->blocksize - 1);
+              DEBUG_F("link count = %d\n", link_count);
+              DEBUG_SLEEP;
+              if ( ++link_count > MAX_LINK_COUNT )
+              {
+                   DEBUG_F("Symlink loop\n");
+                   errnum = FILE_ERR_SYMLINK_LOOP;
+                   return 0;
+              }
 
-               to_read = INFO->blocksize - blk_offset;
-               if ( to_read > len )
-                   to_read = len;
+              /* Get the symlink size. */
+              INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
 
-               /* Journal is only for meta data.
-                   Data blocks can be read directly without using block_read */
-               read_disk_block( INFO->file, blocknr, blk_offset, to_read,
-                                 buf );
-
-             update_buf_len:
-               len -= to_read;
-               buf += to_read;
-               offset += to_read;
-               INFO->file->pos += to_read;
-               if ( len == 0 )
-                   goto done;
-           }
-       }
-      get_next_key:
-       next_key();
-    }
-  done:
-    return (errnum != 0) ? 0 : buf - prev_buf;
-}
+              /* Find out how long our remaining name is. */
+              while ( dirname[len] && !isspace( dirname[len] ) )
+                   len++;
 
+              if ( INFO->file->len + len > sizeof ( linkbuf ) - 1 )
+              {
+                   errnum = FILE_ERR_LENGTH;
+                   return 0;
+              }
+
+              /* Copy the remaining name to the end of the symlink data. Note *
+               * that DIRNAME and LINKBUF may overlap! */
+              memmove( linkbuf + INFO->file->len, dirname, len + 1 );
+
+              INFO->fileinfo.k_dir_id = dir_id;
+              INFO->fileinfo.k_objectid = objectid;
+              INFO->file->pos = 0;
+              if ( !next_key()
+                   || reiserfs_read_data( linkbuf, INFO->file->len ) != INFO->file->len ) {
+                   DEBUG_F("reiserfs_open_file - if !next_key || reiserfs_read_data\n");
+                   DEBUG_SLEEP;
+                   errnum = FILE_IOERR;
+                   return 0;
+              }
+
+
+              DEBUG_F( "symlink=%s\n", linkbuf );
+              DEBUG_SLEEP;
+
+              dirname = linkbuf;
+              if ( *dirname == '/' )
+              {
+                   /* It's an absolute link, so look it up in root. */
+                   dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
+                   objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
+              }
+              else
+              {
+                   /* Relative, so look it up in our parent directory. */
+                   dir_id = parent_dir_id;
+                   objectid = parent_objectid;
+              }
+
+              /* Now lookup the new name. */
+              continue;
+         }
+
+         /* if we have a real file (and we're not just printing *
+          * possibilities), then this is where we want to exit */
+
+         if ( !*dirname || isspace( *dirname ) )
+         {
+              if ( !S_ISREG( mode ) )
+              {
+                   errnum = FILE_ERR_BAD_TYPE;
+                   return 0;
+              }
+
+              INFO->file->pos = 0;
+              INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
+
+              INFO->fileinfo.k_dir_id = dir_id;
+              INFO->fileinfo.k_objectid = objectid;
+              return next_key();
+         }
+
+         /* continue with the file/directory name interpretation */
+         while ( *dirname == '/' )
+              dirname++;
+         if ( !S_ISDIR( mode ) )
+         {
+              errnum = FILE_ERR_NOTDIR;
+              return 0;
+         }
+         for ( rest = dirname; ( ch = *rest ) && !isspace( ch ) && ch != '/';
+               rest++ ) ;
+         *rest = 0;
+
+         while ( 1 )
+         {
+              char *name_end;
+              int num_entries;
+
+              if ( !next_key() )
+                   return 0;
 
-/* preconditions: reiserfs_read_super already executed, therefore 
- *   INFO block is valid
- * returns: 0 if error, nonzero iff we were able to find the file successfully
- * postconditions: on a nonzero return, INFO->fileinfo contains the info
- *   of the file we were trying to look up, filepos is 0 and filemax is 
- *   the size of the file.
- */
-static int
-reiserfs_open_file( char *dirname )
-{
-    struct reiserfs_de_head *de_head;
-    char *rest, ch;
-    __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
-
-    char linkbuf[PATH_MAX];    /* buffer for following symbolic links */
-    int link_count = 0;
-    int mode;
-
-    dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
-    objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
-
-    while ( 1 )
-    {
-
-       DEBUG_F( "dirname=%s\n", dirname );
-
-       /* Search for the stat info first. */
-       if ( !search_stat( dir_id, objectid ) )
-           return 0;
-
-
-       DEBUG_F( "sd_mode=0%o sd_size=%u\n",
-           sd_mode((struct stat_data *) INFO->current_item ),
-           sd_size(INFO->current_ih, INFO->current_item ));
-
-
-        mode = sd_mode((struct stat_data *)INFO->current_item);
-
-       /* If we've got a symbolic link, then chase it. */
-       if ( S_ISLNK( mode ) )
-       {
-           int len = 0;
-
-           if ( ++link_count > MAX_LINK_COUNT )
-           {
-               errnum = FILE_ERR_SYMLINK_LOOP;
-               return 0;
-           }
-
-           /* Get the symlink size. */
-            INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
-
-           /* Find out how long our remaining name is. */
-           while ( dirname[len] && !isspace( dirname[len] ) )
-               len++;
-
-           if ( INFO->file->len + len > sizeof ( linkbuf ) - 1 )
-           {
-               errnum = FILE_ERR_LENGTH;
-               return 0;
-           }
-
-           /* Copy the remaining name to the end of the symlink data. Note * 
-            * that DIRNAME and LINKBUF may overlap! */
-           memmove( linkbuf + INFO->file->len, dirname, len + 1 );
-
-           INFO->fileinfo.k_dir_id = dir_id;
-           INFO->fileinfo.k_objectid = objectid;
-           INFO->file->pos = 0;
-           if ( !next_key()
-               || reiserfs_read_data( linkbuf, INFO->file->len ) != INFO->file->len )
-               return 0;
-
-
-           DEBUG_F( "symlink=%s\n", linkbuf );
-
-
-           dirname = linkbuf;
-           if ( *dirname == '/' )
-           {
-               /* It's an absolute link, so look it up in root. */
-               dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
-               objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
-           }
-           else
-           {
-               /* Relative, so look it up in our parent directory. */
-               dir_id = parent_dir_id;
-               objectid = parent_objectid;
-           }
-
-           /* Now lookup the new name. */
-           continue;
-       }
-
-       /* if we have a real file (and we're not just printing *
-        * possibilities), then this is where we want to exit */
-
-       if ( !*dirname || isspace( *dirname ) )
-       {
-           if ( !S_ISREG( mode ) )
-           {
-               errnum = FILE_ERR_BAD_TYPE;
-               return 0;
-           }
-
-           INFO->file->pos = 0;
-            INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
-
-           INFO->fileinfo.k_dir_id = dir_id;
-           INFO->fileinfo.k_objectid = objectid;
-           return next_key();
-       }
-
-       /* continue with the file/directory name interpretation */
-       while ( *dirname == '/' )
-           dirname++;
-       if ( !S_ISDIR( mode ) )
-       {
-           errnum = FILE_ERR_BAD_TYPE;
-           return 0;
-       }
-       for ( rest = dirname; ( ch = *rest ) && !isspace( ch ) && ch != '/';
-           rest++ ) ;
-       *rest = 0;
-
-       while ( 1 )
-       {
-           char *name_end;
-           int num_entries;
-
-           if ( !next_key() )
-               return 0;
-
-           if ( INFO->current_ih->ih_key.k_objectid != objectid )
-               break;
-
-           name_end = INFO->current_item + ih_item_len(INFO->current_ih);
-           de_head = ( struct reiserfs_de_head * ) INFO->current_item;
-           num_entries = ih_entry_count(INFO->current_ih);
-           while ( num_entries > 0 )
-           {
-               char *filename = INFO->current_item + deh_location(de_head);
-               char tmp = *name_end;
-
-                if( deh_state(de_head) & (1 << DEH_Visible))
-               {
-                   int cmp;
-
-                   /* Directory names in ReiserFS are not null * terminated. 
-                    * We write a temporary 0 behind it. * NOTE: that this
-                    * may overwrite the first block in * the tree cache.
-                    * That doesn't hurt as long as we * don't call next_key
-                    * () in between. */
-                   *name_end = 0;
-                   cmp = strcmp( dirname, filename );
-                   *name_end = tmp;
-                   if ( cmp == 0 )
-                       goto found;
-               }
-               /* The beginning of this name marks the end of the next name. 
-                */
-               name_end = filename;
-               de_head++;
-               num_entries--;
-           }
-       }
-
-       errnum = FILE_ERR_NOTFOUND;
-       *rest = ch;
-       return 0;
-
-      found:
-       *rest = ch;
-       dirname = rest;
-
-       parent_dir_id = dir_id;
-       parent_objectid = objectid;
-       dir_id = de_head->deh_dir_id; /* LE */
-       objectid = de_head->deh_objectid; /* LE */
-    }
+              if ( INFO->current_ih->ih_key.k_objectid != objectid )
+                   break;
+
+              name_end = INFO->current_item + ih_item_len(INFO->current_ih);
+              de_head = ( struct reiserfs_de_head * ) INFO->current_item;
+              num_entries = ih_entry_count(INFO->current_ih);
+              while ( num_entries > 0 )
+              {
+                   char *filename = INFO->current_item + deh_location(de_head);
+                   char tmp = *name_end;
+
+                   if( deh_state(de_head) & (1 << DEH_Visible))
+                   {
+                        int cmp;
+
+                        /* Directory names in ReiserFS are not null * terminated.
+                         * We write a temporary 0 behind it. * NOTE: that this
+                         * may overwrite the first block in * the tree cache.
+                         * That doesn't hurt as long as we * don't call next_key
+                         * () in between. */
+                        *name_end = 0;
+                        cmp = strcmp( dirname, filename );
+                        *name_end = tmp;
+                        if ( cmp == 0 )
+                             goto found;
+                   }
+                   /* The beginning of this name marks the end of the next name.
+                    */
+                   name_end = filename;
+                   de_head++;
+                   num_entries--;
+              }
+         }
+
+         errnum = FILE_ERR_NOTFOUND;
+         *rest = ch;
+         return 0;
+
+     found:
+         *rest = ch;
+         dirname = rest;
+
+         parent_dir_id = dir_id;
+         parent_objectid = objectid;
+         dir_id = de_head->deh_dir_id; /* LE */
+         objectid = de_head->deh_objectid; /* LE */
+     }
 }
 
 
 
 #ifndef __LITTLE_ENDIAN
 typedef union {
-    struct offset_v2 offset_v2;
-    __u64 linear;
+     struct offset_v2 offset_v2;
+     __u64 linear;
 } offset_v2_esafe_overlay;
 
 inline __u16
 offset_v2_k_type( struct offset_v2 *v2 )
 {
-    offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
-    tmp.linear = le64_to_cpu( tmp.linear );
-    return tmp.offset_v2.k_type;
+     offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
+     tmp.linear = le64_to_cpu( tmp.linear );
+     return tmp.offset_v2.k_type;
 }
+
 inline loff_t
 offset_v2_k_offset( struct offset_v2 *v2 )
 {
-    offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
-    tmp.linear = le64_to_cpu( tmp.linear );
-    return tmp.offset_v2.k_offset;
+     offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
+     tmp.linear = le64_to_cpu( tmp.linear );
+     return tmp.offset_v2.k_offset;
 }
 #endif
 
 inline int
 uniqueness2type (__u32 uniqueness)
 {
-    switch (uniqueness) {
-    case V1_SD_UNIQUENESS: return TYPE_STAT_DATA;
-    case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT;
-    case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT;
-    case V1_DIRENTRY_UNIQUENESS: return TYPE_DIRENTRY;
-    }
-    return TYPE_ANY;
+     switch (uniqueness) {
+     case V1_SD_UNIQUENESS: return TYPE_STAT_DATA;
+     case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT;
+     case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT;
+     case V1_DIRENTRY_UNIQUENESS: return TYPE_DIRENTRY;
+     }
+     return TYPE_ANY;
 }
+
+/*
+ * Local variables:
+ * c-file-style: "k&r"
+ * c-basic-offset: 5
+ * End:
+ */