source: patches/grub-0.97-ext4-1.patch@ a10f292

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since a10f292 was fd60f98, checked in by Zach Winkles <eikniw@…>, 16 years ago

Add a patch to implement support for ext4 in GRUB.

  • Property mode set to 100644
File size: 9.1 KB
  • stage2/fsys_ext2fs.c

    Submitted By: Zack Winkles (eikniw AT gmail DOT com)
    Date: 2009-02-27
    Initial Package Version: 0.97
    Origin: http://www.mail-archive.com/bug-grub@gnu.org/msg11458.html
    Upstream Status: Not accepted (package no longer maintained)
    Description: Implement support extents, as implemented in ext4.
    
    diff -Naur grub-0.97.orig/stage2/fsys_ext2fs.c grub-0.97/stage2/fsys_ext2fs.c
    old new  
    5151#define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
    5252#define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
    5353
     54/* Inode flags */
     55#define EXT4_EXTENTS_FL                 0x00080000 /* Inode uses extents */
     56
    5457/* include/linux/ext2_fs.h */
    5558struct ext2_super_block
    5659  {
     
    191194#define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \
    192195                                         ~EXT2_DIR_ROUND)
    193196
     197/* linux/ext4_fs_extents.h */
     198/*
     199 * This is the extent on-disk structure.
     200 * It's used at the bottom of the tree.
     201 */
     202struct ext4_extent {
     203    __u32 ee_block;       /* first logical block extent covers */
     204    __u16 ee_len;         /* number of blocks covered by extent */
     205    __u16 ee_start_hi;    /* high 16 bits of physical block */
     206    __u32 ee_start;       /* low 32 bits of physical block */
     207};
     208
     209/*
     210 * This is index on-disk structure.
     211 * It's used at all the levels except the bottom.
     212 */
     213struct ext4_extent_idx {
     214    __u32 ei_block;       /* index covers logical blocks from 'block' */
     215    __u32 ei_leaf;        /* pointer to the physical block of the next *
     216                                 * level. leaf or next index could be there */
     217    __u16 ei_leaf_hi;     /* high 16 bits of physical block */
     218    __u16 ei_unused;
     219};
     220
     221/*
     222 * Each block (leaves and indexes), even inode-stored has header.
     223 */
     224struct ext4_extent_header {
     225    __u16  eh_magic;       /* probably will support different formats */
     226    __u16  eh_entries;     /* number of valid entries */
     227    __u16  eh_max;         /* capacity of store in entries */
     228    __u16  eh_depth;       /* has tree real underlying blocks? */
     229    __u32  eh_generation;  /* generation of the tree */
     230};
     231
     232#define EXT4_EXT_MAGIC          0xf30a
    194233
    195234/* ext2/super.c */
    196235#define log2(n) ffz(~(n))
     
    279318                  EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
    280319}
    281320
     321/* Walk through extents index tree to find the good leaf */
     322static struct ext4_extent_header *
     323ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block)
     324{
     325  int i;
     326  struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1);
     327  if (extent_block->eh_magic != EXT4_EXT_MAGIC)
     328    return NULL;
     329  if (extent_block->eh_depth == 0)
     330    return extent_block;
     331  for (i = 0; i < extent_block->eh_entries; i++)
     332    {
     333      if (logical_block < index[i].ei_block)
     334        break;
     335    }
     336  if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1))
     337    return NULL;
     338  return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block));
     339}
     340
     341
    282342/* from
    283343  ext2/inode.c:ext2_bmap()
    284344*/
     
    287347static int
    288348ext2fs_block_map (int logical_block)
    289349{
    290 
    291350#ifdef E2DEBUG
    292351  unsigned char *i;
    293352  for (i = (unsigned char *) INODE;
     
    308367  printf ("logical block %d\n", logical_block);
    309368#endif /* E2DEBUG */
    310369
    311   /* if it is directly pointed to by the inode, return that physical addr */
    312   if (logical_block < EXT2_NDIR_BLOCKS)
     370  if (!(INODE->i_flags & EXT4_EXTENTS_FL))
    313371    {
    314 #ifdef E2DEBUG
    315       printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
    316       printf ("returning %d\n", INODE->i_block[logical_block]);
    317 #endif /* E2DEBUG */
    318       return INODE->i_block[logical_block];
    319     }
    320   /* else */
    321   logical_block -= EXT2_NDIR_BLOCKS;
    322   /* try the indirect block */
    323   if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
    324     {
    325       if (mapblock1 != 1
    326           && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
    327         {
    328           errnum = ERR_FSYS_CORRUPT;
    329           return -1;
    330         }
    331       mapblock1 = 1;
    332       return ((__u32 *) DATABLOCK1)[logical_block];
    333     }
    334   /* else */
    335   logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
    336   /* now try the double indirect block */
    337   if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
    338     {
    339       int bnum;
    340       if (mapblock1 != 2
    341           && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
    342         {
    343           errnum = ERR_FSYS_CORRUPT;
    344           return -1;
    345         }
    346       mapblock1 = 2;
    347       if ((bnum = (((__u32 *) DATABLOCK1)
    348                    [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
    349           != mapblock2
    350           && !ext2_rdfsb (bnum, DATABLOCK2))
    351         {
    352           errnum = ERR_FSYS_CORRUPT;
    353           return -1;
    354         }
    355       mapblock2 = bnum;
     372      /* if it is directly pointed to by the inode, return that physical addr */
     373      if (logical_block < EXT2_NDIR_BLOCKS)
     374        {
     375#ifdef E2DEBUG
     376          printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
     377          printf ("returning %d\n", INODE->i_block[logical_block]);
     378#endif /* E2DEBUG */
     379          return INODE->i_block[logical_block];
     380        }
     381      /* else */
     382      logical_block -= EXT2_NDIR_BLOCKS;
     383      /* try the indirect block */
     384      if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
     385        {
     386          if (mapblock1 != 1 && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
     387            {
     388              errnum = ERR_FSYS_CORRUPT;
     389              return -1;
     390            }
     391          mapblock1 = 1;
     392          return ((__u32 *) DATABLOCK1)[logical_block];
     393        }
     394      /* else */
     395      logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
     396      /* now try the double indirect block */
     397      if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
     398        {
     399          int bnum;
     400          if (mapblock1 != 2 && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
     401            {
     402              errnum = ERR_FSYS_CORRUPT;
     403              return -1;
     404            }
     405          mapblock1 = 2;
     406          if ((bnum = (((__u32 *) DATABLOCK1)
     407                  [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
     408         != mapblock2
     409         && !ext2_rdfsb (bnum, DATABLOCK2))
     410           {
     411             errnum = ERR_FSYS_CORRUPT;
     412             return -1;
     413           }
     414          mapblock2 = bnum;
     415          return ((__u32 *) DATABLOCK2)
     416            [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
     417        }
     418      /* else */
     419      mapblock2 = -1;
     420      logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
     421      if (mapblock1 != 3
     422          && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
     423        {
     424          errnum = ERR_FSYS_CORRUPT;
     425          return -1;
     426        }
     427      mapblock1 = 3;
     428      if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
     429                  [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
     430                                     * 2)],
     431                  DATABLOCK2))
     432        {
     433          errnum = ERR_FSYS_CORRUPT;
     434          return -1;
     435        }
     436      if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
     437                  [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
     438                   & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
     439                  DATABLOCK2))
     440        {
     441          errnum = ERR_FSYS_CORRUPT;
     442          return -1;
     443        }
     444
    356445      return ((__u32 *) DATABLOCK2)
    357         [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
     446       [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
    358447    }
    359   /* else */
    360   mapblock2 = -1;
    361   logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
    362   if (mapblock1 != 3
    363       && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
    364     {
    365       errnum = ERR_FSYS_CORRUPT;
    366       return -1;
    367     }
    368   mapblock1 = 3;
    369   if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
    370                    [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
    371                                       * 2)],
    372                    DATABLOCK2))
    373     {
    374       errnum = ERR_FSYS_CORRUPT;
    375       return -1;
    376     }
    377   if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
    378                    [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
    379                     & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
    380                    DATABLOCK2))
     448    /* inode is in extents format */
     449    else
    381450    {
     451      int i;
     452      struct ext4_extent_header *extent_hdr =
     453         ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block);
     454      struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1);
     455      if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC)
     456        {
     457          errnum = ERR_FSYS_CORRUPT;
     458          return -1;
     459        }
     460      for (i = 0; i<extent_hdr->eh_entries; i++)
     461        {
     462          if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15))
     463            return (logical_block - extent[i].ee_block + extent[i].ee_start);
     464        }
     465      /* We should not arrive here */
     466
    382467      errnum = ERR_FSYS_CORRUPT;
    383468      return -1;
    384469    }
    385   return ((__u32 *) DATABLOCK2)
    386     [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
    387470}
    388471
    389472/* preconditions: all preconds of ext2fs_block_map */
Note: See TracBrowser for help on using the repository browser.