summaryrefslogtreecommitdiff
path: root/grub/ext4.patch
blob: 8a2f9bdb0a7915796444c231a38cf792a4740298 (plain)
    1 diff -ruNp grub-0.97/stage2/fsys_ext2fs.c grub-0.97-patch/stage2/fsys_ext2fs.c
    2 --- grub-0.97/stage2/fsys_ext2fs.c      2004-08-08 20:19:18.000000000 +0200
    3 +++ grub-0.97-patch/stage2/fsys_ext2fs.c        2007-12-29 16:25:19.000000000 
    4 +0100
    5 @@ -51,6 +51,9 @@ typedef unsigned int __u32;
    6  #define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
    7  #define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
    8  
    9 +/* Inode flags */
   10 +#define EXT4_EXTENTS_FL                 0x00080000 /* Inode uses extents */
   11 +
   12  /* include/linux/ext2_fs.h */
   13  struct ext2_super_block
   14    {
   15 @@ -191,6 +194,42 @@ struct ext2_dir_entry
   16  #define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \
   17                                           ~EXT2_DIR_ROUND)
   18  
   19 +/* linux/ext4_fs_extents.h */
   20 +/*
   21 + * This is the extent on-disk structure.
   22 + * It's used at the bottom of the tree.
   23 + */
   24 +struct ext4_extent {
   25 +    __u32 ee_block;       /* first logical block extent covers */
   26 +    __u16 ee_len;         /* number of blocks covered by extent */
   27 +    __u16 ee_start_hi;    /* high 16 bits of physical block */
   28 +    __u32 ee_start;       /* low 32 bits of physical block */
   29 +};
   30 +
   31 +/*
   32 + * This is index on-disk structure.
   33 + * It's used at all the levels except the bottom.
   34 + */
   35 +struct ext4_extent_idx {
   36 +    __u32 ei_block;       /* index covers logical blocks from 'block' */
   37 +    __u32 ei_leaf;        /* pointer to the physical block of the next *
   38 +                                 * level. leaf or next index could be there */
   39 +    __u16 ei_leaf_hi;     /* high 16 bits of physical block */
   40 +    __u16 ei_unused;
   41 +};
   42 +
   43 +/*
   44 + * Each block (leaves and indexes), even inode-stored has header.
   45 + */
   46 +struct ext4_extent_header {
   47 +    __u16  eh_magic;       /* probably will support different formats */
   48 +    __u16  eh_entries;     /* number of valid entries */
   49 +    __u16  eh_max;         /* capacity of store in entries */
   50 +    __u16  eh_depth;       /* has tree real underlying blocks? */
   51 +    __u32  eh_generation;  /* generation of the tree */
   52 +};
   53 +
   54 +#define EXT4_EXT_MAGIC          0xf30a
   55  
   56  /* ext2/super.c */
   57  #define log2(n) ffz(~(n))
   58 @@ -279,6 +318,26 @@ ext2_rdfsb (int fsblock, int buffer)
   59                   EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
   60  }
   61  
   62 +/* Walk through extents index tree to find the good leaf */
   63 +static struct ext4_extent_header * 
   64 +ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block)
   65 +{
   66 +  int i;
   67 +  struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1);
   68 +  if (extent_block->eh_magic != EXT4_EXT_MAGIC)
   69 +    return NULL;
   70 +  if (extent_block->eh_depth == 0)
   71 +    return extent_block;
   72 +  for (i = 0; i < extent_block->eh_entries; i++)
   73 +    {
   74 +      if (logical_block < index[i].ei_block)
   75 +        break;
   76 +    }
   77 +  if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1))
   78 +    return NULL;
   79 +  return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block));
   80 +}
   81 +
   82  /* from
   83    ext2/inode.c:ext2_bmap()
   84  */
   85 --- grub-0.97/stage2/fsys_ext2fs.c~	2008-12-28 20:19:00.000000000 +0100
   86 +++ grub-0.97/stage2/fsys_ext2fs.c	2008-12-28 20:19:00.000000000 +0100
   87 @@ -366,83 +366,106 @@
   88      }
   89    printf ("logical block %d\n", logical_block);
   90  #endif /* E2DEBUG */
   91 -
   92 -  /* if it is directly pointed to by the inode, return that physical addr */
   93 -  if (logical_block < EXT2_NDIR_BLOCKS)
   94 -    {
   95 -#ifdef E2DEBUG
   96 -      printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
   97 -      printf ("returning %d\n", INODE->i_block[logical_block]);
   98 -#endif /* E2DEBUG */
   99 -      return INODE->i_block[logical_block];
  100 -    }
  101 -  /* else */
  102 -  logical_block -= EXT2_NDIR_BLOCKS;
  103 -  /* try the indirect block */
  104 -  if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
  105 +  /* standard ext2 inode */
  106 +  if (!(INODE->i_flags & EXT4_EXTENTS_FL))
  107      {
  108 -      if (mapblock1 != 1
  109 -	  && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
  110 -	{
  111 -	  errnum = ERR_FSYS_CORRUPT;
  112 -	  return -1;
  113 -	}
  114 -      mapblock1 = 1;
  115 -      return ((__u32 *) DATABLOCK1)[logical_block];
  116 -    }
  117 -  /* else */
  118 -  logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
  119 -  /* now try the double indirect block */
  120 -  if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
  121 -    {
  122 -      int bnum;
  123 -      if (mapblock1 != 2
  124 -	  && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
  125 -	{
  126 -	  errnum = ERR_FSYS_CORRUPT;
  127 -	  return -1;
  128 -	}
  129 -      mapblock1 = 2;
  130 -      if ((bnum = (((__u32 *) DATABLOCK1)
  131 -		   [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
  132 -	  != mapblock2
  133 -	  && !ext2_rdfsb (bnum, DATABLOCK2))
  134 -	{
  135 -	  errnum = ERR_FSYS_CORRUPT;
  136 -	  return -1;
  137 -	}
  138 -      mapblock2 = bnum;
  139 +      /* if it is directly pointed to by the inode, return that physical addr */
  140 +      if (logical_block < EXT2_NDIR_BLOCKS)
  141 +        {
  142 +#ifdef E2DEBUG
  143 +          printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
  144 +          printf ("returning %d\n", INODE->i_block[logical_block]);
  145 +#endif /* E2DEBUG */
  146 +          return INODE->i_block[logical_block];
  147 +        }
  148 +      /* else */
  149 +      logical_block -= EXT2_NDIR_BLOCKS;
  150 +      /* try the indirect block */
  151 +      if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
  152 +        {
  153 +          if (mapblock1 != 1
  154 +         && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
  155 +       {
  156 +         errnum = ERR_FSYS_CORRUPT;
  157 +         return -1;
  158 +       }
  159 +          mapblock1 = 1;
  160 +          return ((__u32 *) DATABLOCK1)[logical_block];
  161 +        }
  162 +      /* else */
  163 +      logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
  164 +      /* now try the double indirect block */
  165 +      if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
  166 +        {
  167 +          int bnum;
  168 +          if (mapblock1 != 2
  169 +         && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
  170 +       {
  171 +         errnum = ERR_FSYS_CORRUPT;
  172 +         return -1;
  173 +       }
  174 +          mapblock1 = 2;
  175 +          if ((bnum = (((__u32 *) DATABLOCK1)
  176 +                  [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
  177 +         != mapblock2
  178 +         && !ext2_rdfsb (bnum, DATABLOCK2))
  179 +       {
  180 +         errnum = ERR_FSYS_CORRUPT;
  181 +         return -1;
  182 +       }
  183 +          mapblock2 = bnum;
  184 +          return ((__u32 *) DATABLOCK2)
  185 +            [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  186 +        }
  187 +      /* else */
  188 +      mapblock2 = -1;
  189 +      logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
  190 +      if (mapblock1 != 3
  191 +          && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
  192 +        {
  193 +          errnum = ERR_FSYS_CORRUPT;
  194 +          return -1;
  195 +        }
  196 +      mapblock1 = 3;
  197 +      if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
  198 +                  [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
  199 +                                     * 2)],
  200 +                  DATABLOCK2))
  201 +        {
  202 +          errnum = ERR_FSYS_CORRUPT;
  203 +          return -1;
  204 +        }
  205 +      if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
  206 +                  [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
  207 +                   & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
  208 +                  DATABLOCK2))
  209 +        {
  210 +          errnum = ERR_FSYS_CORRUPT;
  211 +          return -1;
  212 +        }
  213        return ((__u32 *) DATABLOCK2)
  214 -	[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  215 -    }
  216 -  /* else */
  217 -  mapblock2 = -1;
  218 -  logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
  219 -  if (mapblock1 != 3
  220 -      && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
  221 -    {
  222 -      errnum = ERR_FSYS_CORRUPT;
  223 -      return -1;
  224 +       [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  225      }
  226 -  mapblock1 = 3;
  227 -  if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
  228 -		   [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
  229 -				      * 2)],
  230 -		   DATABLOCK2))
  231 -    {
  232 -      errnum = ERR_FSYS_CORRUPT;
  233 -      return -1;
  234 -    }
  235 -  if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
  236 -		   [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
  237 -		    & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
  238 -		   DATABLOCK2))
  239 +  /* inode is in extents format */
  240 +  else
  241      {
  242 +      int i;
  243 +      struct ext4_extent_header *extent_hdr = ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block);
  244 +      struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1);
  245 +      if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC)
  246 +      {
  247 +        errnum = ERR_FSYS_CORRUPT;
  248 +        return -1;
  249 +      }
  250 +      for (i = 0; i<extent_hdr->eh_entries; i++)
  251 +        {
  252 +          if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15))
  253 +            return (logical_block - extent[i].ee_block + extent[i].ee_start);
  254 +        }
  255 +      /* We should not arrive here */
  256        errnum = ERR_FSYS_CORRUPT;
  257        return -1;
  258      }
  259 -  return ((__u32 *) DATABLOCK2)
  260 -    [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  261  }
  262  
  263  /* preconditions: all preconds of ext2fs_block_map */

Generated by cgit