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

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since c757871 was fd60f98, checked in by Zach Winkles <eikniw@…>, 16 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.