add ext4 support
SVN-Revision: 24079
This commit is contained in:
		
							
								
								
									
										267
									
								
								package/grub/patches/020-ext4_support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								package/grub/patches/020-ext4_support.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,267 @@
 | 
				
			|||||||
 | 
					--- a/stage2/fsys_ext2fs.c
 | 
				
			||||||
 | 
					+++ b/stage2/fsys_ext2fs.c
 | 
				
			||||||
 | 
					@@ -51,6 +51,9 @@ typedef unsigned int __u32;
 | 
				
			||||||
 | 
					 #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
 | 
				
			||||||
 | 
					   {
 | 
				
			||||||
 | 
					@@ -191,6 +194,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) ffz(~(n))
 | 
				
			||||||
 | 
					@@ -279,6 +318,27 @@ ext2_rdfsb (int fsblock, int buffer)
 | 
				
			||||||
 | 
					 		  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(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(index[i-1].ei_leaf, DATABLOCK1))
 | 
				
			||||||
 | 
					+    return NULL;
 | 
				
			||||||
 | 
					+  return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block));
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /* from
 | 
				
			||||||
 | 
					   ext2/inode.c:ext2_bmap()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@@ -287,7 +347,6 @@ ext2_rdfsb (int fsblock, int buffer)
 | 
				
			||||||
 | 
					 static int
 | 
				
			||||||
 | 
					 ext2fs_block_map (int logical_block)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 #ifdef E2DEBUG
 | 
				
			||||||
 | 
					   unsigned char *i;
 | 
				
			||||||
 | 
					   for (i = (unsigned char *) INODE;
 | 
				
			||||||
 | 
					@@ -308,82 +367,106 @@ ext2fs_block_map (int logical_block)
 | 
				
			||||||
 | 
					   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))
 | 
				
			||||||
 | 
					     {
 | 
				
			||||||
 | 
					-#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 (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 (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 (bnum, DATABLOCK2))
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-	  errnum = ERR_FSYS_CORRUPT;
 | 
				
			||||||
 | 
					-	  return -1;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-      mapblock2 = bnum;
 | 
				
			||||||
 | 
					+      /* 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 (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 (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 (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 (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
 | 
				
			||||||
 | 
					+        {
 | 
				
			||||||
 | 
					+          errnum = ERR_FSYS_CORRUPT;
 | 
				
			||||||
 | 
					+          return -1;
 | 
				
			||||||
 | 
					+        }
 | 
				
			||||||
 | 
					+      mapblock1 = 3;
 | 
				
			||||||
 | 
					+      if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
 | 
				
			||||||
 | 
					+                  [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
 | 
				
			||||||
 | 
					+                                     * 2)],
 | 
				
			||||||
 | 
					+                  DATABLOCK2))
 | 
				
			||||||
 | 
					+        {
 | 
				
			||||||
 | 
					+          errnum = ERR_FSYS_CORRUPT;
 | 
				
			||||||
 | 
					+          return -1;
 | 
				
			||||||
 | 
					+        }
 | 
				
			||||||
 | 
					+      if (!ext2_rdfsb (((__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)];
 | 
				
			||||||
 | 
					+       [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 (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
 | 
				
			||||||
 | 
					-    {
 | 
				
			||||||
 | 
					-      errnum = ERR_FSYS_CORRUPT;
 | 
				
			||||||
 | 
					-      return -1;
 | 
				
			||||||
 | 
					-    }
 | 
				
			||||||
 | 
					-  mapblock1 = 3;
 | 
				
			||||||
 | 
					-  if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
 | 
				
			||||||
 | 
					-		   [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
 | 
				
			||||||
 | 
					-				      * 2)],
 | 
				
			||||||
 | 
					-		   DATABLOCK2))
 | 
				
			||||||
 | 
					-    {
 | 
				
			||||||
 | 
					-      errnum = ERR_FSYS_CORRUPT;
 | 
				
			||||||
 | 
					-      return -1;
 | 
				
			||||||
 | 
					-    }
 | 
				
			||||||
 | 
					-  if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
 | 
				
			||||||
 | 
					-		   [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
 | 
				
			||||||
 | 
					-		    & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
 | 
				
			||||||
 | 
					-		   DATABLOCK2))
 | 
				
			||||||
 | 
					+    /* inode is in extents format */
 | 
				
			||||||
 | 
					+    else
 | 
				
			||||||
 | 
					     {
 | 
				
			||||||
 | 
					+      int i;
 | 
				
			||||||
 | 
					+      struct ext4_extent_header *extent_hdr =
 | 
				
			||||||
 | 
					+         ext4_recurse_extent_index((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;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					-  return ((__u32 *) DATABLOCK2)
 | 
				
			||||||
 | 
					-    [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* preconditions: all preconds of ext2fs_block_map */
 | 
				
			||||||
		Reference in New Issue
	
	Block a user