Root/package/grub/patches/020-ext4_support.patch

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

Archive Download this file



interactive