WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] pygrub: add ext4 support
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 16 Dec 2009 08:50:13 -0800
Delivery-date: Wed, 16 Dec 2009 08:50:26 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] pygrub: add ext4 support, Xen patchbot-unstable <=