[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] pygrub: add ext4 support



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1260981764 0
# Node ID c6ee21dca84850447797afba0550f0a61d160601
# Parent  cbcb3d564b2fb51574b8a1d06cd6e7780839c331
pygrub: add ext4 support

This is a port of the following two patches:
  http://patches.ubuntulinux.org/g/grub/extracted/ext4_support.diff
  
http://patches.ubuntulinux.org/g/grub/extracted/ext4_fix_variable_sized_inodes.diff

Signed-off-by: Mark Johnson <mark.johnson@xxxxxxx>
---
 tools/libfsimage/ext2fs/fsys_ext2fs.c |  237 +++++++++++++++++++++++-----------
 1 files changed, 161 insertions(+), 76 deletions(-)

diff -r cbcb3d564b2f -r c6ee21dca848 tools/libfsimage/ext2fs/fsys_ext2fs.c
--- a/tools/libfsimage/ext2fs/fsys_ext2fs.c     Wed Dec 16 12:45:18 2009 +0000
+++ b/tools/libfsimage/ext2fs/fsys_ext2fs.c     Wed Dec 16 16:42:44 2009 +0000
@@ -48,6 +48,9 @@ typedef unsigned int __u32;
 #define EXT2_DIND_BLOCK                 (EXT2_IND_BLOCK + 1)
 #define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
 #define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
+
+/* Inode flags */
+#define EXT4_EXTENTS_FL                 0x00080000 /* Inode uses extents */
 
 /* include/linux/ext2_fs.h */
 struct ext2_super_block
@@ -234,6 +237,42 @@ struct ext2_dir_entry
 #define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \
                                          ~EXT2_DIR_ROUND)
 
+/* linux/ext4_fs_extents.h */
+/*
+ * This is the extent on-disk structure.
+ * It's used at the bottom of the tree.
+ */
+struct ext4_extent {
+    __u32 ee_block;       /* first logical block extent covers */
+    __u16 ee_len;         /* number of blocks covered by extent */
+    __u16 ee_start_hi;    /* high 16 bits of physical block */
+    __u32 ee_start;       /* low 32 bits of physical block */
+};
+
+/*
+ * This is index on-disk structure.
+ * It's used at all the levels except the bottom.
+ */
+struct ext4_extent_idx {
+    __u32 ei_block;       /* index covers logical blocks from 'block' */
+    __u32 ei_leaf;        /* pointer to the physical block of the next *
+                                 * level. leaf or next index could be there */
+    __u16 ei_leaf_hi;     /* high 16 bits of physical block */
+    __u16 ei_unused;
+};
+
+/*
+ * Each block (leaves and indexes), even inode-stored has header.
+ */
+struct ext4_extent_header {
+    __u16  eh_magic;       /* probably will support different formats */
+    __u16  eh_entries;     /* number of valid entries */
+    __u16  eh_max;         /* capacity of store in entries */
+    __u16  eh_depth;       /* has tree real underlying blocks? */
+    __u32  eh_generation;  /* generation of the tree */
+};
+
+#define EXT4_EXT_MAGIC          0xf30a
 
 /* ext2/super.c */
 #define log2(n) grub_log2(n)
@@ -311,6 +350,27 @@ ext2_rdfsb (fsi_file_t *ffi, int fsblock
                  EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
 }
 
+/* Walk through extents index tree to find the good leaf */
+static struct ext4_extent_header *
+ext4_recurse_extent_index(fsi_file_t *ffi, struct ext4_extent_header 
*extent_block, int logical_block)
+{
+  int i;
+  struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 
1);
+  if (extent_block->eh_magic != EXT4_EXT_MAGIC)
+    return NULL;
+  if (extent_block->eh_depth == 0)
+    return extent_block;
+  for (i = 0; i < extent_block->eh_entries; i++)
+    {
+      if (logical_block < index[i].ei_block)
+        break;
+    }
+  if (i == 0 || !ext2_rdfsb(ffi, index[i-1].ei_leaf, DATABLOCK1))
+    return NULL;
+  return (ext4_recurse_extent_index(ffi, (struct ext4_extent_header *) 
DATABLOCK1, logical_block));
+}
+
+
 /* from
   ext2/inode.c:ext2_bmap()
 */
