Gentoo Archives: gentoo-commits

From: "Robin H. Johnson (robbat2)" <robbat2@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo commit in src/patchsets/grub/0.97: 850_all_grub-0.97_ext4.patch ChangeLog
Date: Fri, 02 Jan 2009 01:46:38
Message-Id: E1LIZ7T-0001T0-4L@stork.gentoo.org
1 robbat2 09/01/02 01:46:35
2
3 Modified: ChangeLog
4 Added: 850_all_grub-0.97_ext4.patch
5 Log:
6 Add ext4 patch now that it is tested.
7
8 Revision Changes Path
9 1.4 src/patchsets/grub/0.97/ChangeLog
10
11 file : http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/grub/0.97/ChangeLog?rev=1.4&view=markup
12 plain: http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/grub/0.97/ChangeLog?rev=1.4&content-type=text/plain
13 diff : http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/grub/0.97/ChangeLog?r1=1.3&r2=1.4
14
15 Index: ChangeLog
16 ===================================================================
17 RCS file: /var/cvsroot/gentoo/src/patchsets/grub/0.97/ChangeLog,v
18 retrieving revision 1.3
19 retrieving revision 1.4
20 diff -p -w -b -B -u -u -r1.3 -r1.4
21 --- ChangeLog 2 Jan 2009 00:43:45 -0000 1.3
22 +++ ChangeLog 2 Jan 2009 01:46:35 -0000 1.4
23 @@ -1,6 +1,10 @@
24 # ChangeLog for grub patchset
25 # Copyright 1999-2009 Gentoo Foundation; Distributed under the GPL v2
26 -# $Header: /var/cvsroot/gentoo/src/patchsets/grub/0.97/ChangeLog,v 1.3 2009/01/02 00:43:45 robbat2 Exp $
27 +# $Header: /var/cvsroot/gentoo/src/patchsets/grub/0.97/ChangeLog,v 1.4 2009/01/02 01:46:35 robbat2 Exp $
28 +
29 + 02 Jan 2009; Robin H. Johnson <robbat2@g.o>
30 + +850_all_grub-0.97_ext4.patch:
31 + Add ext4 patch now that it is tested.
32
33 02 Jan 2009; Robin H. Johnson <robbat2@g.o>
34 820_all_grub-0.97-cvs-sync.patch:
35
36
37
38 1.1 src/patchsets/grub/0.97/850_all_grub-0.97_ext4.patch
39
40 file : http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/grub/0.97/850_all_grub-0.97_ext4.patch?rev=1.1&view=markup
41 plain: http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/grub/0.97/850_all_grub-0.97_ext4.patch?rev=1.1&content-type=text/plain
42
43 Index: 850_all_grub-0.97_ext4.patch
44 ===================================================================
45 Gentoo bug #250829 - Include support for booting from ext4 partitions.
46
47 This is the respun and tested patch adapted from
48 http://code.google.com/p/grub4ext4/ so that it will apply with the rest of the
49 Gentoo patches.
50
51 Tested with:
52 /boot on ext2
53 /boot on ext3
54 /boot on ext4
55 / on ext4 (no seperate /boot)
56
57 Patch ported by Diego E. Pettenò (flameeyes)
58 Testing by Robin H. Johnson (robbat2)
59
60 Signed-off-by: Diego E. 'Flameeyes' Pettenò <flameeyes@g.o>
61 Signed-off-by: Robin H. Johnson <robbat2@g.o>
62
63 Index: grub-0.97/stage2/fsys_ext2fs.c
64 ===================================================================
65 --- grub-0.97.orig/stage2/fsys_ext2fs.c
66 +++ grub-0.97/stage2/fsys_ext2fs.c
67 @@ -41,6 +41,7 @@ typedef __signed__ short __s16;
68 typedef unsigned short __u16;
69 typedef __signed__ int __s32;
70 typedef unsigned int __u32;
71 +typedef unsigned long long __u64;
72
73 /*
74 * Constants relative to the data blocks, from ext2_fs.h
75 @@ -61,9 +62,9 @@ struct ext2_super_block
76 __u32 s_free_inodes_count; /* Free inodes count */
77 __u32 s_first_data_block; /* First Data Block */
78 __u32 s_log_block_size; /* Block size */
79 - __s32 s_log_frag_size; /* Fragment size */
80 + __s32 s_obso_log_frag_size; /* Obsoleted Fragment size */
81 __u32 s_blocks_per_group; /* # Blocks per group */
82 - __u32 s_frags_per_group; /* # Fragments per group */
83 + __u32 s_obso_frags_per_group; /* Obsoleted Fragments per group */
84 __u32 s_inodes_per_group; /* # Inodes per group */
85 __u32 s_mtime; /* Mount time */
86 __u32 s_wtime; /* Write time */
87 @@ -72,7 +73,7 @@ struct ext2_super_block
88 __u16 s_magic; /* Magic signature */
89 __u16 s_state; /* File system state */
90 __u16 s_errors; /* Behaviour when detecting errors */
91 - __u16 s_pad;
92 + __u16 s_minor_rev_level; /* minor revision level */
93 __u32 s_lastcheck; /* time of last check */
94 __u32 s_checkinterval; /* max. time between checks */
95 __u32 s_creator_os; /* OS */
96 @@ -119,7 +120,7 @@ struct ext2_super_block
97 __u32 s_hash_seed[4]; /* HTREE hash seed */
98 __u8 s_def_hash_version; /* Default hash version to use */
99 __u8 s_jnl_backup_type; /* Default type of journal backup */
100 - __u16 s_reserved_word_pad;
101 + __u16 s_desc_size; /* size of group descriptor */
102 __u32 s_default_mount_opts;
103 __u32 s_first_meta_bg; /* First metablock group */
104 __u32 s_mkfs_time; /* When the filesystem was created */
105 @@ -127,7 +128,7 @@ struct ext2_super_block
106 __u32 s_reserved[172]; /* Padding to the end of the block */
107 };
108
109 -struct ext2_group_desc
110 +struct ext4_group_desc
111 {
112 __u32 bg_block_bitmap; /* Blocks bitmap block */
113 __u32 bg_inode_bitmap; /* Inodes bitmap block */
114 @@ -135,8 +136,18 @@ struct ext2_group_desc
115 __u16 bg_free_blocks_count; /* Free blocks count */
116 __u16 bg_free_inodes_count; /* Free inodes count */
117 __u16 bg_used_dirs_count; /* Directories count */
118 - __u16 bg_pad;
119 - __u32 bg_reserved[3];
120 + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
121 + __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
122 + __u16 bg_itable_unused; /* Unused inodes count */
123 + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
124 + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
125 + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
126 + __u32 bg_inode_table_hi; /* Inodes table block MSB */
127 + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
128 + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
129 + __u16 bg_used_dirs_count_hi; /* Directories count MSB */
130 + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
131 + __u32 bg_reserved2[3];
132 };
133
134 struct ext2_inode
135 @@ -174,22 +185,22 @@ struct ext2_inode
136 __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
137 __u32 i_version; /* File version (for NFS) */
138 __u32 i_file_acl; /* File ACL */
139 - __u32 i_dir_acl; /* Directory ACL */
140 - __u32 i_faddr; /* Fragment address */
141 + __u32 i_size_high;
142 + __u32 i_obso_faddr; /* Obsoleted fragment address */
143 union
144 {
145 struct
146 {
147 - __u8 l_i_frag; /* Fragment number */
148 - __u8 l_i_fsize; /* Fragment size */
149 - __u16 i_pad1;
150 - __u32 l_i_reserved2[2];
151 + __u16 l_i_blocks_high; /* were l_i_reserved1 */
152 + __u16 l_i_file_acl_high;
153 + __u16 l_i_uid_high; /* these 2 fields */
154 + __u16 l_i_gid_high; /* were reserved2[0] */
155 + __u32 l_i_reserved2;
156 }
157 linux2;
158 struct
159 {
160 - __u8 h_i_frag; /* Fragment number */
161 - __u8 h_i_fsize; /* Fragment size */
162 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
163 __u16 h_i_mode_high;
164 __u16 h_i_uid_high;
165 __u16 h_i_gid_high;
166 @@ -198,16 +209,36 @@ struct ext2_inode
167 hurd2;
168 struct
169 {
170 - __u8 m_i_frag; /* Fragment number */
171 - __u8 m_i_fsize; /* Fragment size */
172 - __u16 m_pad1;
173 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
174 + __u16 m_i_file_acl_high;
175 __u32 m_i_reserved2[2];
176 }
177 masix2;
178 }
179 osd2; /* OS dependent 2 */
180 + __u16 i_extra_isize;
181 + __u16 i_pad1;
182 + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
183 + __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
184 + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
185 + __u32 i_crtime; /* File Creation time */
186 + __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
187 + __u32 i_version_hi; /* high 32 bits for 64-bit version */
188 };
189
190 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
191 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/
192 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
193 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
194 +
195 +#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
196 + ( sb->s_feature_incompat & mask )
197 +
198 +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
199 +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
200 +
201 +#define EXT4_MIN_DESC_SIZE 32
202 +
203 /* linux/limits.h */
204 #define NAME_MAX 255 /* # chars in a file name */
205
206 @@ -225,6 +256,57 @@ struct ext2_dir_entry
207 char name[EXT2_NAME_LEN]; /* File name */
208 };
209
210 +/* linux/ext4_fs_extents.h */
211 +/* This is the extent on-disk structure.
212 + * It's used at the bottom of the tree.
213 + */
214 +struct ext4_extent
215 + {
216 + __u32 ee_block; /* first logical block extent covers */
217 + __u16 ee_len; /* number of blocks covered by extent */
218 + __u16 ee_start_hi; /* high 16 bits of physical block */
219 + __u32 ee_start_lo; /* low 32 bits of physical block */
220 + };
221 +
222 +/*
223 + * This is index on-disk structure.
224 + * It's used at all the levels except the bottom.
225 + */
226 +struct ext4_extent_idx
227 + {
228 + __u32 ei_block; /* index covers logical blocks from 'block' */
229 + __u32 ei_leaf_lo; /* pointer to the physical block of the next *
230 + * level. leaf or next index could be there */
231 + __u16 ei_leaf_hi; /* high 16 bits of physical block */
232 + __u16 ei_unused;
233 + };
234 +
235 +/*
236 + * Each block (leaves and indexes), even inode-stored has header.
237 + */
238 +struct ext4_extent_header
239 + {
240 + __u16 eh_magic; /* probably will support different formats */
241 + __u16 eh_entries; /* number of valid entries */
242 + __u16 eh_max; /* capacity of store in entries */
243 + __u16 eh_depth; /* has tree real underlying blocks? */
244 + __u32 eh_generation; /* generation of the tree */
245 + };
246 +
247 +#define EXT4_EXT_MAGIC (0xf30a)
248 +#define EXT_FIRST_EXTENT(__hdr__) \
249 + ((struct ext4_extent *) (((char *) (__hdr__)) + \
250 + sizeof(struct ext4_extent_header)))
251 +#define EXT_FIRST_INDEX(__hdr__) \
252 + ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
253 + sizeof(struct ext4_extent_header)))
254 +#define EXT_LAST_EXTENT(__hdr__) \
255 + (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
256 +#define EXT_LAST_INDEX(__hdr__) \
257 + (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
258 +
259 +
260 +
261 /* linux/ext2fs.h */
262 /*
263 * EXT2_DIR_PAD defines the directory entries boundaries
264 @@ -276,8 +358,17 @@ struct ext2_dir_entry
265 /* kind of from ext2/super.c */
266 #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
267 /* linux/ext2fs.h */
268 +/* sizeof(struct ext2_group_desc) is changed in ext4
269 + * in kernel code, ext2/3 uses sizeof(struct ext2_group_desc) to calculate
270 + * number of desc per block, while ext4 uses superblock->s_desc_size in stead
271 + * superblock->s_desc_size is not available in ext2/3
272 + * */
273 +#define EXT2_DESC_SIZE(s) \
274 + (EXT4_HAS_INCOMPAT_FEATURE(s,EXT4_FEATURE_INCOMPAT_64BIT)? \
275 + s->s_desc_size : EXT4_MIN_DESC_SIZE)
276 #define EXT2_DESC_PER_BLOCK(s) \
277 - (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
278 + (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
279 +
280 /* linux/stat.h */
281 #define S_IFMT 00170000
282 #define S_IFLNK 0120000
283 @@ -439,6 +530,122 @@ ext2fs_block_map (int logical_block)
284 [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
285 }
286
287 +/* extent binary search index
288 + * find closest index in the current level extent tree
289 + * kind of from ext4_ext_binsearch_idx in ext4/extents.c
290 + */
291 +static struct ext4_extent_idx*
292 +ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
293 +{
294 + struct ext4_extent_idx *r, *l, *m;
295 + l = EXT_FIRST_INDEX(eh) + 1;
296 + r = EXT_LAST_INDEX(eh);
297 + while (l <= r)
298 + {
299 + m = l + (r - l) / 2;
300 + if (logical_block < m->ei_block)
301 + r = m - 1;
302 + else
303 + l = m + 1;
304 + }
305 + return (struct ext4_extent_idx*)(l - 1);
306 +}
307 +
308 +/* extent binary search
309 + * find closest extent in the leaf level
310 + * kind of from ext4_ext_binsearch in ext4/extents.c
311 + */
312 +static struct ext4_extent*
313 +ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
314 +{
315 + struct ext4_extent *r, *l, *m;
316 + l = EXT_FIRST_EXTENT(eh) + 1;
317 + r = EXT_LAST_EXTENT(eh);
318 + while (l <= r)
319 + {
320 + m = l + (r - l) / 2;
321 + if (logical_block < m->ee_block)
322 + r = m - 1;
323 + else
324 + l = m + 1;
325 + }
326 + return (struct ext4_extent*)(l - 1);
327 +}
328 +
329 +/* Maps extents enabled logical block into physical block via an inode.
330 + * EXT4_HUGE_FILE_FL should be checked before calling this.
331 + */
332 +static int
333 +ext4fs_block_map (int logical_block)
334 +{
335 + struct ext4_extent_header *eh;
336 + struct ext4_extent *ex, *extent;
337 + struct ext4_extent_idx *ei, *index;
338 + int depth;
339 + int i;
340 +
341 +#ifdef E2DEBUG
342 + unsigned char *i;
343 + for (i = (unsigned char *) INODE;
344 + i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
345 + i++)
346 + {
347 + printf ("%c", "0123456789abcdef"[*i >> 4]);
348 + printf ("%c", "0123456789abcdef"[*i % 16]);
349 + if (!((i + 1 - (unsigned char *) INODE) % 16))
350 + {
351 + printf ("\n");
352 + }
353 + else
354 + {
355 + printf (" ");
356 + }
357 + }
358 + printf ("logical block %d\n", logical_block);
359 +#endif /* E2DEBUG */
360 + eh = (struct ext4_extent_header*)INODE->i_block;
361 + if (eh->eh_magic != EXT4_EXT_MAGIC)
362 + {
363 + errnum = ERR_FSYS_CORRUPT;
364 + return -1;
365 + }
366 + while((depth = eh->eh_depth) != 0)
367 + { /* extent index */
368 + if (eh->eh_magic != EXT4_EXT_MAGIC)
369 + {
370 + errnum = ERR_FSYS_CORRUPT;
371 + return -1;
372 + }
373 + ei = ext4_ext_binsearch_idx(eh, logical_block);
374 + if (ei->ei_leaf_hi)
375 + {/* 64bit physical block number not supported */
376 + errnum = ERR_FILELENGTH;
377 + return -1;
378 + }
379 + if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
380 + {
381 + errnum = ERR_FSYS_CORRUPT;
382 + return -1;
383 + }
384 + eh = (struct ext4_extent_header*)DATABLOCK1;
385 + }
386 +
387 + /* depth==0, we come to the leaf */
388 + ex = ext4_ext_binsearch(eh, logical_block);
389 + if (ex->ee_start_hi)
390 + {/* 64bit physical block number not supported */
391 + errnum = ERR_FILELENGTH;
392 + return -1;
393 + }
394 + if ((ex->ee_block + ex->ee_len) < logical_block)
395 + {
396 + errnum = ERR_FSYS_CORRUPT;
397 + return -1;
398 + }
399 + return ex->ee_start_lo + logical_block - ex->ee_block;
400 +
401 +}
402 +
403 /* preconditions: all preconds of ext2fs_block_map */
404 int
405 ext2fs_read (char *buf, int len)
406 @@ -473,6 +680,11 @@ ext2fs_read (char *buf, int len)
407 /* find the (logical) block component of our location */
408 logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
409 offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
410 + /* map extents enabled logical block number to physical fs on-dick block number */
411 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
412 + && INODE->i_flags & EXT4_EXTENTS_FL)
413 + map = ext4fs_block_map (logical_block);
414 + else
415 map = ext2fs_block_map (logical_block);
416 #ifdef E2DEBUG
417 printf ("map=%d\n", map);
418 @@ -557,7 +769,7 @@ ext2fs_dir (char *dirname)
419 int desc; /* index within that group */
420 int ino_blk; /* fs pointer of the inode's information */
421 int str_chk = 0; /* used to hold the results of a string compare */
422 - struct ext2_group_desc *gdp;
423 + struct ext4_group_desc *ext4_gdp;
424 struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
425
426 char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
427 @@ -603,8 +815,15 @@ ext2fs_dir (char *dirname)
428 {
429 return 0;
430 }
431 - gdp = GROUP_DESC;
432 - ino_blk = gdp[desc].bg_inode_table +
433 + ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC +
434 + desc * EXT2_DESC_SIZE(SUPERBLOCK));
435 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT)
436 + && (! ext4_gdp->bg_inode_table_hi))
437 + {/* 64bit itable not supported */
438 + errnum = ERR_FILELENGTH;
439 + return -1;
440 + }
441 + ino_blk = ext4_gdp->bg_inode_table +
442 (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
443 >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
444 #ifdef E2DEBUG
445 @@ -681,7 +900,10 @@ ext2fs_dir (char *dirname)
446 }
447 linkbuf[filemax + len] = '\0';
448
449 - /* Read the symlink data. */
450 + /* Read the symlink data.
451 + * Slow symlink is extents enabled
452 + * But since grub_read invokes ext2fs_read, nothing to change here
453 + * */
454 if (! ext2_is_fast_symlink ())
455 {
456 /* Read the necessary blocks, and reset the file pointer. */
457 @@ -692,7 +914,9 @@ ext2fs_dir (char *dirname)
458 }
459 else
460 {
461 - /* Copy the data directly from the inode. */
462 + /* Copy the data directly from the inode.
463 + * Fast symlink is not extents enabled
464 + * */
465 len = filemax;
466 memmove (linkbuf, (char *) INODE->i_block, len);
467 }
468 @@ -726,6 +950,13 @@ ext2fs_dir (char *dirname)
469 errnum = ERR_BAD_FILETYPE;
470 return 0;
471 }
472 + /* if file is too large, just stop and report an error*/
473 + if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high))
474 + {
475 + /* file too large, stop reading */
476 + errnum = ERR_FILELENGTH;
477 + return 0;
478 + }
479
480 filemax = (INODE->i_size);
481 return 1;
482 @@ -780,17 +1011,28 @@ ext2fs_dir (char *dirname)
483 }
484
485 /* else, find the (logical) block component of our location */
486 + /* ext4 logical block number the same as ext2/3 */
487 blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
488
489 /* we know which logical block of the directory entry we are looking
490 for, now we have to translate that to the physical (fs) block on
491 the disk */
492 + /* map extents enabled logical block number to physical fs on-dick block number */
493 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
494 + && INODE->i_flags & EXT4_EXTENTS_FL)
495 + map = ext4fs_block_map (blk);
496 + else
497 map = ext2fs_block_map (blk);
498 #ifdef E2DEBUG
499 printf ("fs block=%d\n", map);
500 #endif /* E2DEBUG */
501 mapblock2 = -1;
502 - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
503 + if (map < 0)
504 + {
505 + *rest = ch;
506 + return 0;
507 + }
508 + if (!ext2_rdfsb (map, DATABLOCK2))
509 {
510 errnum = ERR_FSYS_CORRUPT;
511 *rest = ch;