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

clfs-1.2clfs-2.1clfs-3.0.0-systemdclfs-3.0.0-sysvinitsystemdsysvinit
Last change on this file since 28428e9 was fd60f98, checked in by Zach Winkles <eikniw@…>, 15 years ago

Add a patch to implement support for ext4 in GRUB.

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