@@ -319,7 +379,6 @@ static int
 static int
 ext2fs_block_map (fsi_file_t *ffi, int logical_block)
 {
-
 #ifdef E2DEBUG
   unsigned char *i;
   for (i = (unsigned char *) INODE;
@@ -340,82 +399,106 @@ ext2fs_block_map (fsi_file_t *ffi, int l
   printf ("logical block %d\n", logical_block);
 #endif /* E2DEBUG */
 
-  /* if it is directly pointed to by the inode, return that physical addr */
-  if (logical_block < EXT2_NDIR_BLOCKS)
+  if (!(INODE->i_flags & EXT4_EXTENTS_FL))
+      {
+      /* if it is directly pointed to by the inode, return that physical addr 
*/
+      if (logical_block < EXT2_NDIR_BLOCKS)
+        {
+#ifdef E2DEBUG
+          printf ("returning %d\n", (unsigned char *) 
(INODE->i_block[logical_block]));
+          printf ("returning %d\n", INODE->i_block[logical_block]);
+#endif /* E2DEBUG */
+          return INODE->i_block[logical_block];
+        }
+      /* else */
+      logical_block -= EXT2_NDIR_BLOCKS;
+      /* try the indirect block */
+      if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
+        {
+          if (mapblock1 != 1 && !ext2_rdfsb (ffi, 
INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
+            {
+              errnum = ERR_FSYS_CORRUPT;
+              return -1;
+            }
+          mapblock1 = 1;
+          return ((__u32 *) DATABLOCK1)[logical_block];
+        }
+      /* else */
+      logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
+      /* now try the double indirect block */
+      if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
+        {
+          int bnum;
+          if (mapblock1 != 2 && !ext2_rdfsb (ffi, 
INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
+            {
+              errnum = ERR_FSYS_CORRUPT;
+              return -1;
+            }
+          mapblock1 = 2;
+          if ((bnum = (((__u32 *) DATABLOCK1)
+                  [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
+         != mapblock2
+         && !ext2_rdfsb (ffi, bnum, DATABLOCK2))
+           {
+             errnum = ERR_FSYS_CORRUPT;
+             return -1;
+           }
+          mapblock2 = bnum;
+          return ((__u32 *) DATABLOCK2)
+            [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
+        }
+      /* else */
+      mapblock2 = -1;
+      logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
+      if (mapblock1 != 3
+          && !ext2_rdfsb (ffi, INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
+        {
+          errnum = ERR_FSYS_CORRUPT;
+          return -1;
+        }
+      mapblock1 = 3;
+      if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK1)
+                  [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
+                                     * 2)],
+                  DATABLOCK2))
+        {
+          errnum = ERR_FSYS_CORRUPT;
+          return -1;
+        }
+      if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK2)
+                  [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
+                   & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
+                  DATABLOCK2))
+        {
+          errnum = ERR_FSYS_CORRUPT;
+          return -1;
+        }
+
+      return ((__u32 *) DATABLOCK2)
+       [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
+    }
+    /* inode is in extents format */
+    else
     {
-#ifdef E2DEBUG
-      printf ("returning %d\n", (unsigned char *) 
(INODE->i_block[logical_block]));
-      printf ("returning %d\n", INODE->i_block[logical_block]);
-#endif /* E2DEBUG */
-      return INODE->i_block[logical_block];
-    }
-  /* else */
-  logical_block -= EXT2_NDIR_BLOCKS;
-  /* try the indirect block */
-  if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
-    {
-      if (mapblock1 != 1
-         && !ext2_rdfsb (ffi, INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
-       {
-         errnum = ERR_FSYS_CORRUPT;
-         return -1;
-       }
-      mapblock1 = 1;
-      return ((__u32 *) DATABLOCK1)[logical_block];
-    }
-  /* else */
-  logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
-  /* now try the double indirect block */
-  if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
-    {
-      int bnum;
-      if (mapblock1 != 2
-         && !ext2_rdfsb (ffi, INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
-       {
-         errnum = ERR_FSYS_CORRUPT;
-         return -1;
-       }
-      mapblock1 = 2;
-      if ((bnum = (((__u32 *) DATABLOCK1)
-                  [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
-         != mapblock2
-         && !ext2_rdfsb (ffi, bnum, DATABLOCK2))
-       {
-         errnum = ERR_FSYS_CORRUPT;
-         return -1;
-       }
-      mapblock2 = bnum;
-      return ((__u32 *) DATABLOCK2)
-       [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
-    }
-  /* else */
-  mapblock2 = -1;
-  logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
-  if (mapblock1 != 3
-      && !ext2_rdfsb (ffi, INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
-    {
+      int i;
+      struct ext4_extent_header *extent_hdr =
+         ext4_recurse_extent_index(ffi, (struct ext4_extent_header *) 
INODE->i_block, logical_block);
+      struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1);
+      if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC)
+        {
+          errnum = ERR_FSYS_CORRUPT;
+          return -1;
+        }
+      for (i = 0; i<extent_hdr->eh_entries; i++)
+        {
+          if (extent[i].ee_block <= logical_block && logical_block < 
extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15))
+            return (logical_block - extent[i].ee_block + extent[i].ee_start);
+        }
+      /* We should not arrive here */
+
       errnum = ERR_FSYS_CORRUPT;
       return -1;
     }
-  mapblock1 = 3;
-  if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK1)
-                  [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
-                                     * 2)],
-                  DATABLOCK2))
-    {
-      errnum = ERR_FSYS_CORRUPT;
-      return -1;
-    }
-  if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK2)
-                  [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
-                   & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
-                  DATABLOCK2))
-    {
-      errnum = ERR_FSYS_CORRUPT;
-      return -1;
-    }
-  return ((__u32 *) DATABLOCK2)
-    [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
 }
 
 /* preconditions: all preconds of ext2fs_block_map */
@@ -548,6 +631,8 @@ ext2fs_dir (fsi_file_t *ffi, char *dirna
   int off;                     /* offset within block of directory entry (off 
mod blocksize) */
   int loc;                     /* location within a directory */
   int blk;                     /* which data blk within dir entry (off div 
blocksize) */
+  int inodes_per_block;                /* number of inodes in each block */
+  int inode_offset;            /* inode offset in block */
   long map;                    /* fs pointer of a particular block from dir 
entry */
   struct ext2_dir_entry *dp;   /* pointer to directory entry */
 #ifdef E2DEBUG
@@ -583,9 +668,9 @@ ext2fs_dir (fsi_file_t *ffi, char *dirna
          return 0;
        }
       gdp = GROUP_DESC;
-      ino_blk = gdp[desc].bg_inode_table +
-       (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
-        >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
+      inodes_per_block =  EXT2_BLOCK_SIZE (SUPERBLOCK) / 
EXT2_INODE_SIZE(SUPERBLOCK);
+      inode_offset = ((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group));
+      ino_blk = gdp[desc].bg_inode_table + (inode_offset / inodes_per_block);
 #ifdef E2DEBUG
       printf ("inode table fsblock=%d\n", ino_blk);
 #endif /* E2DEBUG */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.