1diff -up grub-upstream.wip/AUTHORS.btrfs grub-upstream.wip/AUTHORS
2--- grub-upstream.wip/AUTHORS.btrfs	2004-03-27 16:25:17.000000000 +0000
3+++ grub-upstream.wip/AUTHORS	2012-03-20 05:07:09.000000000 +0000
4@@ -41,6 +41,8 @@ Kristoffer Branemyr added VSTa filesyste
5
6 Serguei Tzukanov added JFS and XFS support.
7
8+Edward Shishkin added Btrfs support.
9+
10 Jason Thomas added Linux DAC960 support and support for hiding/unhiding
11 logical partitions, and did a significant bugfix for the terminal stuff.
12
13diff -up grub-upstream.wip/configure.ac.btrfs grub-upstream.wip/configure.ac
14--- grub-upstream.wip/configure.ac.btrfs	2012-03-20 05:06:49.000000000 +0000
15+++ grub-upstream.wip/configure.ac	2012-03-20 05:07:09.000000000 +0000
16@@ -274,6 +274,13 @@ if test x"$enable_reiserfs" != xno; then
17   FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_REISERFS=1"
18 fi
19
20+AC_ARG_ENABLE(btrfs,
21+  [  --disable-btrfs         disable BtrFS support in Stage 2])
22+
23+if test x"$enable_btrfs" != xno; then
24+  FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_BTRFS=1"
25+fi
26+
27 AC_ARG_ENABLE(vstafs,
28   [  --disable-vstafs        disable VSTa FS support in Stage 2])
29
30diff -up grub-upstream.wip/docs/grub.texi.btrfs grub-upstream.wip/docs/grub.texi
31--- grub-upstream.wip/docs/grub.texi.btrfs	2012-03-20 05:06:49.000000000 +0000
32+++ grub-upstream.wip/docs/grub.texi	2012-03-20 05:07:09.000000000 +0000
33@@ -1761,6 +1761,7 @@ itself. Usually, this is put in a filesy
34 @itemx jfs_stage1_5
35 @itemx minix_stage1_5
36 @itemx reiserfs_stage1_5
37+@itemx btrfs_stage1_5
38 @itemx vstafs_stage1_5
39 @itemx xfs_stage1_5
40
41diff -up grub-upstream.wip/grub/Makefile.am.btrfs grub-upstream.wip/grub/Makefile.am
42--- grub-upstream.wip/grub/Makefile.am.btrfs	2005-02-02 20:38:19.000000000 +0000
43+++ grub-upstream.wip/grub/Makefile.am	2012-03-20 05:07:09.000000000 +0000
44@@ -8,7 +8,7 @@ endif
45
46 AM_CPPFLAGS = -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
47 	-DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
48-	-DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
49+	-DFSYS_BTRFS=1 -DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
50 	-DUSE_MD5_PASSWORDS=1 -DSUPPORT_HERCULES=1 \
51 	$(SERIAL_FLAGS) -I$(top_srcdir)/stage2 \
52 	-I$(top_srcdir)/stage1 -I$(top_srcdir)/lib
53diff -up grub-upstream.wip/INSTALL.btrfs grub-upstream.wip/INSTALL
54--- grub-upstream.wip/INSTALL.btrfs	2005-05-08 02:43:15.000000000 +0000
55+++ grub-upstream.wip/INSTALL	2012-03-20 05:07:09.000000000 +0000
56@@ -207,6 +207,9 @@ operates.
57 `--disable-reiserfs'
58      Omit the ReiserFS support in Stage 2.
59
60+`--disable-btrfs'
61+     Omit the BtrFS support in Stage 2.
62+
63 `--disable-vstafs'
64      Omit the VSTa filesystem support in Stage 2.
65
66diff -up /dev/null grub-upstream.wip/stage2/btrfs.h
67--- /dev/null	2009-06-03 06:46:26.160951000 +0000
68+++ grub-upstream.wip/stage2/btrfs.h	2012-03-20 05:07:09.000000000 +0000
69@@ -0,0 +1,1413 @@
70+/* btrfs.h - an extraction from btrfs-progs-0.18/ctree.h into one file
71+ *
72+ * Copyright (C) 2007 Oracle.  All rights reserved.
73+ *
74+ * This program is free software; you can redistribute it and/or
75+ * modify it under the terms of the GNU General Public
76+ * License v2 as published by the Free Software Foundation.
77+ *
78+ * This program is distributed in the hope that it will be useful,
79+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
80+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
81+ * General Public License for more details.
82+ *
83+ * You should have received a copy of the GNU General Public
84+ * License along with this program; If not, see <http://www.gnu.org/licenses/>
85+ */
86+
87+/* include/asm-i386/types.h */
88+
89+typedef __signed__ char __s8;
90+typedef unsigned char __u8;
91+typedef __signed__ short __s16;
92+typedef unsigned short __u16;
93+typedef __signed__ int __s32;
94+typedef unsigned int __u32;
95+typedef unsigned long long __u64;
96+typedef __signed__ long long __s64;
97+
98+typedef __s8 s8;
99+typedef __u8 u8;
100+typedef __u16 u16;
101+typedef __u32 u32;
102+typedef __u64 u64;
103+typedef __s64 s64;
104+
105+#define __bitwise
106+
107+typedef u16 __bitwise __le16;
108+typedef u32 __bitwise __le32;
109+typedef u64 __bitwise __le64;
110+
111+/* linux/posix_type.h */
112+typedef long linux_off_t;
113+
114+/* linux/little_endian.h */
115+#define cpu_to_le64(x) ((__u64) (x))
116+#define le64_to_cpu(x) ((__u64) (x))
117+#define cpu_to_le32(x) ((__u32) (x))
118+#define le32_to_cpu(x) ((__u32) (x))
119+#define cpu_to_le16(x) ((__u16) (x))
120+#define le16_to_cpu(x) ((__u16) (x))
121+#define le8_to_cpu(x) ((__u8) (x))
122+#define cpu_to_le8(x) ((__u8) (x))
123+
124+/* linux/stat.h */
125+#define S_IFMT  00170000
126+#define S_IFLNK  0120000
127+#define S_IFREG  0100000
128+#define S_IFDIR  0040000
129+#define S_ISLNK(m)     (((m) & S_IFMT) == S_IFLNK)
130+#define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
131+#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
132+
133+struct btrfs_root;
134+#define BTRFS_MAGIC "_BHRfS_M"
135+
136+#define BTRFS_SUPER_INFO_OFFSET (64 * 1024)
137+#define BTRFS_SUPER_INFO_SIZE 4096
138+
139+#define BTRFS_SUPER_MIRROR_MAX  3
140+#define BTRFS_SUPER_MIRROR_SHIFT 12
141+
142+#define PATH_MAX                1024   /* include/linux/limits.h */
143+#define MAX_LINK_COUNT             5   /* number of symbolic links
144+                                          to follow */
145+#define BTRFS_MAX_LEVEL 8
146+#define BTRFS_ROOT_TREE_OBJECTID 1ULL
147+#define BTRFS_EXTENT_TREE_OBJECTID 2ULL
148+#define BTRFS_CHUNK_TREE_OBJECTID 3ULL
149+#define BTRFS_DEV_TREE_OBJECTID 4ULL
150+#define BTRFS_FS_TREE_OBJECTID 5ULL
151+#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL
152+#define BTRFS_CSUM_TREE_OBJECTID 7ULL
153+
154+#define BTRFS_ORPHAN_OBJECTID -5ULL
155+#define BTRFS_TREE_LOG_OBJECTID -6ULL
156+#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL
157+#define BTRFS_TREE_RELOC_OBJECTID -8ULL
158+#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL
159+#define BTRFS_EXTENT_CSUM_OBJECTID -10ULL
160+
161+#define BTRFS_MULTIPLE_OBJECTIDS -255ULL
162+#define BTRFS_FIRST_FREE_OBJECTID 256ULL
163+#define BTRFS_LAST_FREE_OBJECTID -256ULL
164+#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL
165+#define BTRFS_DEV_ITEMS_OBJECTID 1ULL
166+
167+
168+#define BTRFS_NAME_LEN 255
169+#define BTRFS_CSUM_SIZE 32
170+#define BTRFS_CSUM_TYPE_CRC32  0
171+
172+static int btrfs_csum_sizes[] = { 4, 0 };
173+
174+/* four bytes for CRC32 */
175+#define BTRFS_CRC32_SIZE 4
176+#define BTRFS_EMPTY_DIR_SIZE 0
177+
178+#define BTRFS_FT_UNKNOWN       0
179+#define BTRFS_FT_REG_FILE      1
180+#define BTRFS_FT_DIR           2
181+#define BTRFS_FT_CHRDEV                3
182+#define BTRFS_FT_BLKDEV                4
183+#define BTRFS_FT_FIFO          5
184+#define BTRFS_FT_SOCK          6
185+#define BTRFS_FT_SYMLINK       7
186+#define BTRFS_FT_XATTR         8
187+#define BTRFS_FT_MAX           9
188+
189+#define BTRFS_UUID_SIZE 16
190+
191+#define BTRFS_DEFAULT_NUM_DEVICES     1
192+#define BTRFS_DEFAULT_NODE_SIZE       4096
193+#define BTRFS_DEFAULT_LEAF_SIZE       4096
194+#define BTRFS_NUM_CACHED_DEVICES      128
195+
196+#define WARN_ON(c)
197+#define cassert(cond) ({ switch (-1) { case (cond): case 0: break; } })
198+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
199+
200+#define offsetof(type, memb) \
201+       ((unsigned long)(&((type *)0)->memb))
202+
203+struct btrfs_disk_key {
204+       __le64 objectid;
205+       u8 type;
206+       __le64 offset;
207+} __attribute__ ((__packed__));
208+
209+/* cpu key */
210+struct btrfs_key {
211+       u64 objectid;
212+       u8 type;
213+       u64 offset;
214+} __attribute__ ((__packed__));
215+
216+/* this represents a divice in a chunk tree */
217+struct btrfs_dev_item {
218+       __le64 devid; /* internal device id */
219+       __le64 total_bytes; /* size of the device */
220+       __le64 bytes_used;
221+       __le32 io_align; /* optimal io alignment */
222+       __le32 io_width; /* optimal io width */
223+       __le32 sector_size; /* minimal io size */
224+       __le64 type; /* type and info about this device */
225+       __le64 generation; /* expected generation */
226+        __le64 start_offset; /* of the partition on a device */
227+
228+       /* info for allocation decisions */
229+       __le32 dev_group;
230+
231+        u8 seek_speed; /* 0-100 (100 is fastest) */
232+       u8 bandwidth;  /* 0-100 (100 is fastest) */
233+
234+        u8 uuid[BTRFS_UUID_SIZE]; /* dev uuid generated by btrfs */
235+       u8 fsid[BTRFS_UUID_SIZE]; /* uuid of the host FS */
236+} __attribute__ ((__packed__));
237+
238+struct btrfs_stripe {
239+       __le64 devid;
240+       __le64 offset;
241+       u8 dev_uuid[BTRFS_UUID_SIZE];
242+} __attribute__ ((__packed__));
243+
244+struct btrfs_chunk {
245+       /* size of this chunk in bytes */
246+       __le64 length;
247+       __le64 owner; /* objectid of the root referincing this chunk */
248+       __le64 stripe_len;
249+       __le64 type;
250+       __le32 io_align; /* optimal io alignment for this chunk */
251+       __le32 io_width; /* optimal io width for this chunk */
252+       __le32 sector_size; /* minimal io size for this chunk */
253+       __le16 num_stripes;
254+       __le16 sub_stripes; /* sub stripes (for raid10) */
255+       struct btrfs_stripe stripe;
256+} __attribute__ ((__packed__));
257+
258+static inline unsigned long btrfs_chunk_item_size(int num_stripes)
259+{
260+       return sizeof(struct btrfs_chunk) +
261+               sizeof(struct btrfs_stripe) * (num_stripes - 1);
262+}
263+
264+#define BTRFS_FSID_SIZE 16
265+#define BTRFS_HEADER_FLAG_WRITTEN (1 << 0)
266+
267+struct btrfs_header {
268+       /* these first four must match the super block */
269+       u8 csum[BTRFS_CSUM_SIZE];
270+       u8 fsid[BTRFS_FSID_SIZE]; /* uuid of the host fs */
271+       __le64 bytenr; /* which block this node is supposed to live in */
272+       __le64 flags;
273+
274+       /* allowed to be different from the super from here on down */
275+       u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
276+       __le64 generation;
277+       __le64 owner;
278+       __le32 nritems;
279+       u8 level;
280+} __attribute__ ((__packed__));
281+
282+#define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \
283+                               sizeof(struct btrfs_header)) / \
284+                               sizeof(struct btrfs_key_ptr))
285+#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
286+#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
287+#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
288+                                       sizeof(struct btrfs_item) - \
289+                                       sizeof(struct btrfs_file_extent_item))
290+
291+#define BTRFS_SUPER_FLAG_SEEDING       (1ULL << 32)
292+#define BTRFS_SUPER_FLAG_METADUMP      (1ULL << 33)
293+
294+/*
295+ * a portion of superblock which is used
296+ * for chunk translation (up to 14 chunks
297+ * with 3 stripes each.
298+ */
299+#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048
300+#define BTRFS_LABEL_SIZE 256
301+
302+/*
303+ * the super block basically lists the main trees of the FS
304+ * it currently lacks any block count etc etc
305+ */
306+
307+struct btrfs_super_block {
308+       u8 csum[BTRFS_CSUM_SIZE];
309+       /* the first 3 fields must match struct btrfs_header */
310+       u8 fsid[BTRFS_FSID_SIZE];    /* FS specific uuid */
311+       __le64 bytenr; /* this block number */
312+       __le64 flags;
313+
314+       /* allowed to be different from the btrfs_header from here own down */
315+       __le64 magic;
316+       __le64 generation;
317+       __le64 root;        /* tree root */
318+       __le64 chunk_root;
319+       __le64 log_root;
320+
321+       /* this will help find the new super based on the log root */
322+       __le64 log_root_transid;
323+       __le64 total_bytes;
324+       __le64 bytes_used;
325+       __le64 root_dir_objectid;
326+       __le64 num_devices;
327+       __le32 sectorsize;
328+       __le32 nodesize;
329+       __le32 leafsize;
330+       __le32 stripesize;
331+       __le32 sys_chunk_array_size;
332+       __le64 chunk_root_generation;
333+       __le64 compat_flags;
334+       __le64 compat_ro_flags;
335+       __le64 incompat_flags;
336+       __le16 csum_type;
337+       u8 root_level;
338+       u8 chunk_root_level;
339+       u8 log_root_level;
340+       struct btrfs_dev_item dev_item;
341+
342+       char label[BTRFS_LABEL_SIZE];
343+
344+       /* future expansion */
345+       __le64 reserved[32];
346+       u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
347+} __attribute__ ((__packed__));
348+
349+/*
350+ * Compat flags that we support.  If any incompat flags are set other than the
351+ * ones specified below then we will fail to mount
352+ */
353+#define BTRFS_FEATURE_COMPAT_SUPP      0x0
354+#define BTRFS_FEATURE_COMPAT_RO_SUPP   0x0
355+#define BTRFS_FEATURE_INCOMPAT_SUPP    0x0
356+
357+/* Item header for per-leaf lookup */
358+struct btrfs_item {
359+       struct btrfs_disk_key key;
360+       __le32 offset;
361+       __le32 size;
362+} __attribute__ ((__packed__));
363+
364+/*
365+ * Format of the leaves:
366+ * [item0, item1....itemN] [free space] [dataN...data1, data0]
367+ */
368+struct btrfs_leaf {
369+       struct btrfs_header header;
370+       struct btrfs_item items[];
371+} __attribute__ ((__packed__));
372+
373+/*
374+ * keys-pointers pairs for per-node (non-leaf) lookup
375+ */
376+struct btrfs_key_ptr {
377+       struct btrfs_disk_key key;
378+       __le64 blockptr;
379+       __le64 generation;
380+} __attribute__ ((__packed__));
381+
382+struct btrfs_node {
383+       struct btrfs_header header;
384+       struct btrfs_key_ptr ptrs[];
385+} __attribute__ ((__packed__));
386+
387+struct btrfs_device {
388+	/* the internal btrfs device id */
389+	u64 devid;
390+	/* the internal grub device representation */
391+	unsigned long drive;
392+	unsigned long part;
393+	unsigned long length;
394+};
395+
396+struct extent_buffer {
397+       /* metadata */
398+       struct btrfs_device dev;
399+       u64 start;
400+       u64 dev_bytenr;
401+       u32 len;
402+       /* data */
403+       char *data;
404+};
405+
406+static inline void read_extent_buffer(struct extent_buffer *eb,
407+                                     void *dst, unsigned long start,
408+                                     unsigned long len)
409+{
410+       memcpy(dst, eb->data + start, len);
411+}
412+
413+static inline void write_extent_buffer(struct extent_buffer *eb,
414+                                      const void *src, unsigned long start,
415+                                      unsigned long len)
416+{
417+       memcpy(eb->data + start, src, len);
418+}
419+
420+/*
421+ * NOTE:
422+ * don't increase a number of levels for grub-0.97!
423+ */
424+typedef enum {
425+       FIRST_EXTERNAL_LOOKUP_POOL,
426+       SECOND_EXTERNAL_LOOKUP_POOL,
427+       INTERNAL_LOOKUP_POOL,
428+       LAST_LOOKUP_POOL
429+} lookup_pool_id;
430+
431+/*             Relationship between lookup pools:
432+ *  depth
433+ *
434+ *    ^             +----> INTERNAL <----+
435+ *    |             |                    |
436+ *    |             |                    |
437+ *    -        FIRST_EXTERNAL     SECOND_EXTERNAL
438+ */
439+
440+struct btrfs_path {
441+       lookup_pool_id lpid;
442+       struct extent_buffer nodes[BTRFS_MAX_LEVEL];
443+       int slots[BTRFS_MAX_LEVEL];
444+};
445+
446+/*
447+ * items in the extent btree are used to record the objectid of the
448+ * owner of the block and the number of references
449+ */
450+struct btrfs_extent_item {
451+       __le32 refs;
452+} __attribute__ ((__packed__));
453+
454+struct btrfs_extent_ref {
455+       __le64 root;
456+       __le64 generation;
457+       __le64 objectid;
458+       __le32 num_refs;
459+} __attribute__ ((__packed__));
460+
461+/* dev extents record free space on individual devices.  The owner
462+ * field points back to the chunk allocation mapping tree that allocated
463+ * the extent.  The chunk tree uuid field is a way to double check the owner
464+ */
465+struct btrfs_dev_extent {
466+       __le64 chunk_tree;
467+       __le64 chunk_objectid;
468+       __le64 chunk_offset;
469+       __le64 length;
470+       u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
471+} __attribute__ ((__packed__));
472+
473+struct btrfs_inode_ref {
474+       __le64 index;
475+       __le16 name_len;
476+       /* name goes here */
477+} __attribute__ ((__packed__));
478+
479+struct btrfs_timespec {
480+       __le64 sec;
481+       __le32 nsec;
482+} __attribute__ ((__packed__));
483+
484+typedef enum {
485+       BTRFS_COMPRESS_NONE = 0,
486+       BTRFS_COMPRESS_ZLIB = 1,
487+       BTRFS_COMPRESS_LAST = 2,
488+} btrfs_compression_type;
489+
490+/* we don't understand any encryption methods right now */
491+typedef enum {
492+       BTRFS_ENCRYPTION_NONE = 0,
493+       BTRFS_ENCRYPTION_LAST = 1,
494+} btrfs_encryption_type;
495+
496+struct btrfs_inode_item {
497+       /* nfs style generation number */
498+       __le64 generation;
499+       /* transid that last touched this inode */
500+       __le64 transid;
501+       __le64 size;
502+       __le64 nbytes;
503+       __le64 block_group;
504+       __le32 nlink;
505+       __le32 uid;
506+       __le32 gid;
507+       __le32 mode;
508+       __le64 rdev;
509+       __le64 flags;
510+
511+       /* modification sequence number for NFS */
512+       __le64 sequence;
513+
514+       /*
515+        * a little future expansion, for more than this we can
516+        * just grow the inode item and version it
517+        */
518+       __le64 reserved[4];
519+       struct btrfs_timespec atime;
520+       struct btrfs_timespec ctime;
521+       struct btrfs_timespec mtime;
522+       struct btrfs_timespec otime;
523+} __attribute__ ((__packed__));
524+
525+struct btrfs_dir_item {
526+       struct btrfs_disk_key location;
527+       __le64 transid;
528+       __le16 data_len;
529+       __le16 name_len;
530+       u8 type;
531+} __attribute__ ((__packed__));
532+
533+struct btrfs_root_item {
534+       struct btrfs_inode_item inode;
535+       __le64 generation;
536+       __le64 root_dirid;
537+       __le64 bytenr;
538+       __le64 byte_limit;
539+       __le64 bytes_used;
540+       __le64 last_snapshot;
541+       __le64 flags;
542+       __le32 refs;
543+       struct btrfs_disk_key drop_progress;
544+       u8 drop_level;
545+       u8 level;
546+} __attribute__ ((__packed__));
547+
548+/*
549+ * this is used for both forward and backward root refs
550+ */
551+struct btrfs_root_ref {
552+       __le64 dirid;
553+       __le64 sequence;
554+       __le16 name_len;
555+} __attribute__ ((__packed__));
556+
557+#define BTRFS_FILE_EXTENT_INLINE 0
558+#define BTRFS_FILE_EXTENT_REG 1
559+#define BTRFS_FILE_EXTENT_PREALLOC 2
560+
561+struct btrfs_file_extent_item {
562+       /*
563+        * transaction id that created this extent
564+        */
565+       __le64 generation;
566+       /*
567+        * max number of bytes to hold this extent in ram
568+        * when we split a compressed extent we can't know how big
569+        * each of the resulting pieces will be.  So, this is
570+        * an upper limit on the size of the extent in ram instead of
571+        * an exact limit.
572+        */
573+       __le64 ram_bytes;
574+
575+       /*
576+        * 32 bits for the various ways we might encode the data,
577+        * including compression and encryption.  If any of these
578+        * are set to something a given disk format doesn't understand
579+        * it is treated like an incompat flag for reading and writing,
580+        * but not for stat.
581+        */
582+       u8 compression;
583+       u8 encryption;
584+       __le16 other_encoding; /* spare for later use */
585+
586+       /* are we inline data or a real extent? */
587+       u8 type;
588+
589+       /*
590+        * disk space consumed by the extent, checksum blocks are included
591+        * in these numbers
592+        */
593+       __le64 disk_bytenr;
594+       __le64 disk_num_bytes;
595+       /*
596+        * the logical offset in file blocks (no csums)
597+        * this extent record is for.  This allows a file extent to point
598+        * into the middle of an existing extent on disk, sharing it
599+        * between two snapshots (useful if some bytes in the middle of the
600+        * extent have changed
601+        */
602+       __le64 offset;
603+       /*
604+        * the logical number of file blocks (no csums included)
605+        */
606+       __le64 num_bytes;
607+
608+} __attribute__ ((__packed__));
609+
610+struct btrfs_csum_item {
611+       u8 csum;
612+} __attribute__ ((__packed__));
613+
614+/* tag for the radix tree of block groups in ram */
615+#define BTRFS_BLOCK_GROUP_DATA     (1 << 0)
616+#define BTRFS_BLOCK_GROUP_SYSTEM   (1 << 1)
617+#define BTRFS_BLOCK_GROUP_METADATA (1 << 2)
618+#define BTRFS_BLOCK_GROUP_RAID0    (1 << 3)
619+#define BTRFS_BLOCK_GROUP_RAID1    (1 << 4)
620+#define BTRFS_BLOCK_GROUP_DUP     (1 << 5)
621+#define BTRFS_BLOCK_GROUP_RAID10   (1 << 6)
622+
623+struct btrfs_block_group_item {
624+       __le64 used;
625+       __le64 chunk_objectid;
626+       __le64 flags;
627+} __attribute__ ((__packed__));
628+
629+/*
630+ * in ram representation of the tree.  extent_root is used for all allocations
631+ * and for the extent tree extent_root root.
632+ */
633+struct btrfs_root {
634+       struct extent_buffer   node;
635+       char                   data[4096];
636+       struct btrfs_root_item root_item;
637+       u64 objectid;
638+
639+       /* data allocations are done in sectorsize units */
640+       u32 sectorsize;
641+
642+       /* node allocations are done in nodesize units */
643+       u32 nodesize;
644+
645+       /* leaf allocations are done in leafsize units */
646+       u32 leafsize;
647+
648+       /* leaf allocations are done in leafsize units */
649+       u32 stripesize;
650+};
651+
652+struct btrfs_file_info {
653+	struct btrfs_key key;
654+};
655+
656+struct btrfs_root;
657+struct btrfs_fs_devices;
658+struct btrfs_fs_info {
659+       u8 fsid[BTRFS_FSID_SIZE];
660+       struct btrfs_root fs_root;
661+       struct btrfs_root tree_root;
662+       struct btrfs_root chunk_root;
663+
664+       struct btrfs_file_info file_info; /* currently opened file */
665+       struct btrfs_path paths [LAST_LOOKUP_POOL];
666+
667+       char mbr[SECTOR_SIZE];
668+
669+       int sb_mirror;
670+       u64 sb_transid;
671+       struct btrfs_device sb_dev;
672+       struct btrfs_super_block sb_copy;
673+
674+       struct btrfs_device devices[BTRFS_NUM_CACHED_DEVICES + 1];
675+};
676+
677+/*
678+ * inode items have the data typically returned from stat and store other
679+ * info about object characteristics.  There is one for every file and dir in
680+ * the FS
681+ */
682+#define BTRFS_INODE_ITEM_KEY           1
683+#define BTRFS_INODE_REF_KEY            12
684+#define BTRFS_XATTR_ITEM_KEY           24
685+#define BTRFS_ORPHAN_ITEM_KEY          48
686+
687+#define BTRFS_DIR_LOG_ITEM_KEY  60
688+#define BTRFS_DIR_LOG_INDEX_KEY 72
689+/*
690+ * dir items are the name -> inode pointers in a directory.  There is one
691+ * for every name in a directory.
692+ */
693+#define BTRFS_DIR_ITEM_KEY     84
694+#define BTRFS_DIR_INDEX_KEY    96
695+
696+/*
697+ * extent data is for file data
698+ */
699+#define BTRFS_EXTENT_DATA_KEY  108
700+
701+/*
702+ * csum items have the checksums for data in the extents
703+ */
704+#define BTRFS_CSUM_ITEM_KEY    120
705+/*
706+ * extent csums are stored in a separate tree and hold csums for
707+ * an entire extent on disk.
708+ */
709+#define BTRFS_EXTENT_CSUM_KEY  128
710+
711+/*
712+ * root items point to tree roots.  There are typically in the root
713+ * tree used by the super block to find all the other trees
714+ */
715+#define BTRFS_ROOT_ITEM_KEY    132
716+
717+/*
718+ * root backrefs tie subvols and snapshots to the directory entries that
719+ * reference them
720+ */
721+#define BTRFS_ROOT_BACKREF_KEY 144
722+
723+/*
724+ * root refs make a fast index for listing all of the snapshots and
725+ * subvolumes referenced by a given root.  They point directly to the
726+ * directory item in the root that references the subvol
727+ */
728+#define BTRFS_ROOT_REF_KEY     156
729+
730+/*
731++ * extent items are in the extent map tree.  These record which blocks
732++ * are used, and how many references there are to each block
733++ */
734+#define BTRFS_EXTENT_ITEM_KEY  168
735+#define BTRFS_EXTENT_REF_KEY   180
736+
737+/*
738+ * block groups give us hints into the extent allocation trees.  Which
739+ * blocks are free etc etc
740+ */
741+#define BTRFS_BLOCK_GROUP_ITEM_KEY 192
742+
743+#define BTRFS_DEV_EXTENT_KEY   204
744+#define BTRFS_DEV_ITEM_KEY     216
745+#define BTRFS_CHUNK_ITEM_KEY   228
746+
747+/*
748+ * string items are for debugging.  They just store a short string of
749+ * data in the FS
750+ */
751+#define BTRFS_STRING_ITEM_KEY  253
752+/*
753+ * Inode flags
754+ */
755+#define BTRFS_INODE_NODATASUM          (1 << 0)
756+#define BTRFS_INODE_NODATACOW          (1 << 1)
757+#define BTRFS_INODE_READONLY           (1 << 2)
758+
759+#define read_eb_member(eb, ptr, type, member, result) (                        \
760+       read_extent_buffer(eb, (char *)(result),                        \
761+                          ((unsigned long)(ptr)) +                     \
762+                           offsetof(type, member),                     \
763+                          sizeof(((type *)0)->member)))
764+
765+#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)            \
766+static inline u##bits btrfs_##name(struct extent_buffer *eb)           \
767+{                                                                      \
768+       struct btrfs_header *h = (struct btrfs_header *)eb->data;       \
769+       return le##bits##_to_cpu(h->member);                            \
770+}                                                                      \
771+static inline void btrfs_set_##name(struct extent_buffer *eb,          \
772+                                   u##bits val)                        \
773+{                                                                      \
774+       struct btrfs_header *h = (struct btrfs_header *)eb->data;       \
775+       h->member = cpu_to_le##bits(val);                               \
776+}
777+
778+#define BTRFS_SETGET_FUNCS(name, type, member, bits)                   \
779+static inline u##bits btrfs_##name(struct extent_buffer *eb,           \
780+                                  type *s)                             \
781+{                                                                      \
782+       unsigned long offset = (unsigned long)s;                        \
783+       type *p = (type *) (eb->data + offset);                         \
784+       return le##bits##_to_cpu(p->member);                            \
785+}                                                                      \
786+static inline void btrfs_set_##name(struct extent_buffer *eb,          \
787+                                   type *s, u##bits val)               \
788+{                                                                      \
789+       unsigned long offset = (unsigned long)s;                        \
790+       type *p = (type *) (eb->data + offset);                         \
791+       p->member = cpu_to_le##bits(val);                               \
792+}
793+
794+#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits)             \
795+static inline u##bits btrfs_##name(type *s)                            \
796+{                                                                      \
797+       return le##bits##_to_cpu(s->member);                            \
798+}                                                                      \
799+static inline void btrfs_set_##name(type *s, u##bits val)              \
800+{                                                                      \
801+       s->member = cpu_to_le##bits(val);                               \
802+}
803+
804+BTRFS_SETGET_FUNCS(device_type, struct btrfs_dev_item, type, 64);
805+BTRFS_SETGET_FUNCS(device_total_bytes, struct btrfs_dev_item, total_bytes, 64);
806+BTRFS_SETGET_FUNCS(device_bytes_used, struct btrfs_dev_item, bytes_used, 64);
807+BTRFS_SETGET_FUNCS(device_io_align, struct btrfs_dev_item, io_align, 32);
808+BTRFS_SETGET_FUNCS(device_io_width, struct btrfs_dev_item, io_width, 32);
809+BTRFS_SETGET_FUNCS(device_start_offset, struct btrfs_dev_item,
810+                  start_offset, 64);
811+BTRFS_SETGET_FUNCS(device_sector_size, struct btrfs_dev_item, sector_size, 32);
812+BTRFS_SETGET_FUNCS(device_id, struct btrfs_dev_item, devid, 64);
813+BTRFS_SETGET_FUNCS(device_group, struct btrfs_dev_item, dev_group, 32);
814+BTRFS_SETGET_FUNCS(device_seek_speed, struct btrfs_dev_item, seek_speed, 8);
815+BTRFS_SETGET_FUNCS(device_bandwidth, struct btrfs_dev_item, bandwidth, 8);
816+BTRFS_SETGET_FUNCS(device_generation, struct btrfs_dev_item, generation, 64);
817+
818+BTRFS_SETGET_STACK_FUNCS(stack_device_type, struct btrfs_dev_item, type, 64);
819+BTRFS_SETGET_STACK_FUNCS(stack_device_total_bytes, struct btrfs_dev_item,
820+                        total_bytes, 64);
821+BTRFS_SETGET_STACK_FUNCS(stack_device_bytes_used, struct btrfs_dev_item,
822+                        bytes_used, 64);
823+BTRFS_SETGET_STACK_FUNCS(stack_device_io_align, struct btrfs_dev_item,
824+                        io_align, 32);
825+BTRFS_SETGET_STACK_FUNCS(stack_device_io_width, struct btrfs_dev_item,
826+                        io_width, 32);
827+BTRFS_SETGET_STACK_FUNCS(stack_device_sector_size, struct btrfs_dev_item,
828+                        sector_size, 32);
829+BTRFS_SETGET_STACK_FUNCS(stack_device_id, struct btrfs_dev_item, devid, 64);
830+BTRFS_SETGET_STACK_FUNCS(stack_device_group, struct btrfs_dev_item,
831+                        dev_group, 32);
832+BTRFS_SETGET_STACK_FUNCS(stack_device_seek_speed, struct btrfs_dev_item,
833+                        seek_speed, 8);
834+BTRFS_SETGET_STACK_FUNCS(stack_device_bandwidth, struct btrfs_dev_item,
835+                        bandwidth, 8);
836+BTRFS_SETGET_STACK_FUNCS(stack_device_generation, struct btrfs_dev_item,
837+                        generation, 64);
838+
839+static inline char *btrfs_device_uuid(struct btrfs_dev_item *d)
840+{
841+       return (char *)d + offsetof(struct btrfs_dev_item, uuid);
842+}
843+
844+static inline char *btrfs_device_fsid(struct btrfs_dev_item *d)
845+{
846+       return (char *)d + offsetof(struct btrfs_dev_item, fsid);
847+}
848+
849+BTRFS_SETGET_FUNCS(chunk_length, struct btrfs_chunk, length, 64);
850+BTRFS_SETGET_FUNCS(chunk_owner, struct btrfs_chunk, owner, 64);
851+BTRFS_SETGET_FUNCS(chunk_stripe_len, struct btrfs_chunk, stripe_len, 64);
852+BTRFS_SETGET_FUNCS(chunk_io_align, struct btrfs_chunk, io_align, 32);
853+BTRFS_SETGET_FUNCS(chunk_io_width, struct btrfs_chunk, io_width, 32);
854+BTRFS_SETGET_FUNCS(chunk_sector_size, struct btrfs_chunk, sector_size, 32);
855+BTRFS_SETGET_FUNCS(chunk_type, struct btrfs_chunk, type, 64);
856+BTRFS_SETGET_FUNCS(chunk_num_stripes, struct btrfs_chunk, num_stripes, 16);
857+BTRFS_SETGET_FUNCS(chunk_sub_stripes, struct btrfs_chunk, sub_stripes, 16);
858+BTRFS_SETGET_FUNCS(stripe_devid, struct btrfs_stripe, devid, 64);
859+BTRFS_SETGET_FUNCS(stripe_offset, struct btrfs_stripe, offset, 64);
860+
861+static inline char *btrfs_stripe_dev_uuid(struct btrfs_stripe *s)
862+{
863+       return (char *)s + offsetof(struct btrfs_stripe, dev_uuid);
864+}
865+
866+BTRFS_SETGET_STACK_FUNCS(stack_chunk_length, struct btrfs_chunk, length, 64);
867+BTRFS_SETGET_STACK_FUNCS(stack_chunk_owner, struct btrfs_chunk, owner, 64);
868+BTRFS_SETGET_STACK_FUNCS(stack_chunk_stripe_len, struct btrfs_chunk,
869+                        stripe_len, 64);
870+BTRFS_SETGET_STACK_FUNCS(stack_chunk_io_align, struct btrfs_chunk,
871+                        io_align, 32);
872+BTRFS_SETGET_STACK_FUNCS(stack_chunk_io_width, struct btrfs_chunk,
873+                        io_width, 32);
874+BTRFS_SETGET_STACK_FUNCS(stack_chunk_sector_size, struct btrfs_chunk,
875+                        sector_size, 32);
876+BTRFS_SETGET_STACK_FUNCS(stack_chunk_type, struct btrfs_chunk, type, 64);
877+BTRFS_SETGET_STACK_FUNCS(stack_chunk_num_stripes, struct btrfs_chunk,
878+                        num_stripes, 16);
879+BTRFS_SETGET_STACK_FUNCS(stack_chunk_sub_stripes, struct btrfs_chunk,
880+                        sub_stripes, 16);
881+BTRFS_SETGET_STACK_FUNCS(stack_stripe_devid, struct btrfs_stripe, devid, 64);
882+BTRFS_SETGET_STACK_FUNCS(stack_stripe_offset, struct btrfs_stripe, offset, 64);
883+
884+static inline struct btrfs_stripe *btrfs_stripe_nr(struct btrfs_chunk *c,
885+                                                  int nr)
886+{
887+       unsigned long offset = (unsigned long)c;
888+       offset += offsetof(struct btrfs_chunk, stripe);
889+       offset += nr * sizeof(struct btrfs_stripe);
890+       return (struct btrfs_stripe *)offset;
891+}
892+
893+static inline char *btrfs_stripe_dev_uuid_nr(struct btrfs_chunk *c, int nr)
894+{
895+       return btrfs_stripe_dev_uuid(btrfs_stripe_nr(c, nr));
896+}
897+
898+static inline u64 btrfs_stripe_offset_nr(struct extent_buffer *eb,
899+                                        struct btrfs_chunk *c, int nr)
900+{
901+       return btrfs_stripe_offset(eb, btrfs_stripe_nr(c, nr));
902+}
903+
904+static inline void btrfs_set_stripe_offset_nr(struct extent_buffer *eb,
905+                                            struct btrfs_chunk *c, int nr,
906+                                            u64 val)
907+{
908+       btrfs_set_stripe_offset(eb, btrfs_stripe_nr(c, nr), val);
909+}
910+
911+static inline u64 btrfs_stripe_devid_nr(struct extent_buffer *eb,
912+                                        struct btrfs_chunk *c, int nr)
913+{
914+       return btrfs_stripe_devid(eb, btrfs_stripe_nr(c, nr));
915+}
916+
917+static inline void btrfs_set_stripe_devid_nr(struct extent_buffer *eb,
918+                                            struct btrfs_chunk *c, int nr,
919+                                            u64 val)
920+{
921+       btrfs_set_stripe_devid(eb, btrfs_stripe_nr(c, nr), val);
922+}
923+
924+/* struct btrfs_block_group_item */
925+BTRFS_SETGET_STACK_FUNCS(block_group_used, struct btrfs_block_group_item,
926+                        used, 64);
927+BTRFS_SETGET_FUNCS(disk_block_group_used, struct btrfs_block_group_item,
928+                        used, 64);
929+BTRFS_SETGET_STACK_FUNCS(block_group_chunk_objectid,
930+                       struct btrfs_block_group_item, chunk_objectid, 64);
931+
932+BTRFS_SETGET_FUNCS(disk_block_group_chunk_objectid,
933+                  struct btrfs_block_group_item, chunk_objectid, 64);
934+BTRFS_SETGET_FUNCS(disk_block_group_flags,
935+                  struct btrfs_block_group_item, flags, 64);
936+BTRFS_SETGET_STACK_FUNCS(block_group_flags,
937+                       struct btrfs_block_group_item, flags, 64);
938+
939+/* struct btrfs_inode_ref */
940+BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16);
941+BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64);
942+
943+/* struct btrfs_inode_item */
944+BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64);
945+BTRFS_SETGET_FUNCS(inode_sequence, struct btrfs_inode_item, sequence, 64);
946+BTRFS_SETGET_FUNCS(inode_transid, struct btrfs_inode_item, transid, 64);
947+BTRFS_SETGET_FUNCS(inode_size, struct btrfs_inode_item, size, 64);
948+BTRFS_SETGET_FUNCS(inode_nbytes, struct btrfs_inode_item, nbytes, 64);
949+BTRFS_SETGET_FUNCS(inode_block_group, struct btrfs_inode_item, block_group, 64);
950+BTRFS_SETGET_FUNCS(inode_nlink, struct btrfs_inode_item, nlink, 32);
951+BTRFS_SETGET_FUNCS(inode_uid, struct btrfs_inode_item, uid, 32);
952+BTRFS_SETGET_FUNCS(inode_gid, struct btrfs_inode_item, gid, 32);
953+BTRFS_SETGET_FUNCS(inode_mode, struct btrfs_inode_item, mode, 32);
954+BTRFS_SETGET_FUNCS(inode_rdev, struct btrfs_inode_item, rdev, 64);
955+BTRFS_SETGET_FUNCS(inode_flags, struct btrfs_inode_item, flags, 64);
956+
957+BTRFS_SETGET_STACK_FUNCS(stack_inode_generation,
958+                        struct btrfs_inode_item, generation, 64);
959+BTRFS_SETGET_STACK_FUNCS(stack_inode_sequence,
960+                        struct btrfs_inode_item, generation, 64);
961+BTRFS_SETGET_STACK_FUNCS(stack_inode_size,
962+                        struct btrfs_inode_item, size, 64);
963+BTRFS_SETGET_STACK_FUNCS(stack_inode_nbytes,
964+                        struct btrfs_inode_item, nbytes, 64);
965+BTRFS_SETGET_STACK_FUNCS(stack_inode_block_group,
966+                        struct btrfs_inode_item, block_group, 64);
967+BTRFS_SETGET_STACK_FUNCS(stack_inode_nlink,
968+                        struct btrfs_inode_item, nlink, 32);
969+BTRFS_SETGET_STACK_FUNCS(stack_inode_uid,
970+                        struct btrfs_inode_item, uid, 32);
971+BTRFS_SETGET_STACK_FUNCS(stack_inode_gid,
972+                        struct btrfs_inode_item, gid, 32);
973+BTRFS_SETGET_STACK_FUNCS(stack_inode_mode,
974+                        struct btrfs_inode_item, mode, 32);
975+BTRFS_SETGET_STACK_FUNCS(stack_inode_rdev,
976+                        struct btrfs_inode_item, rdev, 64);
977+BTRFS_SETGET_STACK_FUNCS(stack_inode_flags,
978+                        struct btrfs_inode_item, flags, 64);
979+
980+BTRFS_SETGET_FUNCS(timespec_sec, struct btrfs_timespec, sec, 64);
981+BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_timespec, nsec, 32);
982+BTRFS_SETGET_STACK_FUNCS(stack_timespec_sec, struct btrfs_timespec,
983+                        sec, 64);
984+BTRFS_SETGET_STACK_FUNCS(stack_timespec_nsec, struct btrfs_timespec,
985+                        nsec, 32);
986+
987+/* struct btrfs_dev_extent */
988+BTRFS_SETGET_FUNCS(dev_extent_chunk_tree, struct btrfs_dev_extent,
989+                  chunk_tree, 64);
990+BTRFS_SETGET_FUNCS(dev_extent_chunk_objectid, struct btrfs_dev_extent,
991+                  chunk_objectid, 64);
992+BTRFS_SETGET_FUNCS(dev_extent_chunk_offset, struct btrfs_dev_extent,
993+                  chunk_offset, 64);
994+BTRFS_SETGET_FUNCS(dev_extent_length, struct btrfs_dev_extent, length, 64);
995+
996+static inline u8 *btrfs_dev_extent_chunk_tree_uuid(struct btrfs_dev_extent *dev)
997+{
998+       unsigned long ptr = offsetof(struct btrfs_dev_extent, chunk_tree_uuid);
999+       return (u8 *)((unsigned long)dev + ptr);
1000+}
1001+
1002+/* struct btrfs_extent_ref */
1003+BTRFS_SETGET_FUNCS(ref_root, struct btrfs_extent_ref, root, 64);
1004+BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64);
1005+BTRFS_SETGET_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64);
1006+BTRFS_SETGET_FUNCS(ref_num_refs, struct btrfs_extent_ref, num_refs, 32);
1007+
1008+BTRFS_SETGET_STACK_FUNCS(stack_ref_root, struct btrfs_extent_ref, root, 64);
1009+BTRFS_SETGET_STACK_FUNCS(stack_ref_generation, struct btrfs_extent_ref,
1010+                        generation, 64);
1011+BTRFS_SETGET_STACK_FUNCS(stack_ref_objectid, struct btrfs_extent_ref,
1012+                        objectid, 64);
1013+BTRFS_SETGET_STACK_FUNCS(stack_ref_num_refs, struct btrfs_extent_ref,
1014+                        num_refs, 32);
1015+
1016+/* struct btrfs_extent_item */
1017+BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32);
1018+BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item,
1019+                        refs, 32);
1020+
1021+/* struct btrfs_node */
1022+BTRFS_SETGET_FUNCS(key_blockptr, struct btrfs_key_ptr, blockptr, 64);
1023+BTRFS_SETGET_FUNCS(key_generation, struct btrfs_key_ptr, generation, 64);
1024+
1025+static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr)
1026+{
1027+       unsigned long ptr;
1028+       ptr = offsetof(struct btrfs_node, ptrs) +
1029+               sizeof(struct btrfs_key_ptr) * nr;
1030+       return btrfs_key_blockptr(eb, (struct btrfs_key_ptr *)ptr);
1031+}
1032+
1033+static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
1034+                                          int nr, u64 val)
1035+{
1036+       unsigned long ptr;
1037+       ptr = offsetof(struct btrfs_node, ptrs) +
1038+               sizeof(struct btrfs_key_ptr) * nr;
1039+       btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val);
1040+}
1041+
1042+static inline u64 btrfs_node_ptr_generation(struct extent_buffer *eb, int nr)
1043+{
1044+       unsigned long ptr;
1045+       ptr = offsetof(struct btrfs_node, ptrs) +
1046+               sizeof(struct btrfs_key_ptr) * nr;
1047+       return btrfs_key_generation(eb, (struct btrfs_key_ptr *)ptr);
1048+}
1049+
1050+static inline void btrfs_set_node_ptr_generation(struct extent_buffer *eb,
1051+                                                int nr, u64 val)
1052+{
1053+       unsigned long ptr;
1054+       ptr = offsetof(struct btrfs_node, ptrs) +
1055+               sizeof(struct btrfs_key_ptr) * nr;
1056+       btrfs_set_key_generation(eb, (struct btrfs_key_ptr *)ptr, val);
1057+}
1058+
1059+static inline unsigned long btrfs_node_key_ptr_offset(int nr)
1060+{
1061+       return offsetof(struct btrfs_node, ptrs) +
1062+               sizeof(struct btrfs_key_ptr) * nr;
1063+}
1064+
1065+static inline void btrfs_node_key(struct extent_buffer *eb,
1066+                                 struct btrfs_disk_key *disk_key, int nr)
1067+{
1068+       unsigned long ptr;
1069+       ptr = btrfs_node_key_ptr_offset(nr);
1070+       read_eb_member(eb, (struct btrfs_key_ptr *)ptr,
1071+                      struct btrfs_key_ptr, key, disk_key);
1072+}
1073+
1074+/* struct btrfs_item */
1075+BTRFS_SETGET_FUNCS(item_offset, struct btrfs_item, offset, 32);
1076+BTRFS_SETGET_FUNCS(item_size, struct btrfs_item, size, 32);
1077+
1078+static inline unsigned long btrfs_item_nr_offset(int nr)
1079+{
1080+       return offsetof(struct btrfs_leaf, items) +
1081+               sizeof(struct btrfs_item) * nr;
1082+}
1083+
1084+static inline struct btrfs_item *btrfs_item_nr(struct extent_buffer *eb,
1085+                                              int nr)
1086+{
1087+       return (struct btrfs_item *)btrfs_item_nr_offset(nr);
1088+}
1089+
1090+static inline u32 btrfs_item_end(struct extent_buffer *eb,
1091+                                struct btrfs_item *item)
1092+{
1093+       return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item);
1094+}
1095+
1096+static inline u32 btrfs_item_end_nr(struct extent_buffer *eb, int nr)
1097+{
1098+       return btrfs_item_end(eb, btrfs_item_nr(eb, nr));
1099+}
1100+
1101+static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr)
1102+{
1103+       return btrfs_item_offset(eb, btrfs_item_nr(eb, nr));
1104+}
1105+
1106+static inline u32 btrfs_item_size_nr(struct extent_buffer *eb, int nr)
1107+{
1108+       return btrfs_item_size(eb, btrfs_item_nr(eb, nr));
1109+}
1110+
1111+static inline void btrfs_item_key(struct extent_buffer *eb,
1112+                          struct btrfs_disk_key *disk_key, int nr)
1113+{
1114+       struct btrfs_item *item = btrfs_item_nr(eb, nr);
1115+       read_eb_member(eb, item, struct btrfs_item, key, disk_key);
1116+}
1117+
1118+/*
1119+ * struct btrfs_root_ref
1120+ */
1121+BTRFS_SETGET_FUNCS(root_ref_dirid, struct btrfs_root_ref, dirid, 64);
1122+BTRFS_SETGET_FUNCS(root_ref_sequence, struct btrfs_root_ref, sequence, 64);
1123+BTRFS_SETGET_FUNCS(root_ref_name_len, struct btrfs_root_ref, name_len, 16);
1124+
1125+/* struct btrfs_dir_item */
1126+BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16);
1127+BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8);
1128+BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16);
1129+BTRFS_SETGET_FUNCS(dir_transid, struct btrfs_dir_item, transid, 64);
1130+
1131+static inline void btrfs_dir_item_key(struct extent_buffer *eb,
1132+                                     struct btrfs_dir_item *item,
1133+                                     struct btrfs_disk_key *key)
1134+{
1135+       read_eb_member(eb, item, struct btrfs_dir_item, location, key);
1136+}
1137+
1138+/* struct btrfs_disk_key */
1139+BTRFS_SETGET_STACK_FUNCS(disk_key_objectid, struct btrfs_disk_key,
1140+                        objectid, 64);
1141+BTRFS_SETGET_STACK_FUNCS(disk_key_offset, struct btrfs_disk_key, offset, 64);
1142+BTRFS_SETGET_STACK_FUNCS(disk_key_type, struct btrfs_disk_key, type, 8);
1143+
1144+static inline void btrfs_disk_key_to_cpu(struct btrfs_key *cpu,
1145+                                        struct btrfs_disk_key *disk)
1146+{
1147+       cpu->offset = le64_to_cpu(disk->offset);
1148+       cpu->type = disk->type;
1149+       cpu->objectid = le64_to_cpu(disk->objectid);
1150+}
1151+
1152+static inline void btrfs_cpu_key_to_disk(struct btrfs_disk_key *disk,
1153+                                        struct btrfs_key *cpu)
1154+{
1155+       disk->offset = cpu_to_le64(cpu->offset);
1156+       disk->type = cpu->type;
1157+       disk->objectid = cpu_to_le64(cpu->objectid);
1158+}
1159+
1160+static inline void btrfs_node_key_to_cpu(struct extent_buffer *eb,
1161+                                 struct btrfs_key *key, int nr)
1162+{
1163+       struct btrfs_disk_key disk_key;
1164+       btrfs_node_key(eb, &disk_key, nr);
1165+       btrfs_disk_key_to_cpu(key, &disk_key);
1166+}
1167+
1168+static inline void btrfs_item_key_to_cpu(struct extent_buffer *eb,
1169+                                 struct btrfs_key *key, int nr)
1170+{
1171+       struct btrfs_disk_key disk_key;
1172+       btrfs_item_key(eb, &disk_key, nr);
1173+       btrfs_disk_key_to_cpu(key, &disk_key);
1174+}
1175+
1176+static inline void btrfs_dir_item_key_to_cpu(struct extent_buffer *eb,
1177+                                     struct btrfs_dir_item *item,
1178+                                     struct btrfs_key *key)
1179+{
1180+       struct btrfs_disk_key disk_key;
1181+       btrfs_dir_item_key(eb, item, &disk_key);
1182+       btrfs_disk_key_to_cpu(key, &disk_key);
1183+}
1184+
1185+static inline u8 btrfs_key_type(struct btrfs_key *key)
1186+{
1187+       return key->type;
1188+}
1189+
1190+static inline void btrfs_set_key_type(struct btrfs_key *key, u8 val)
1191+{
1192+       key->type = val;
1193+}
1194+
1195+static inline u64 btrfs_super_devid(struct btrfs_super_block *disk_super)
1196+{
1197+	return le64_to_cpu(disk_super->dev_item.devid);
1198+}
1199+
1200+/* struct btrfs_header */
1201+BTRFS_SETGET_HEADER_FUNCS(header_bytenr, struct btrfs_header, bytenr, 64);
1202+BTRFS_SETGET_HEADER_FUNCS(header_generation, struct btrfs_header,
1203+                         generation, 64);
1204+BTRFS_SETGET_HEADER_FUNCS(header_owner, struct btrfs_header, owner, 64);
1205+BTRFS_SETGET_HEADER_FUNCS(header_nritems, struct btrfs_header, nritems, 32);
1206+BTRFS_SETGET_HEADER_FUNCS(header_flags, struct btrfs_header, flags, 64);
1207+BTRFS_SETGET_HEADER_FUNCS(header_level, struct btrfs_header, level, 8);
1208+
1209+/* struct btrfs_root_item */
1210+BTRFS_SETGET_FUNCS(disk_root_generation, struct btrfs_root_item,
1211+                  generation, 64);
1212+BTRFS_SETGET_FUNCS(disk_root_refs, struct btrfs_root_item, refs, 32);
1213+BTRFS_SETGET_FUNCS(disk_root_bytenr, struct btrfs_root_item, bytenr, 64);
1214+BTRFS_SETGET_FUNCS(disk_root_level, struct btrfs_root_item, level, 8);
1215+
1216+BTRFS_SETGET_STACK_FUNCS(root_generation, struct btrfs_root_item,
1217+                        generation, 64);
1218+BTRFS_SETGET_STACK_FUNCS(root_bytenr, struct btrfs_root_item, bytenr, 64);
1219+BTRFS_SETGET_STACK_FUNCS(root_level, struct btrfs_root_item, level, 8);
1220+BTRFS_SETGET_STACK_FUNCS(root_dirid, struct btrfs_root_item, root_dirid, 64);
1221+BTRFS_SETGET_STACK_FUNCS(root_refs, struct btrfs_root_item, refs, 32);
1222+BTRFS_SETGET_STACK_FUNCS(root_flags, struct btrfs_root_item, flags, 64);
1223+BTRFS_SETGET_STACK_FUNCS(root_used, struct btrfs_root_item, bytes_used, 64);
1224+BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64);
1225+BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
1226+                        last_snapshot, 64);
1227+
1228+/* struct btrfs_super_block */
1229+
1230+BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
1231+BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64);
1232+BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
1233+                        generation, 64);
1234+BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64);
1235+BTRFS_SETGET_STACK_FUNCS(super_sys_array_size,
1236+                        struct btrfs_super_block, sys_chunk_array_size, 32);
1237+BTRFS_SETGET_STACK_FUNCS(super_chunk_root_generation,
1238+                        struct btrfs_super_block, chunk_root_generation, 64);
1239+BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block,
1240+                        root_level, 8);
1241+BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,
1242+                        chunk_root, 64);
1243+BTRFS_SETGET_STACK_FUNCS(super_chunk_root_level, struct btrfs_super_block,
1244+                        chunk_root_level, 8);
1245+BTRFS_SETGET_STACK_FUNCS(super_log_root, struct btrfs_super_block,
1246+                        log_root, 64);
1247+BTRFS_SETGET_STACK_FUNCS(super_log_root_transid, struct btrfs_super_block,
1248+                        log_root_transid, 64);
1249+BTRFS_SETGET_STACK_FUNCS(super_log_root_level, struct btrfs_super_block,
1250+                        log_root_level, 8);
1251+BTRFS_SETGET_STACK_FUNCS(super_total_bytes, struct btrfs_super_block,
1252+                        total_bytes, 64);
1253+BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block,
1254+                        bytes_used, 64);
1255+BTRFS_SETGET_STACK_FUNCS(super_sectorsize, struct btrfs_super_block,
1256+                        sectorsize, 32);
1257+BTRFS_SETGET_STACK_FUNCS(super_nodesize, struct btrfs_super_block,
1258+                        nodesize, 32);
1259+BTRFS_SETGET_STACK_FUNCS(super_leafsize, struct btrfs_super_block,
1260+                        leafsize, 32);
1261+BTRFS_SETGET_STACK_FUNCS(super_stripesize, struct btrfs_super_block,
1262+                        stripesize, 32);
1263+BTRFS_SETGET_STACK_FUNCS(super_root_dir, struct btrfs_super_block,
1264+                        root_dir_objectid, 64);
1265+BTRFS_SETGET_STACK_FUNCS(super_num_devices, struct btrfs_super_block,
1266+                        num_devices, 64);
1267+BTRFS_SETGET_STACK_FUNCS(super_compat_flags, struct btrfs_super_block,
1268+                        compat_flags, 64);
1269+BTRFS_SETGET_STACK_FUNCS(super_compat_ro_flags, struct btrfs_super_block,
1270+                        compat_flags, 64);
1271+BTRFS_SETGET_STACK_FUNCS(super_incompat_flags, struct btrfs_super_block,
1272+                        incompat_flags, 64);
1273+BTRFS_SETGET_STACK_FUNCS(super_csum_type, struct btrfs_super_block,
1274+                        csum_type, 16);
1275+
1276+static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
1277+{
1278+       int t = btrfs_super_csum_type(s);
1279+       //BUG_ON(t >= ARRAY_SIZE(btrfs_csum_sizes));
1280+       return btrfs_csum_sizes[t];
1281+}
1282+
1283+static inline unsigned long btrfs_leaf_data(struct extent_buffer *l)
1284+{
1285+       return offsetof(struct btrfs_leaf, items);
1286+}
1287+
1288+/* struct btrfs_file_extent_item */
1289+BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8);
1290+
1291+static inline unsigned long btrfs_file_extent_inline_start(struct
1292+                                                  btrfs_file_extent_item *e)
1293+{
1294+       unsigned long offset = (unsigned long)e;
1295+       offset += offsetof(struct btrfs_file_extent_item, disk_bytenr);
1296+       return offset;
1297+}
1298+
1299+static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize)
1300+{
1301+       return offsetof(struct btrfs_file_extent_item, disk_bytenr) + datasize;
1302+}
1303+
1304+BTRFS_SETGET_FUNCS(file_extent_disk_bytenr, struct btrfs_file_extent_item,
1305+                  disk_bytenr, 64);
1306+BTRFS_SETGET_FUNCS(file_extent_generation, struct btrfs_file_extent_item,
1307+                  generation, 64);
1308+BTRFS_SETGET_FUNCS(file_extent_disk_num_bytes, struct btrfs_file_extent_item,
1309+                  disk_num_bytes, 64);
1310+BTRFS_SETGET_FUNCS(file_extent_offset, struct btrfs_file_extent_item,
1311+                 offset, 64);
1312+BTRFS_SETGET_FUNCS(file_extent_num_bytes, struct btrfs_file_extent_item,
1313+                  num_bytes, 64);
1314+BTRFS_SETGET_FUNCS(file_extent_ram_bytes, struct btrfs_file_extent_item,
1315+                  ram_bytes, 64);
1316+BTRFS_SETGET_FUNCS(file_extent_compression, struct btrfs_file_extent_item,
1317+                  compression, 8);
1318+BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item,
1319+                  encryption, 8);
1320+BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
1321+                  other_encoding, 16);
1322+
1323+/* this returns the number of file bytes represented by the inline item.
1324+ * If an item is compressed, this is the uncompressed size
1325+ */
1326+static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
1327+                                       struct btrfs_file_extent_item *e)
1328+{
1329+       return btrfs_file_extent_ram_bytes(eb, e);
1330+}
1331+
1332+/*
1333+ * this returns the number of bytes used by the item on disk, minus the
1334+ * size of any extent headers.  If a file is compressed on disk, this is
1335+ * the compressed size
1336+ */
1337+static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
1338+                                                   struct btrfs_item *e)
1339+{
1340+       unsigned long offset;
1341+       offset = offsetof(struct btrfs_file_extent_item, disk_bytenr);
1342+       return btrfs_item_size(eb, e) - offset;
1343+}
1344+
1345+static inline u32 btrfs_level_size(struct btrfs_root *root, int level) {
1346+       if (level == 0)
1347+               return root->leafsize;
1348+       return root->nodesize;
1349+}
1350+
1351+static inline u32 btrfs_root_level_size(struct btrfs_super_block *sb) {
1352+       return btrfs_super_root_level(sb) == 0 ?
1353+               btrfs_super_leafsize(sb) :
1354+               btrfs_super_nodesize(sb);
1355+}
1356+
1357+static inline u32 btrfs_chunk_root_level_size(struct btrfs_super_block *sb) {
1358+       return btrfs_super_chunk_root_level(sb) == 0 ?
1359+               btrfs_super_leafsize(sb) :
1360+               btrfs_super_nodesize(sb);
1361+}
1362+
1363+/* helper function to cast into the data area of the leaf. */
1364+#define btrfs_item_ptr(leaf, slot, type) \
1365+       ((type *)(btrfs_leaf_data(leaf) + \
1366+       btrfs_item_offset_nr(leaf, slot)))
1367+
1368+#define btrfs_item_ptr_offset(leaf, slot) \
1369+       ((unsigned long)(btrfs_leaf_data(leaf) + \
1370+       btrfs_item_offset_nr(leaf, slot)))
1371+
1372+/*volumes.h */
1373+
1374+struct btrfs_fs_devices {
1375+       u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
1376+
1377+       /* the device with this id has the most recent coyp of the super */
1378+       u64 latest_devid;
1379+       u64 latest_trans;
1380+       u64 lowest_devid;
1381+       int latest_bdev;
1382+       int lowest_bdev;
1383+       int seeding;
1384+       struct btrfs_fs_devices *seed;
1385+};
1386+
1387+struct btrfs_bio_stripe {
1388+	struct btrfs_device dev;
1389+	u64 physical;
1390+};
1391+
1392+#define MAX_NRSTRIPES 8
1393+struct btrfs_multi_bio {
1394+       int error;
1395+       int num_stripes;
1396+       struct btrfs_bio_stripe stripes[MAX_NRSTRIPES];
1397+};
1398+
1399+#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
1400+                           (sizeof(struct btrfs_bio_stripe) * (n)))
1401+
1402+static int aux_tree_lookup(struct btrfs_root *root,
1403+                          struct btrfs_key *key,
1404+                          struct btrfs_path *path);
1405+
1406+struct cache_extent {
1407+       u64 start;
1408+       u64 size;
1409+};
1410+
1411+struct map_lookup {
1412+       struct cache_extent ce;
1413+       u64 type;
1414+       int io_align;
1415+       int io_width;
1416+       int stripe_len;
1417+       int sector_size;
1418+       int num_stripes;
1419+       int sub_stripes;
1420+        struct btrfs_bio_stripe stripes[MAX_NRSTRIPES];
1421+};
1422+
1423+/* "VFS" things */
1424+
1425+/* file types recognized by grub */
1426+typedef enum {
1427+       BTRFS_REGULAR_FILE,
1428+       BTRFS_DIRECTORY_FILE,
1429+       BTRFS_SYMLINK_FILE,
1430+       BTRFS_UNKNOWN_FILE
1431+} btrfs_file_type;
1432+
1433+static inline int coord_is_root(struct btrfs_root *root,
1434+                               struct btrfs_path *path)
1435+{
1436+       return btrfs_header_bytenr(&path->nodes[0]) ==
1437+               btrfs_header_bytenr(&root->node);
1438+}
1439+
1440+static inline btrfs_file_type btrfs_get_file_type (int mode)
1441+{
1442+       if (S_ISLNK(mode))
1443+               return BTRFS_SYMLINK_FILE;
1444+       if (S_ISREG(mode))
1445+               return BTRFS_REGULAR_FILE;
1446+       if (S_ISDIR(mode))
1447+               return BTRFS_DIRECTORY_FILE;
1448+       return BTRFS_UNKNOWN_FILE;
1449+}
1450+
1451+#define min_t(type,x,y)                                                       \
1452+       ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
1453+#define max_t(type,x,y)                                                       \
1454+       ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
1455+
1456+
1457+int sys_array_lookup(struct map_lookup *map, u64 logical);
1458+int tree_chunk_lookup(struct map_lookup *map,
1459+                     u64 logical);
1460+int __btrfs_map_block(u64 logical, u64 *length,
1461+                     struct btrfs_multi_bio *multi_ret, int mirror_num);
1462+int read_tree_block(struct btrfs_root *root,
1463+                   struct extent_buffer *eb,
1464+                   u64 bytenr, /* logical */
1465+                   u32 blocksize,
1466+                   u64 parent_transid,
1467+                   lookup_pool_id lpid);
1468+int check_read_chunk(struct btrfs_key *key,
1469+                    struct extent_buffer *leaf,
1470+                    struct btrfs_chunk *chunk,
1471+                    struct map_lookup *map,
1472+                    u64 logical);
1473+/*
1474+  Local variables:
1475+  c-indentation-style: "K&R"
1476+  mode-name: "LC"
1477+  c-basic-offset: 8
1478+  tab-width: 8
1479+  fill-column: 80
1480+  scroll-step: 1
1481+  End:
1482+*/
1483\ No newline at end of file
1484diff -up grub-upstream.wip/stage2/builtins.c.btrfs grub-upstream.wip/stage2/builtins.c
1485--- grub-upstream.wip/stage2/builtins.c.btrfs	2012-03-20 05:06:49.000000000 +0000
1486+++ grub-upstream.wip/stage2/builtins.c	2012-03-20 05:11:13.000000000 +0000
1487@@ -2456,6 +2456,16 @@ install_func (char *arg, int flags)
1488 	  else
1489 #endif /* GRUB_UTIL */
1490 	    {
1491+ 	      /*
1492+	       * FIXME: Ugly hack.
1493+	       * Do not write to btrfs partition
1494+	       * without a help of the file system!
1495+	       */
1496+ 	      if (!strcmp(fsys_table[fsys_type].name, "btrfs"))
1497+ 		{
1498+ 		  errnum = ERR_BAD_ARGUMENT;
1499+ 		  goto fail;
1500+ 		}
1501 	      if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
1502 		goto fail;
1503 	    }
1504@@ -4281,6 +4291,7 @@ setup_func (char *arg, int flags)
1505     {"jfs",      "/jfs_stage1_5"},
1506     {"minix",    "/minix_stage1_5"},
1507     {"reiserfs", "/reiserfs_stage1_5"},
1508+    {"btrfs",    "/btrfs_stage1_5"},
1509     {"vstafs",   "/vstafs_stage1_5"},
1510     {"xfs",      "/xfs_stage1_5"}
1511   };
1512diff -up grub-upstream.wip/stage2/disk_io.c.btrfs grub-upstream.wip/stage2/disk_io.c
1513--- grub-upstream.wip/stage2/disk_io.c.btrfs	2012-03-20 05:06:49.000000000 +0000
1514+++ grub-upstream.wip/stage2/disk_io.c	2012-03-20 05:07:09.000000000 +0000
1515@@ -78,6 +78,9 @@ struct fsys_entry fsys_table[NUM_FSYS +
1516 # ifdef FSYS_ISO9660
1517   {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0},
1518 # endif
1519+# ifdef FSYS_BTRFS
1520+  {"btrfs", btrfs_mount, btrfs_read, btrfs_dir, 0, btrfs_embed},
1521+# endif
1522   /* XX FFS should come last as it's superblock is commonly crossing tracks
1523      on floppies from track 1 to 2, while others only use 1.  */
1524 # ifdef FSYS_FFS
1525diff -up grub-upstream.wip/stage2/filesys.h.btrfs grub-upstream.wip/stage2/filesys.h
1526--- grub-upstream.wip/stage2/filesys.h.btrfs	2004-05-14 19:36:43.000000000 +0000
1527+++ grub-upstream.wip/stage2/filesys.h	2012-03-20 05:07:09.000000000 +0000
1528@@ -77,6 +77,16 @@ int reiserfs_embed (int *start_sector, i
1529 #define FSYS_REISERFS_NUM 0
1530 #endif
1531
1532+#ifdef FSYS_BTRFS
1533+#define FSYS_BTRFS_NUM 1
1534+int btrfs_mount (void);
1535+int btrfs_read (char *buf, int len);
1536+int btrfs_dir (char *dirname);
1537+int btrfs_embed (int *start_sector, int needed_sectors);
1538+#else
1539+#define FSYS_BTRFS_NUM 0
1540+#endif
1541+
1542 #ifdef FSYS_VSTAFS
1543 #define FSYS_VSTAFS_NUM 1
1544 int vstafs_mount (void);
1545@@ -127,8 +137,8 @@ int iso9660_dir (char *dirname);
1546 #ifndef NUM_FSYS
1547 #define NUM_FSYS	\
1548   (FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM	\
1549-   + FSYS_REISERFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM + FSYS_XFS_NUM	\
1550-   + FSYS_TFTP_NUM + FSYS_ISO9660_NUM + FSYS_UFS2_NUM)
1551+   + FSYS_REISERFS_NUM + FSYS_BTRFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM \
1552+   + FSYS_XFS_NUM + FSYS_TFTP_NUM + FSYS_ISO9660_NUM + FSYS_UFS2_NUM)
1553 #endif
1554
1555 /* defines for the block filesystem info area */
1556diff -up /dev/null grub-upstream.wip/stage2/fsys_btrfs.c
1557--- /dev/null	2009-06-03 06:46:26.160951000 +0000
1558+++ grub-upstream.wip/stage2/fsys_btrfs.c	2012-03-20 05:07:09.000000000 +0000
1559@@ -0,0 +1,1820 @@
1560+/* fsys_btrfs.c - an implementation for the Btrfs filesystem
1561+ *
1562+ * Copyright 2009 Red Hat, Inc.  All rights reserved.
1563+ *
1564+ * This program is free software; you can redistribute it and/or modify
1565+ * it under the terms of the GNU General Public License as published by
1566+ * the Free Software Foundation; either version 2 of the License, or
1567+ * (at your option) any later version.
1568+ *
1569+ * This program is distributed in the hope that it will be useful,
1570+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1571+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1572+ * GNU General Public License for more details.
1573+ *
1574+ * You should have received a copy of the GNU General Public License
1575+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1576+ */
1577+
1578+#ifdef FSYS_BTRFS
1579+
1580+#include "shared.h"
1581+#include "filesys.h"
1582+#include "btrfs.h"
1583+
1584+#define BTRFS_VERBOSE 0
1585+
1586+/* Cache layouts */
1587+
1588+#define LOOKUP_CACHE_BUF_SIZE   (4096)
1589+#define LOOKUP_CACHE_SIZE       (LOOKUP_CACHE_BUF_SIZE * LAST_LOOKUP_POOL)
1590+#define BTRFS_FS_INFO							\
1591+	((struct btrfs_fs_info *)((unsigned long)FSYS_BUF +		\
1592+				  LOOKUP_CACHE_SIZE))
1593+#define BTRFS_CACHE_SIZE         (sizeof(struct btrfs_fs_info) +	\
1594+				  LOOKUP_CACHE_SIZE)
1595+#define BTRFS_TREE_ROOT          (&BTRFS_FS_INFO->tree_root)
1596+#define BTRFS_CHUNK_ROOT         (&BTRFS_FS_INFO->chunk_root)
1597+#define BTRFS_FS_ROOT            (&BTRFS_FS_INFO->fs_root)
1598+#define BTRFS_SUPER              (&BTRFS_FS_INFO->sb_copy)
1599+#define BTRFS_DEVICES            (&BTRFS_FS_INFO->devices[0])
1600+#define BTRFS_FILE_INFO          (&BTRFS_FS_INFO->file_info)
1601+#define BTRFS_FILE_INFO_KEY      (&BTRFS_FILE_INFO->key)
1602+
1603+#define BTRFS_VOLATILE_DEV_CACHE				        \
1604+	(&BTRFS_FS_INFO->devices[BTRFS_NUM_CACHED_DEVICES])
1605+
1606+#define LOOKUP_CACHE_BUF(id) ((char *)((unsigned long)FSYS_BUF +	\
1607+				       id * LOOKUP_CACHE_BUF_SIZE))
1608+
1609+#define noop   do {; } while (0)
1610+
1611+#if BTRFS_VERBOSE
1612+#define btrfs_msg(format, ...) printf(format , ## __VA_ARGS__)
1613+#else
1614+#define btrfs_msg(format, args...) noop
1615+#endif
1616+
1617+/* compile-time check to make sure we don't overlap
1618+   filesystem buffer */
1619+static inline void check_btrfs_cache_size(void)
1620+{
1621+	cassert(BTRFS_CACHE_SIZE <= FSYS_BUFLEN);
1622+}
1623+
1624+static inline u64 btrfs_sb_offset(int mirror)
1625+{
1626+	u64 start = 16 * 1024;
1627+	if (mirror)
1628+		return start << (BTRFS_SUPER_MIRROR_SHIFT * mirror);
1629+	return BTRFS_SUPER_INFO_OFFSET;
1630+}
1631+
1632+static inline char *grab_lookup_cache(lookup_pool_id lpid)
1633+{
1634+	char *buf = LOOKUP_CACHE_BUF(lpid);
1635+	memset(buf, 0, LOOKUP_CACHE_BUF_SIZE);
1636+	return buf;
1637+}
1638+
1639+static inline struct btrfs_path *btrfs_grab_path(lookup_pool_id lpid)
1640+{
1641+	return &BTRFS_FS_INFO->paths[lpid];
1642+}
1643+
1644+static inline void btrfs_set_path_key(struct btrfs_path *path,
1645+				      struct btrfs_key *key)
1646+{
1647+	btrfs_item_key_to_cpu(&path->nodes[0],
1648+			      key,
1649+			      path->slots[0]);
1650+}
1651+
1652+static inline void btrfs_update_file_info(struct btrfs_path *path)
1653+{
1654+	btrfs_set_path_key(path, BTRFS_FILE_INFO_KEY);
1655+}
1656+
1657+static inline void btrfs_set_root_dir_key(struct btrfs_key *key)
1658+{
1659+	key->objectid = BTRFS_FIRST_FREE_OBJECTID;
1660+	btrfs_set_key_type(key, BTRFS_INODE_ITEM_KEY);
1661+	key->offset = 0;
1662+}
1663+
1664+static inline void copy_extent_buffer(struct extent_buffer *dst,
1665+				      struct extent_buffer *src)
1666+{
1667+	char *data = dst->data;
1668+	memcpy(dst, src, sizeof(*dst));
1669+	memcpy(data, src->data, 4096);
1670+	dst->data = data;
1671+}
1672+
1673+static inline void move_extent_buffer(struct extent_buffer *dst,
1674+				      struct extent_buffer *src)
1675+{
1676+	memcpy(dst, src, sizeof(*dst));
1677+}
1678+
1679+static inline void init_btrfs_root (struct btrfs_root *root)
1680+{
1681+	root->node.data = root->data;
1682+}
1683+
1684+static inline void init_btrfs_path(lookup_pool_id lpid)
1685+{
1686+	struct btrfs_path *path;
1687+	path = btrfs_grab_path(lpid);
1688+	path->lpid = lpid;
1689+}
1690+
1691+static inline void init_btrfs_info(void)
1692+{
1693+	int i;
1694+
1695+	memset(BTRFS_FS_INFO, 0, sizeof(struct btrfs_fs_info));
1696+	for(i = 0; i < LAST_LOOKUP_POOL; i++)
1697+		init_btrfs_path(i);
1698+	init_btrfs_root(BTRFS_TREE_ROOT);
1699+	init_btrfs_root(BTRFS_CHUNK_ROOT);
1700+	init_btrfs_root(BTRFS_FS_ROOT);
1701+}
1702+
1703+static void setup_root(struct btrfs_root *root,
1704+		       u32 nodesize,
1705+		       u32 leafsize,
1706+		       u32 sectorsize,
1707+		       u32 stripesize,
1708+		       u64 objectid)
1709+{
1710+	root->nodesize = nodesize;
1711+	root->leafsize = leafsize;
1712+	root->sectorsize = sectorsize;
1713+	root->stripesize = stripesize;
1714+	root->objectid = objectid;
1715+}
1716+
1717+/*
1718+ * Pick up the latest root of a
1719+ * tree with specified @objectid
1720+ */
1721+static int btrfs_find_last_root(struct btrfs_root *tree_root,
1722+				u64 objectid,
1723+				struct btrfs_root_item *item,
1724+				lookup_pool_id lpid)
1725+{
1726+	int ret;
1727+	int slot;
1728+	struct btrfs_key search_key;
1729+	struct btrfs_key found_key;
1730+	struct btrfs_path *path;
1731+
1732+	search_key.objectid = objectid;
1733+	search_key.type = BTRFS_ROOT_ITEM_KEY;
1734+	search_key.offset = (u64)-1;
1735+	path = btrfs_grab_path(lpid);
1736+
1737+	ret = aux_tree_lookup(tree_root, &search_key, path);
1738+	if (ret < 0)
1739+		return 1;
1740+	slot = path->slots[0];
1741+	WARN_ON(slot == 0);
1742+	slot -= 1;
1743+	btrfs_item_key_to_cpu(&path->nodes[0], &found_key, slot);
1744+	if (found_key.objectid != objectid)
1745+		return 1;
1746+
1747+	read_extent_buffer(&path->nodes[0], item,
1748+			   btrfs_item_ptr_offset(&path->nodes[0], slot),
1749+			   sizeof(*item));
1750+	return 0;
1751+}
1752+
1753+static int find_setup_root(struct btrfs_root *tree_root,
1754+			   u32 nodesize,
1755+			   u32 leafsize,
1756+			   u32 sectorsize,
1757+			   u32 stripesize,
1758+			   u64 objectid,
1759+			   struct btrfs_root *dest_root,
1760+			   u64 bytenr,
1761+			   u32 blocksize,
1762+			   u64 generation,
1763+			   lookup_pool_id lpid)
1764+{
1765+	int ret;
1766+	struct extent_buffer eb;
1767+
1768+	setup_root(dest_root,
1769+		   nodesize,
1770+		   leafsize,
1771+		   sectorsize,
1772+		   stripesize,
1773+		   objectid);
1774+	if (tree_root) {
1775+		/*
1776+		 * pick up the latest version
1777+		 * of the root we want to set up
1778+		 */
1779+		ret = btrfs_find_last_root(tree_root, objectid,
1780+					   &dest_root->root_item,
1781+					   lpid);
1782+		if (ret)
1783+			return ret;
1784+		bytenr = btrfs_root_bytenr(&dest_root->root_item);
1785+		blocksize = btrfs_level_size(dest_root,
1786+				       btrfs_root_level(&dest_root->root_item));
1787+		generation = btrfs_root_generation(&dest_root->root_item);
1788+	}
1789+	ret = read_tree_block(dest_root,
1790+			      &eb,
1791+			      bytenr,
1792+			      blocksize,
1793+			      generation,
1794+			      lpid);
1795+	if (!ret)
1796+		return 1;
1797+	copy_extent_buffer(&dest_root->node, &eb);
1798+	return 0;
1799+}
1800+
1801+static inline int btrfs_strncmp(const char *cs, const char *ct, int count)
1802+{
1803+	signed char __res = 0;
1804+
1805+	while (count) {
1806+		if ((__res = *cs - *ct++) != 0 || !*cs++)
1807+			break;
1808+		count--;
1809+	}
1810+	return __res;
1811+}
1812+
1813+/*
1814+ * the same as devread, but accepts
1815+ * device number, start and length.
1816+ */
1817+static int btrfs_devread(unsigned long drive, unsigned long part,
1818+			 unsigned long dev_len, int sector,
1819+			 int byte_offset, int byte_len, char *buf)
1820+{
1821+	if (sector < 0
1822+	    || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS))
1823+		>= dev_len)) {
1824+		errnum = ERR_OUTSIDE_PART;
1825+		return 0;
1826+	}
1827+	sector += byte_offset >> SECTOR_BITS;
1828+	byte_offset &= SECTOR_SIZE - 1;
1829+#if !defined(STAGE1_5)
1830+	if (disk_read_hook && debug)
1831+		printf ("<%d, %d, %d>", sector, byte_offset, byte_len);
1832+#endif /* !STAGE1_5 */
1833+	return rawread(drive, part + sector, byte_offset,
1834+		       byte_len, buf);
1835+}
1836+
1837+static int btrfs_check_super(void)
1838+{
1839+	struct btrfs_super_block *sb = BTRFS_SUPER;
1840+
1841+	if (sb->nodesize != BTRFS_DEFAULT_NODE_SIZE) {
1842+		btrfs_msg("Btrfs node size (%d) != %d unsupported\n",
1843+			  sb->nodesize, BTRFS_DEFAULT_NODE_SIZE);
1844+		goto error;
1845+	}
1846+	if (sb->leafsize != BTRFS_DEFAULT_LEAF_SIZE) {
1847+ 	        btrfs_msg("Btrfs leaf size (%d) != %d unsupported\n",
1848+			  sb->leafsize, BTRFS_DEFAULT_LEAF_SIZE);
1849+		goto error;
1850+	}
1851+
1852+ 	return 0;
1853+error:
1854+	return 1;
1855+}
1856+
1857+/* lift the super block */
1858+static int btrfs_uptodate_super_copy(struct btrfs_fs_info *fs)
1859+{
1860+	errnum = ERR_NONE;
1861+	btrfs_devread(BTRFS_FS_INFO->sb_dev.drive,
1862+		      BTRFS_FS_INFO->sb_dev.part,
1863+		      BTRFS_FS_INFO->sb_dev.length,
1864+		      btrfs_sb_offset(BTRFS_FS_INFO->sb_mirror) >> SECTOR_BITS,
1865+		      0,
1866+		      sizeof(struct btrfs_super_block),
1867+		      (char *)BTRFS_SUPER);
1868+	return btrfs_check_super();
1869+}
1870+
1871+/*
1872+ * Looking for a btrfs super block by magic, @fsid and @devid
1873+ * (the last two ones are optional). Update latest transid (if
1874+ * any). Return 0, if such super block was found. Otherwise,
1875+ * return 1.
1876+ *
1877+ * NOTE:
1878+ * After calling this function the sb_copy of global btrfs_fs_info
1879+ * can contain garbage, so the caller is responsible for this to be
1880+ * uptodate (see the function btrfs_uptodate_super_copy()).
1881+ */
1882+static int btrfs_find_super(struct btrfs_device *dev, char *fsid, u64 *devid)
1883+{
1884+	int i, ret;
1885+	int found = 0;
1886+
1887+	for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
1888+		ret = btrfs_devread(dev->drive,
1889+				    dev->part,
1890+				    dev->length,
1891+				    btrfs_sb_offset(i) >> SECTOR_BITS,
1892+				    0,
1893+				    sizeof(struct btrfs_super_block),
1894+				    (char *)BTRFS_SUPER);
1895+		if (!ret) {
1896+			if (errnum == ERR_OUTSIDE_PART) {
1897+				errnum = ERR_NONE;
1898+				break;
1899+			} else {
1900+				errnum = ERR_NONE;
1901+				continue;
1902+			}
1903+		}
1904+		if (btrfs_super_bytenr(BTRFS_SUPER) != btrfs_sb_offset(i) ||
1905+		    btrfs_strncmp((char *)(&BTRFS_SUPER->magic),
1906+				  BTRFS_MAGIC,
1907+				  sizeof(BTRFS_SUPER->magic)))
1908+			continue;
1909+		if (fsid &&
1910+		    btrfs_strncmp(fsid,
1911+				  (char *)BTRFS_SUPER->fsid,
1912+				  BTRFS_FSID_SIZE))
1913+			return 1;
1914+		if (devid &&
1915+		    *devid != btrfs_super_devid(BTRFS_SUPER))
1916+			return 1;
1917+		found = 1;
1918+		dev->devid = btrfs_super_devid(BTRFS_SUPER);
1919+
1920+		if (btrfs_super_generation(BTRFS_SUPER) >
1921+		    BTRFS_FS_INFO->sb_transid) {
1922+			BTRFS_FS_INFO->sb_transid =
1923+				btrfs_super_generation(BTRFS_SUPER);
1924+			BTRFS_FS_INFO->sb_mirror = i;
1925+			BTRFS_FS_INFO->sb_dev.devid =
1926+				btrfs_super_devid(BTRFS_SUPER);
1927+			BTRFS_FS_INFO->sb_dev.drive = dev->drive;
1928+			BTRFS_FS_INFO->sb_dev.part = dev->part;
1929+			BTRFS_FS_INFO->sb_dev.length = dev->length;
1930+		}
1931+	}
1932+	return !found;
1933+}
1934+
1935+/*
1936+ * "Discern" a btrfs device by fsid and
1937+ * optionaly by devid (if lookup is set).
1938+ * Populate persistent device cache (if
1939+ * there are free slots).
1940+ */
1941+static int btrfs_discerner(struct btrfs_device **dev, int lookup)
1942+{
1943+	if (btrfs_find_super(*dev,
1944+			     (char *)BTRFS_FS_INFO->fsid,
1945+			     (lookup ? &(*dev)->devid : 0)))
1946+		/* not found */
1947+		return 0;
1948+	if (*dev < BTRFS_VOLATILE_DEV_CACHE) {
1949+		/* populate persistent device cache */
1950+		memcpy(*dev + 1, *dev, sizeof(struct btrfs_device));
1951+		(*dev)++;
1952+	}
1953+	return 1;
1954+}
1955+
1956+/*
1957+ * Scan available grub devices and call discerner
1958+ * for them. Return a number of discerned devices
1959+ * The scanner was stolen from print_completions().
1960+ *
1961+ * Preconditions:
1962+ * The global structure btrfs_fs_info contains
1963+ * the latest valid version of btrfs superblock
1964+ * (the field @sb_copy)
1965+ */
1966+static u64 scan_grub_devices(struct btrfs_device *dev,
1967+			     int (*discerner)(struct btrfs_device **, int),
1968+			     int lookup)
1969+{
1970+	int i, j;
1971+	u64 count = 0;
1972+	struct geometry geom;
1973+
1974+	for (i = 0; i < 2; i++)
1975+		for (j = 0; j < 8; j++) {
1976+			unsigned long part = 0xFFFFFF;
1977+			int type, entry, gpt_count, gpt_size;
1978+			unsigned long offset, ext_offset, gpt_offset;
1979+
1980+			dev->drive = (i * 0x80) + j;
1981+			if (get_diskinfo(dev->drive, &geom))
1982+				continue;
1983+			while (1) {
1984+				int ret;
1985+				buf_drive = -1;
1986+				errnum = ERR_NONE;
1987+				ret = next_partition(dev->drive, 0xFFFFFF,
1988+						     &part, &type, &dev->part,
1989+						     &dev->length, &offset,
1990+						     &entry, &ext_offset,
1991+						     &gpt_offset, &gpt_count,
1992+						     &gpt_size,
1993+						     BTRFS_FS_INFO->mbr);
1994+				if (!ret)
1995+					break;
1996+				if (discerner(&dev, lookup)) {
1997+					count++;
1998+					if (lookup)
1999+						goto exit;
2000+				}
2001+			}
2002+		}
2003+#if 0
2004+	errnum = ERR_NONE;
2005+	if (cdrom_drive != GRUB_INVALID_DRIVE &&
2006+	    !get_diskinfo(cdrom_drive, &geom)) {
2007+		dev->drive = cdrom_drive;
2008+		dev->part = 0;
2009+		dev->length = geom.total_sectors;
2010+		if (discerner(&dev, lookup)) {
2011+			count++;
2012+			if (lookup)
2013+				goto exit;
2014+		}
2015+	}
2016+#ifdef SUPPORT_NETBOOT
2017+	errnum = ERR_NONE;
2018+	if (network_ready &&
2019+	    !get_diskinfo(NETWORK_DRIVE, &geom)) {
2020+		dev->drive = NETWORK_DRIVE;
2021+		dev->part = 0;
2022+		dev->length = geom.total_sectors;
2023+		if (discerner(&dev, lookup)) {
2024+			count++;
2025+			if (lookup)
2026+				goto exit;
2027+		}
2028+	}
2029+#endif /* SUPPORT_NETBOOT */
2030+#endif /* 0 */
2031+ exit:
2032+	return count;
2033+}
2034+
2035+#if 0
2036+static int btrfs_next_item(struct btrfs_root *root,
2037+			   struct btrfs_path *path);
2038+
2039+/*
2040+ * Scan the chunk tree for dev items
2041+ * and call a seeker for all of them.
2042+ * Preconditions: chunk root is installed
2043+ * to the global btrfs_fs_info.
2044+ */
2045+static int scan_dev_tree(struct btrfs_device* (*seeker)(u64))
2046+{
2047+	int ret;
2048+	u64 num_devices = 0;
2049+	struct btrfs_key key;
2050+	struct btrfs_key found_key;
2051+	struct btrfs_path *path;
2052+	struct btrfs_root *root;
2053+
2054+	root = BTRFS_CHUNK_ROOT;
2055+	path = btrfs_grab_path(FIRST_EXTERNAL_LOOKUP_POOL);
2056+	key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
2057+	key.type = 0;
2058+	key.offset = 0;
2059+
2060+	ret = aux_tree_lookup(root, &key, path);
2061+	if (ret == -1)
2062+		goto corrupted;
2063+	while (1) {
2064+		struct btrfs_device *result;
2065+		struct btrfs_dev_item *dev_item;
2066+
2067+		btrfs_item_key_to_cpu(&path->nodes[0],
2068+				      &found_key,
2069+				      path->slots[0]);
2070+		if (found_key.objectid != BTRFS_DEV_ITEMS_OBJECTID)
2071+			break;
2072+		dev_item = btrfs_item_ptr(&path->nodes[0],
2073+					  path->slots[0],
2074+					  struct btrfs_dev_item);
2075+		result = seeker(btrfs_device_id(&path->nodes[0], dev_item));
2076+		if (result == NULL) {
2077+			btrfs_msg("Btrfs device %llu is not available\n",
2078+				  btrfs_device_id(&path->nodes[0], dev_item));
2079+			goto missed_dev;
2080+		}
2081+		num_devices++;
2082+		ret = btrfs_next_item(root, path);
2083+		if (ret)
2084+			break;
2085+	}
2086+	if (num_devices == btrfs_super_num_devices(BTRFS_SUPER))
2087+		return 0;
2088+ corrupted:
2089+	errnum = ERR_FSYS_CORRUPT;
2090+	return 1;
2091+ missed_dev:
2092+	errnum = ERR_FSYS_MOUNT;
2093+	return 1;
2094+}
2095+#endif /* 0 */
2096+
2097+/*
2098+ * Find a grub btrfs device by devid.
2099+ * Preconditions: global btrfs_fs_info
2100+ * contains a copy of btrfs super block.
2101+ *
2102+ * Return pointer to the cached device on success.
2103+ * Otherwise return NULL.
2104+ */
2105+static struct btrfs_device *btrfs_lookup_device(u64 devid)
2106+{
2107+	int i, result;
2108+	struct btrfs_device *cdev;
2109+
2110+	for (i = 0; i < BTRFS_NUM_CACHED_DEVICES; i++) {
2111+		cdev = &BTRFS_DEVICES[i];
2112+		if (cdev->devid == devid)
2113+			goto found_in_cache;
2114+		if (cdev->devid == 0)
2115+			goto not_found_in_cache;
2116+	}
2117+not_found_in_cache:
2118+	cdev = BTRFS_VOLATILE_DEV_CACHE;
2119+	cdev->devid = devid;
2120+	result = scan_grub_devices(cdev,
2121+				   btrfs_discerner,
2122+				   1);
2123+	if (result == 0)
2124+		/*
2125+		 * At mount time we have figured out that
2126+		 * number of available devices is not less
2127+		 * then number of devices recorded in the
2128+		 * super block. Hence we treat this case as
2129+		 * file system corruption.
2130+		 */
2131+		goto corrupt;
2132+	result = btrfs_uptodate_super_copy(BTRFS_FS_INFO);
2133+	if (result)
2134+		goto corrupt;
2135+found_in_cache:
2136+	return cdev;
2137+corrupt:
2138+	errnum = ERR_FSYS_CORRUPT;
2139+	return NULL;
2140+}
2141+
2142+static int btrfs_find_device(struct btrfs_device *dev)
2143+{
2144+	struct btrfs_device *cdev;
2145+
2146+	if (btrfs_super_num_devices(BTRFS_SUPER) == 1) {
2147+		dev->drive = current_drive;
2148+		dev->part = part_start;
2149+		dev->length = part_length;
2150+		return 0;
2151+	}
2152+	cdev = btrfs_lookup_device(dev->devid);
2153+	if (cdev == NULL)
2154+		return 1;
2155+	dev->drive  = cdev->drive;
2156+	dev->part   = cdev->part;
2157+	dev->length = cdev->length;
2158+	return 0;
2159+}
2160+
2161+static inline void init_btrfs_volatile_dev_cache(void)
2162+{
2163+	BTRFS_VOLATILE_DEV_CACHE->devid = 0;
2164+	BTRFS_VOLATILE_DEV_CACHE->drive = current_drive;
2165+	BTRFS_VOLATILE_DEV_CACHE->part = part_start;
2166+	BTRFS_VOLATILE_DEV_CACHE->length = part_length;
2167+}
2168+
2169+/*
2170+ * check availability of btrfs devices
2171+ * and populate the persistent device cache
2172+ */
2173+static int btrfs_check_devices(void)
2174+{
2175+	u64 num_dev;
2176+
2177+	if (btrfs_super_num_devices(BTRFS_SUPER) == 1)
2178+		return 0;
2179+	num_dev = scan_grub_devices(BTRFS_DEVICES,
2180+				    btrfs_discerner, 0);
2181+	if (btrfs_uptodate_super_copy(BTRFS_FS_INFO))
2182+		return 1;
2183+	if (num_dev < btrfs_super_num_devices(BTRFS_SUPER)) {
2184+		btrfs_msg("Some (%llu) Btrfs devices is not available\n",
2185+			  btrfs_super_num_devices(BTRFS_SUPER) - num_dev);
2186+	        return 1;
2187+	}
2188+	return 0;
2189+}
2190+
2191+int btrfs_mount(void)
2192+{
2193+	int ret;
2194+
2195+	check_btrfs_cache_size();
2196+	init_btrfs_info();
2197+	init_btrfs_volatile_dev_cache();
2198+
2199+	ret = btrfs_find_super(BTRFS_VOLATILE_DEV_CACHE, NULL, NULL);
2200+	if (ret) {
2201+		btrfs_msg("Drive %lu, partition %lu: no Btrfs metadata\n",
2202+			  current_drive, part_start);
2203+		goto error;
2204+	}
2205+	ret = btrfs_uptodate_super_copy(BTRFS_FS_INFO);
2206+	if (ret)
2207+		goto error;
2208+	BTRFS_FS_INFO->sb_transid =
2209+		btrfs_super_generation(BTRFS_SUPER);
2210+	memcpy(BTRFS_FS_INFO->fsid,
2211+	       BTRFS_SUPER->fsid,
2212+	       BTRFS_FSID_SIZE);
2213+	ret = btrfs_check_devices();
2214+	if (ret)
2215+		goto error;
2216+	/* setup chunk root */
2217+	ret = find_setup_root(NULL,
2218+			      btrfs_super_nodesize(BTRFS_SUPER),
2219+			      btrfs_super_leafsize(BTRFS_SUPER),
2220+			      btrfs_super_sectorsize(BTRFS_SUPER),
2221+			      btrfs_super_stripesize(BTRFS_SUPER),
2222+			      BTRFS_CHUNK_TREE_OBJECTID,
2223+			      BTRFS_CHUNK_ROOT,
2224+			      btrfs_super_chunk_root(BTRFS_SUPER),
2225+			      btrfs_chunk_root_level_size(BTRFS_SUPER),
2226+			      btrfs_super_chunk_root_generation(BTRFS_SUPER),
2227+			      FIRST_EXTERNAL_LOOKUP_POOL);
2228+	if (ret)
2229+		return 0;
2230+	/* setup tree root */
2231+	ret = find_setup_root(NULL,
2232+			      btrfs_super_nodesize(BTRFS_SUPER),
2233+			      btrfs_super_leafsize(BTRFS_SUPER),
2234+			      btrfs_super_sectorsize(BTRFS_SUPER),
2235+			      btrfs_super_stripesize(BTRFS_SUPER),
2236+			      BTRFS_ROOT_TREE_OBJECTID,
2237+			      BTRFS_TREE_ROOT,
2238+			      btrfs_super_root(BTRFS_SUPER),
2239+			      btrfs_root_level_size(BTRFS_SUPER),
2240+			      btrfs_super_generation(BTRFS_SUPER),
2241+			      FIRST_EXTERNAL_LOOKUP_POOL);
2242+	if (ret)
2243+		return 0;
2244+	/* setup fs_root */
2245+	ret = find_setup_root(BTRFS_TREE_ROOT,
2246+			      btrfs_super_nodesize(BTRFS_SUPER),
2247+			      btrfs_super_leafsize(BTRFS_SUPER),
2248+			      btrfs_super_sectorsize(BTRFS_SUPER),
2249+			      btrfs_super_stripesize(BTRFS_SUPER),
2250+			      BTRFS_FS_TREE_OBJECTID,
2251+			      BTRFS_FS_ROOT,
2252+			      0,
2253+			      0,
2254+			      0,
2255+			      FIRST_EXTERNAL_LOOKUP_POOL);
2256+	return !ret;
2257+
2258+error:
2259+	errnum = ERR_FSYS_MOUNT;
2260+	return 0;
2261+}
2262+
2263+/*
2264+ * Check, whether @chunk is the map for a
2265+ * block with @logical block number.
2266+ * If yes, then fill the @map.
2267+ * Return 1 on affirmative result,
2268+ * otherwise return 0.
2269+ */
2270+int check_read_chunk(struct btrfs_key *key,
2271+			    struct extent_buffer *leaf,
2272+			    struct btrfs_chunk *chunk,
2273+			    struct map_lookup *map,
2274+			    u64 logical)
2275+{
2276+	int i, ret;
2277+	u64 chunk_start;
2278+	u64 chunk_size;
2279+	int num_stripes;
2280+
2281+	chunk_start = key->offset;
2282+	chunk_size = btrfs_chunk_length(leaf, chunk);
2283+
2284+	if (logical + 1 > chunk_start + chunk_size ||
2285+	    logical < chunk_start)
2286+		/* not a fit */
2287+		return 0;
2288+	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
2289+	map->ce.start = chunk_start;
2290+	map->ce.size = chunk_size;
2291+	map->num_stripes = num_stripes;
2292+	map->io_width = btrfs_chunk_io_width(leaf, chunk);
2293+	map->io_align = btrfs_chunk_io_align(leaf, chunk);
2294+	map->sector_size = btrfs_chunk_sector_size(leaf, chunk);
2295+	map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
2296+	map->type = btrfs_chunk_type(leaf, chunk);
2297+	map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
2298+
2299+	for (i = 0; i < num_stripes; i++) {
2300+		map->stripes[i].physical =
2301+			btrfs_stripe_offset_nr(leaf, chunk, i);
2302+		map->stripes[i].dev.devid =
2303+			btrfs_stripe_devid_nr(leaf, chunk, i);
2304+		ret = btrfs_find_device(&map->stripes[i].dev);
2305+		if (ret)
2306+			return 0;
2307+	}
2308+	return 1;
2309+}
2310+
2311+static void init_extent_buffer(struct extent_buffer *eb,
2312+			       struct btrfs_device *dev,
2313+			       u64 logical,
2314+			       u32 blocksize,
2315+			       u64 physical,
2316+			       lookup_pool_id lpid)
2317+{
2318+	if (dev)
2319+		memcpy(&eb->dev, dev, sizeof(*dev));
2320+	eb->start = logical;
2321+	eb->len = blocksize;
2322+	eb->dev_bytenr = physical;
2323+	eb->data = grab_lookup_cache(lpid);
2324+}
2325+
2326+/*
2327+ * Search for a map by logical offset in sys array.
2328+ * Return -1 on errors;
2329+ * Return 1 if the map is found,
2330+ * Return 0 if the map is not found.
2331+ */
2332+int sys_array_lookup(struct map_lookup *map, u64 logical)
2333+{
2334+	struct extent_buffer sb;
2335+	struct btrfs_disk_key *disk_key;
2336+	struct btrfs_chunk *chunk;
2337+	struct btrfs_key key;
2338+	u32 num_stripes;
2339+	u32 array_size;
2340+	u32 len = 0;
2341+	u8 *ptr;
2342+	unsigned long sb_ptr;
2343+	u32 cur;
2344+	int ret;
2345+	int i = 0;
2346+
2347+	sb.data = (char *)BTRFS_SUPER;
2348+	array_size = btrfs_super_sys_array_size(BTRFS_SUPER);
2349+
2350+	ptr = BTRFS_SUPER->sys_chunk_array;
2351+	sb_ptr = offsetof(struct btrfs_super_block, sys_chunk_array);
2352+	cur = 0;
2353+
2354+	while (cur < array_size) {
2355+		disk_key = (struct btrfs_disk_key *)ptr;
2356+		btrfs_disk_key_to_cpu(&key, disk_key);
2357+
2358+		len = sizeof(*disk_key);
2359+		ptr += len;
2360+		sb_ptr += len;
2361+		cur += len;
2362+
2363+		if (key.type == BTRFS_CHUNK_ITEM_KEY) {
2364+			chunk = (struct btrfs_chunk *)sb_ptr;
2365+			ret = check_read_chunk(&key, &sb,
2366+					       chunk, map, logical);
2367+			if (ret)
2368+				/* map is found */
2369+				return ret;
2370+			num_stripes = btrfs_chunk_num_stripes(&sb, chunk);
2371+			len = btrfs_chunk_item_size(num_stripes);
2372+		} else {
2373+			errnum = ERR_FSYS_CORRUPT;
2374+			return -1;
2375+		}
2376+		ptr += len;
2377+		sb_ptr += len;
2378+		cur += len;
2379+		i++;
2380+	}
2381+	return 0;
2382+}
2383+
2384+/*
2385+ * Search for a map by logical offset in the chunk tree.
2386+ * Return 1 if map is found, otherwise return 0.
2387+ */
2388+static int chunk_tree_lookup(struct map_lookup *map,
2389+			     u64 logical)
2390+{
2391+	int ret;
2392+	int slot;
2393+	struct extent_buffer *leaf;
2394+	struct btrfs_key key;
2395+	struct btrfs_key found_key;
2396+	struct btrfs_chunk *chunk;
2397+	struct btrfs_path *path;
2398+
2399+	path = btrfs_grab_path(INTERNAL_LOOKUP_POOL);
2400+
2401+	key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
2402+	key.offset = logical;
2403+	key.type = BTRFS_CHUNK_ITEM_KEY;
2404+
2405+	ret = aux_tree_lookup(BTRFS_CHUNK_ROOT, &key, path);
2406+	if (ret < 0)
2407+		return 0;
2408+	leaf = &path->nodes[0];
2409+	slot = path->slots[0];
2410+	if (ret == 1) {
2411+		WARN_ON(slot == 0);
2412+		slot -= 1;
2413+	}
2414+	btrfs_item_key_to_cpu(leaf, &found_key, slot);
2415+	if (found_key.type != BTRFS_CHUNK_ITEM_KEY)
2416+		return 0;
2417+	chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
2418+	return check_read_chunk(&found_key, leaf,
2419+				chunk, map, logical);
2420+}
2421+
2422+/*
2423+ * Btrfs logical/physical block mapper.
2424+ * Look for an appropriate map-extent and
2425+ * perform a translation. Return 1 on errors.
2426+ */
2427+static int btrfs_map_block(u64 logical, u64 *length,
2428+			   struct btrfs_multi_bio *multi,
2429+			   int mirror_num)
2430+{
2431+	struct map_lookup map;
2432+	u64 offset;
2433+	u64 stripe_offset;
2434+	u64 stripe_nr;
2435+	struct cache_extent *ce;
2436+	int stripe_index;
2437+	int i;
2438+	int ret;
2439+
2440+	memset(&map, 0, sizeof(map));
2441+	ret = sys_array_lookup(&map, logical);
2442+	if (ret == -1) {
2443+		errnum = ERR_FSYS_CORRUPT;
2444+		return 1;
2445+	}
2446+	if (ret == 0) {
2447+		ret = chunk_tree_lookup(&map, logical);
2448+		if (!ret) {
2449+			/* something should be found! */
2450+			errnum = ERR_FSYS_CORRUPT;
2451+			return 1;
2452+		}
2453+	}
2454+	/* do translation */
2455+	ce = &map.ce;
2456+
2457+	offset = logical - ce->start;
2458+	stripe_nr = offset / map.stripe_len;
2459+	stripe_offset = stripe_nr * map.stripe_len;
2460+	WARN_ON(offset < stripe_offset);
2461+
2462+	stripe_offset = offset - stripe_offset;
2463+
2464+	if (map.type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
2465+			 BTRFS_BLOCK_GROUP_RAID10 |
2466+			 BTRFS_BLOCK_GROUP_DUP)) {
2467+		*length = min_t(u64, ce->size - offset,
2468+			      map.stripe_len - stripe_offset);
2469+	} else {
2470+		*length = ce->size - offset;
2471+	}
2472+	multi->num_stripes = 1;
2473+	stripe_index = 0;
2474+	if (map.type & BTRFS_BLOCK_GROUP_RAID1) {
2475+		if (mirror_num)
2476+			stripe_index = mirror_num - 1;
2477+		else
2478+			stripe_index = stripe_nr % map.num_stripes;
2479+	} else if (map.type & BTRFS_BLOCK_GROUP_RAID10) {
2480+		int factor = map.num_stripes / map.sub_stripes;
2481+
2482+		stripe_index = stripe_nr % factor;
2483+		stripe_index *= map.sub_stripes;
2484+
2485+		if (mirror_num)
2486+			stripe_index += mirror_num - 1;
2487+		else
2488+			stripe_index = stripe_nr % map.sub_stripes;
2489+
2490+		stripe_nr = stripe_nr / factor;
2491+	} else if (map.type & BTRFS_BLOCK_GROUP_DUP) {
2492+		if (mirror_num)
2493+			stripe_index = mirror_num - 1;
2494+	} else {
2495+		stripe_index = stripe_nr % map.num_stripes;
2496+		stripe_nr = stripe_nr / map.num_stripes;
2497+	}
2498+	WARN_ON(stripe_index >= map.num_stripes);
2499+
2500+	for (i = 0; i < multi->num_stripes; i++) {
2501+		asm("" : "+r"(multi));
2502+		multi->stripes[i].physical =
2503+			map.stripes[stripe_index].physical + stripe_offset +
2504+			stripe_nr * map.stripe_len;
2505+		memcpy(&multi->stripes[i].dev,
2506+		       &map.stripes[stripe_index].dev,
2507+		       sizeof(struct btrfs_device));
2508+		stripe_index++;
2509+	}
2510+	return 0;
2511+}
2512+
2513+static u64 read_data_extent(u64 logical_start, u64 to_read, char *pos)
2514+{
2515+	int ret;
2516+	u64 length;
2517+	struct btrfs_multi_bio multi;
2518+
2519+	while (to_read) {
2520+		ret = btrfs_map_block(logical_start, &length, &multi, 0);
2521+		if (ret) {
2522+			errnum = ERR_FSYS_CORRUPT;
2523+			return ret;
2524+		}
2525+		if (length > to_read)
2526+			length = to_read;
2527+		disk_read_func = disk_read_hook;
2528+		ret = btrfs_devread(multi.stripes[0].dev.drive,
2529+				    multi.stripes[0].dev.part,
2530+				    multi.stripes[0].dev.length,
2531+				    multi.stripes[0].physical >> SECTOR_BITS,
2532+				    logical_start & ((u64)SECTOR_SIZE - 1),
2533+				    length,
2534+				    pos);
2535+		disk_read_func = NULL;
2536+		if (!ret)
2537+			return 1;
2538+		btrfs_msg("BTRFS data extent: read %llu bytes\n", length);
2539+		to_read -= length;
2540+		pos += length;
2541+		logical_start += length;
2542+	}
2543+	return 0;
2544+}
2545+
2546+static int read_extent_from_disk(struct extent_buffer *eb)
2547+{
2548+	WARN_ON(eb->dev_bytenr % SECTOR_BITS);
2549+	return btrfs_devread(eb->dev.drive,
2550+			     eb->dev.part,
2551+			     eb->dev.length,
2552+			     eb->dev_bytenr >> SECTOR_BITS,
2553+			     0,
2554+			     eb->len,
2555+			     eb->data);
2556+}
2557+
2558+static int verify_parent_transid(struct extent_buffer *eb, u64 parent_transid)
2559+{
2560+	return parent_transid && (btrfs_header_generation(eb) != parent_transid);
2561+}
2562+
2563+static int btrfs_num_copies(u64 logical, u64 len)
2564+{
2565+	return 1;
2566+}
2567+
2568+static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
2569+{
2570+	return 0;
2571+}
2572+
2573+static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
2574+		    int verify)
2575+{
2576+	return 0;
2577+}
2578+
2579+/*
2580+ * Read a block of logical number @bytenr
2581+ * from disk to buffer @eb.
2582+ * Return 1 on success.
2583+ */
2584+int read_tree_block(struct btrfs_root *root,
2585+		    struct extent_buffer *eb,
2586+		    u64 bytenr, /* logical */
2587+		    u32 blocksize,
2588+		    u64 parent_transid,
2589+		    lookup_pool_id lpid)
2590+{
2591+	int ret;
2592+	int dev_nr;
2593+	u64 length;
2594+	struct btrfs_multi_bio multi;
2595+	int mirror_num = 0;
2596+	int num_copies;
2597+
2598+	dev_nr = 0;
2599+	length = blocksize;
2600+	while (1) {
2601+		ret = btrfs_map_block(bytenr,
2602+				      &length, &multi, mirror_num);
2603+		if (ret) {
2604+			errnum = ERR_FSYS_CORRUPT;
2605+			return 0;
2606+		}
2607+		init_extent_buffer(eb,
2608+				   &multi.stripes[0].dev,
2609+				   bytenr,
2610+				   blocksize,
2611+				   multi.stripes[0].physical,
2612+				   lpid);
2613+
2614+		ret = read_extent_from_disk(eb);
2615+		if (ret &&
2616+		    check_tree_block(root, eb) == 0 &&
2617+		    csum_tree_block(root, eb, 1) == 0 &&
2618+		    verify_parent_transid(eb, parent_transid) == 0)
2619+			return 1;
2620+
2621+		num_copies = btrfs_num_copies(eb->start, eb->len);
2622+		if (num_copies == 1)
2623+			break;
2624+		mirror_num++;
2625+		if (mirror_num > num_copies)
2626+			break;
2627+	}
2628+	return 0;
2629+}
2630+
2631+/*
2632+ * Read a child pointed by @slot node pointer
2633+ * of @parent. Put the result to @parent.
2634+ * Return 1 on success.
2635+ */
2636+static int parent2child(struct btrfs_root *root,
2637+			struct extent_buffer *parent,
2638+			int slot,
2639+			lookup_pool_id lpid)
2640+{
2641+	int level;
2642+
2643+	WARN_ON(slot < 0);
2644+	WARN_ON(slot >= btrfs_header_nritems(parent));
2645+
2646+	level = btrfs_header_level(parent);
2647+	WARN_ON(level <= 0);
2648+
2649+	return read_tree_block(root,
2650+			       parent,
2651+			       btrfs_node_blockptr(parent, slot),
2652+			       btrfs_level_size(root, level - 1),
2653+			       btrfs_node_ptr_generation(parent, slot),
2654+			       lpid);
2655+}
2656+
2657+static int btrfs_comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
2658+{
2659+	struct btrfs_key k1;
2660+
2661+	btrfs_disk_key_to_cpu(&k1, disk);
2662+
2663+	if (k1.objectid > k2->objectid)
2664+		return 1;
2665+	if (k1.objectid < k2->objectid)
2666+		return -1;
2667+	if (k1.type > k2->type)
2668+		return 1;
2669+	if (k1.type < k2->type)
2670+		return -1;
2671+	if (k1.offset > k2->offset)
2672+		return 1;
2673+	if (k1.offset < k2->offset)
2674+		return -1;
2675+	return 0;
2676+}
2677+
2678+static int bin_search(struct extent_buffer *eb, unsigned long p,
2679+		      int item_size, struct btrfs_key *key,
2680+		      int max, int *slot)
2681+{
2682+	int low = 0;
2683+	int high = max;
2684+	int mid;
2685+	int ret;
2686+	unsigned long offset;
2687+	struct btrfs_disk_key *tmp;
2688+
2689+	while(low < high) {
2690+		mid = (low + high) / 2;
2691+		offset = p + mid * item_size;
2692+
2693+		tmp = (struct btrfs_disk_key *)(eb->data + offset);
2694+		ret = btrfs_comp_keys(tmp, key);
2695+
2696+		if (ret < 0)
2697+			low = mid + 1;
2698+		else if (ret > 0)
2699+			high = mid;
2700+		else {
2701+			*slot = mid;
2702+			return 0;
2703+		}
2704+	}
2705+	*slot = low;
2706+	return 1;
2707+}
2708+
2709+/* look for a key in a node */
2710+static int node_lookup(struct extent_buffer *eb,
2711+		       struct btrfs_key *key,
2712+		       int *slot)
2713+{
2714+	if (btrfs_header_level(eb) == 0) {
2715+		return bin_search(eb,
2716+				  offsetof(struct btrfs_leaf, items),
2717+				  sizeof(struct btrfs_item),
2718+				  key, btrfs_header_nritems(eb),
2719+				  slot);
2720+	} else {
2721+		return bin_search(eb,
2722+				  offsetof(struct btrfs_node, ptrs),
2723+				  sizeof(struct btrfs_key_ptr),
2724+				  key, btrfs_header_nritems(eb),
2725+				  slot);
2726+	}
2727+	return -1;
2728+}
2729+
2730+static inline int check_node(struct extent_buffer *buf, int slot)
2731+{
2732+	return 0;
2733+}
2734+
2735+/*
2736+ * Look for an item by key in read-only tree.
2737+ * Return 0, if key was found. Return -1 on io errors.
2738+ *
2739+ * Preconditions: btrfs_mount already executed.
2740+ * Postconditions: if returned value is non-negative,
2741+ * then path[0] represents the found position in the
2742+ * tree. All components of the @path from leaf to root
2743+ * are valid except their data buffers (only path[0]
2744+ * has valid attached data buffer).
2745+ */
2746+
2747+int aux_tree_lookup(struct btrfs_root *root,
2748+		    struct btrfs_key *key,
2749+		    struct btrfs_path *path)
2750+{
2751+	int ret;
2752+	int slot = 0;
2753+	int level;
2754+	struct extent_buffer node;
2755+	init_extent_buffer(&node,
2756+			   NULL,
2757+			   0,
2758+			   0,
2759+			   0,
2760+			   path->lpid);
2761+	copy_extent_buffer(&node, &root->node);
2762+	do {
2763+		level = btrfs_header_level(&node);
2764+		ret = check_node(&node, slot);
2765+		if (ret)
2766+			return -1;
2767+		move_extent_buffer(&path->nodes[level],
2768+				   &node);
2769+		ret = node_lookup(&node, key, &slot);
2770+		if (ret < 0)
2771+			return ret;
2772+		if (level) {
2773+		        /*
2774+			 * non-leaf,
2775+			 * jump to the next level
2776+			 */
2777+			if (ret && slot > 0)
2778+			        slot -= 1;
2779+			ret = parent2child(root, &node, slot, path->lpid);
2780+			if (ret == 0)
2781+				return -1;
2782+		}
2783+		path->slots[level] = slot;
2784+	} while (level);
2785+	return ret;
2786+}
2787+
2788+static int readup_buffer(struct extent_buffer *buf, lookup_pool_id lpid)
2789+{
2790+	buf->data = grab_lookup_cache(lpid);
2791+	return read_extent_from_disk(buf);
2792+}
2793+
2794+/*
2795+ * Find the next leaf in accordance with tree order;
2796+ * walk up the tree as far as required to find it.
2797+ * Returns 0 if something was found, or 1 if there
2798+ * are no greater leaves. Returns < 0 on io errors.
2799+ *
2800+ * Preconditions: all @path components from leaf to
2801+ * root have valid meta-data fields. path[0] has a
2802+ * valid attached data buffer with initial leaf.
2803+ * Postcondition: the same as above, but path[0] has
2804+ * an attached data buffer with the next leaf.
2805+ */
2806+static int btrfs_next_leaf(struct btrfs_root *root,
2807+			   struct btrfs_path *path)
2808+{
2809+	int res;
2810+	int slot;
2811+	int level = 1;
2812+	struct extent_buffer *buf;
2813+
2814+	while(level < BTRFS_MAX_LEVEL) {
2815+		buf = &path->nodes[level];
2816+		slot = path->slots[level] + 1;
2817+		/*
2818+		 * lift data on this level
2819+		 */
2820+		res = readup_buffer(buf, path->lpid);
2821+		if (!res)
2822+			break;
2823+		if (slot >= btrfs_header_nritems(buf)) {
2824+			/* alas, go to parent (if any) */
2825+			level++;
2826+			res = 1;
2827+			continue;
2828+		}
2829+		break;
2830+	}
2831+	if (!res)
2832+		return 1;
2833+	/*
2834+	 * At this level slot points to
2835+	 * the subtree we are interested in.
2836+	 */
2837+	path->slots[level] = slot;
2838+	while(level) {
2839+		struct extent_buffer tmp;
2840+		move_extent_buffer(&tmp, &path->nodes[level]);
2841+		res = parent2child(root, &tmp, slot, path->lpid);
2842+		if (res == 0)
2843+			return -1;
2844+		level --;
2845+		slot = 0;
2846+		move_extent_buffer(&path->nodes[level], &tmp);
2847+		path->slots[level] = slot;
2848+	}
2849+	return 0;
2850+}
2851+
2852+/* Preconditions: path is valid, data buffer
2853+ * is attached to leaf node.
2854+ * Postcondition: path is updated to point to
2855+ * the next position with respect to the tree
2856+ * order.
2857+ *
2858+ * Return -1 on io errors.
2859+ * Return 0, if next item was found.
2860+ * Return 1, if next item wasn't found (no more items).
2861+ */
2862+static int btrfs_next_item(struct btrfs_root *root,
2863+			   struct btrfs_path *path)
2864+{
2865+	WARN_ON(path->slots[0] >= btrfs_header_nritems(&path->nodes[0]));
2866+
2867+	path->slots[0] += 1;
2868+
2869+	if (path->slots[0] < btrfs_header_nritems(&path->nodes[0]))
2870+		return 0;
2871+	if (coord_is_root(root, path))
2872+		/* no more items */
2873+		return 1;
2874+	return btrfs_next_leaf(root, path);
2875+}
2876+
2877+/*
2878+ * check if we can reuse results of previous
2879+ * search for read operation
2880+ */
2881+static int path_is_valid(struct btrfs_path *path,
2882+			 struct btrfs_key *key, u64 offset)
2883+{
2884+	btrfs_item_key_to_cpu(&path->nodes[0],
2885+			      key,
2886+			      path->slots[0]);
2887+	if (BTRFS_FILE_INFO_KEY->objectid != key->objectid)
2888+		return 0;
2889+	if (btrfs_key_type(key) == BTRFS_INODE_ITEM_KEY)
2890+		return 1;
2891+	if (btrfs_key_type(key) != BTRFS_EXTENT_DATA_KEY)
2892+		return 0;
2893+	return BTRFS_FILE_INFO_KEY->offset <= offset;
2894+}
2895+
2896+/* ->read_func() */
2897+int btrfs_read(char *buf, int len)
2898+{
2899+	int ret;
2900+	struct btrfs_root *fs_root;
2901+	struct btrfs_path *path;
2902+	struct btrfs_key  path_key;
2903+	u64 ioff;
2904+	u64 bytes;
2905+	int to_read;
2906+	char *pos = buf;
2907+
2908+	fs_root = BTRFS_FS_ROOT;
2909+	path = btrfs_grab_path(FIRST_EXTERNAL_LOOKUP_POOL);
2910+
2911+	if (!path_is_valid(path, &path_key, filepos)) {
2912+		ret = aux_tree_lookup(fs_root, BTRFS_FILE_INFO_KEY, path);
2913+		if (ret < 0)
2914+			errnum = ERR_FSYS_CORRUPT;
2915+	}
2916+	while (!errnum) {
2917+		struct btrfs_item *item;
2918+		struct btrfs_file_extent_item *fi;
2919+		u64 from;
2920+
2921+		btrfs_item_key_to_cpu(&path->nodes[0],
2922+				      &path_key,
2923+				      path->slots[0]);
2924+		if (BTRFS_FILE_INFO_KEY->objectid != path_key.objectid)
2925+			break;
2926+		if (btrfs_key_type(&path_key) != BTRFS_EXTENT_DATA_KEY)
2927+			goto next;
2928+		/*
2929+		 * current position is extent item
2930+		 */
2931+		item = btrfs_item_nr(&path->nodes[0], path->slots[0]);
2932+		fi = btrfs_item_ptr(&path->nodes[0],
2933+				    path->slots[0],
2934+				    struct btrfs_file_extent_item);
2935+		if (btrfs_file_extent_compression(&path->nodes[0], fi)) {
2936+		       btrfs_msg("Btrfs transparent compression unsupported\n");
2937+		       errnum = ERR_BAD_FILETYPE;
2938+		       goto exit;
2939+		}
2940+		ioff = filepos - path_key.offset;
2941+
2942+		switch (btrfs_file_extent_type(&path->nodes[0], fi)) {
2943+		case BTRFS_FILE_EXTENT_INLINE:
2944+			bytes = btrfs_file_extent_inline_item_len(&path->
2945+								  nodes[0],
2946+								  item);
2947+			if (path_key.offset + bytes < filepos)
2948+				goto next;
2949+			to_read = bytes - ioff;
2950+			if (to_read > len)
2951+				to_read = len;
2952+			from = ioff + btrfs_file_extent_inline_start(fi);
2953+			if (disk_read_hook != NULL) {
2954+				disk_read_func = disk_read_hook;
2955+				ret = btrfs_devread(path->nodes[0].dev.drive,
2956+						    path->nodes[0].dev.part,
2957+						    path->nodes[0].dev.length,
2958+						    path->nodes[0].dev_bytenr >>
2959+						    SECTOR_BITS,
2960+						    from,
2961+						    to_read,
2962+						    pos);
2963+				disk_read_func = NULL;
2964+				if (ret)
2965+					goto exit;
2966+			} else
2967+				memcpy(pos,
2968+				       path->nodes[0].data + from,
2969+				       to_read);
2970+			btrfs_msg("BTRFS inline extent: read %d bytes pos %d\n",
2971+				  to_read, filepos);
2972+			break;
2973+		case BTRFS_FILE_EXTENT_REG:
2974+			bytes = btrfs_file_extent_num_bytes(&path->nodes[0],
2975+							    fi);
2976+			if (path_key.offset + bytes < filepos)
2977+				goto next;
2978+			to_read = bytes - ioff;
2979+			if (to_read > len)
2980+				to_read = len;
2981+			from = ioff +
2982+				btrfs_file_extent_disk_bytenr(&path->nodes[0],
2983+							      fi) +
2984+				btrfs_file_extent_offset(&path->nodes[0],
2985+							 fi);
2986+			ret = read_data_extent(from, to_read, pos);
2987+			if (ret)
2988+				goto exit;
2989+			break;
2990+		case BTRFS_FILE_EXTENT_PREALLOC:
2991+			btrfs_msg("Btrfs preallocated extents unsupported\n");
2992+			errnum = ERR_BAD_FILETYPE;
2993+			goto exit;
2994+		default:
2995+			errnum = ERR_FSYS_CORRUPT;
2996+			goto exit;
2997+		}
2998+		len -= to_read;
2999+		pos += to_read;
3000+		filepos += to_read;
3001+		if (len == 0)
3002+			break;
3003+		/* not everything was read */
3004+	next:
3005+		ret = btrfs_next_item(fs_root, path);
3006+		if (ret < 0) {
3007+			errnum = ERR_FSYS_CORRUPT;
3008+			break;
3009+		}
3010+		btrfs_update_file_info(path);
3011+		continue;
3012+	}
3013+exit:
3014+	return errnum ? 0 : pos - buf;
3015+}
3016+
3017+static int btrfs_follow_link(struct btrfs_root *root,
3018+			     struct btrfs_path *path,
3019+			     char **dirname, char *linkbuf,
3020+			     int *link_count,
3021+			     struct btrfs_inode_item *sd)
3022+{
3023+	int ret;
3024+	int len;
3025+	char *name = *dirname;
3026+
3027+	if (++(*link_count) > MAX_LINK_COUNT) {
3028+		errnum = ERR_SYMLINK_LOOP;
3029+		return 0;
3030+	}
3031+	/* calculate remaining name size */
3032+	filemax = btrfs_inode_size(&path->nodes[0], sd);
3033+	for (len = 0;
3034+	     name[len] && isspace(name[len]);
3035+	     len ++);
3036+
3037+	if (filemax + len > PATH_MAX - 1) {
3038+		errnum = ERR_FILELENGTH;
3039+		return 0;
3040+	}
3041+	grub_memmove(linkbuf + filemax, name, len + 1);
3042+	btrfs_update_file_info(path);
3043+	filepos = 0;
3044+	/* extract symlink content */
3045+	while (1) {
3046+		u64 oid = BTRFS_FILE_INFO_KEY->objectid;
3047+		ret = btrfs_next_item(root, path);
3048+		if (ret)
3049+			break;
3050+		btrfs_update_file_info(path);
3051+		if (oid != BTRFS_FILE_INFO_KEY->objectid)
3052+			break;
3053+		if (btrfs_key_type(BTRFS_FILE_INFO_KEY) ==
3054+		    BTRFS_EXTENT_DATA_KEY)
3055+			goto found;
3056+	}
3057+	/* no target was found */
3058+	errnum = ERR_FSYS_CORRUPT;
3059+	return 0;
3060+found:
3061+	/* fill the rest of linkbuf with the content */
3062+	ret = btrfs_read(linkbuf, filemax);
3063+	if (ret != filemax) {
3064+		errnum = ERR_FSYS_CORRUPT;
3065+		return 0;
3066+	}
3067+	return 1;
3068+}
3069+
3070+static int update_fs_root(struct btrfs_root *fs_root,
3071+			  struct btrfs_key *location)
3072+{
3073+	int ret;
3074+	struct btrfs_root *tree_root;
3075+
3076+	if (location->offset != (u64)-1)
3077+		return 0;
3078+	tree_root = &BTRFS_FS_INFO->tree_root;
3079+	ret = find_setup_root(tree_root,
3080+			      tree_root->nodesize,
3081+			      tree_root->leafsize,
3082+			      tree_root->sectorsize,
3083+			      tree_root->stripesize,
3084+			      location->objectid,
3085+			      fs_root,
3086+			      0,
3087+			      0,
3088+			      0,
3089+			      SECOND_EXTERNAL_LOOKUP_POOL);
3090+	if (ret)
3091+		return ret;
3092+	location->objectid = btrfs_root_dirid(&fs_root->root_item);
3093+	btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
3094+	location->offset = 0;
3095+	return 0;
3096+}
3097+
3098+#ifndef STAGE1_5
3099+static inline void update_possibilities(void)
3100+{
3101+	if (print_possibilities > 0)
3102+		print_possibilities =
3103+			-print_possibilities;
3104+}
3105+#endif
3106+
3107+/*
3108+ * Look for a directory item by name.
3109+ * Print possibilities, if needed.
3110+ * Postconditions: on success @sd_key points
3111+ * to the key contained in the directory entry.
3112+ */
3113+static int btrfs_de_index_by_name(struct btrfs_root *root,
3114+				  struct btrfs_path *path,
3115+				  char **dirname,
3116+				  struct btrfs_key *sd_key)
3117+{
3118+	char ch;
3119+	int ret;
3120+	char *rest;
3121+	struct btrfs_dir_item *di;
3122+#ifndef STAGE1_5
3123+	int do_possibilities = 0;
3124+#endif
3125+	for (; **dirname == '/'; (*dirname)++);
3126+	for (rest = *dirname;
3127+	     (ch = *rest) && !isspace(ch) && ch != '/';
3128+	     rest++);
3129+	*rest = 0; /* for substrung() */
3130+#ifndef STAGE1_5
3131+	if (print_possibilities && ch != '/')
3132+		do_possibilities = 1;
3133+#endif
3134+	/* scan a directory */
3135+	while (1) {
3136+		u32 total;
3137+		u32 cur = 0;
3138+		u32 len;
3139+		struct btrfs_key di_key;
3140+		struct btrfs_disk_key location;
3141+		struct btrfs_item *item;
3142+
3143+		/* extract next dir entry */
3144+		ret = btrfs_next_item(root, path);
3145+		if (ret)
3146+			break;
3147+		item = btrfs_item_nr(&path->nodes[0],
3148+				     path->slots[0]);
3149+		btrfs_item_key_to_cpu(&path->nodes[0],
3150+				      &di_key,
3151+				      path->slots[0]);
3152+		if (di_key.objectid != sd_key->objectid)
3153+			/* no more entries */
3154+			break;
3155+		di = btrfs_item_ptr(&path->nodes[0],
3156+				    path->slots[0],
3157+				    struct btrfs_dir_item);
3158+		/*
3159+		 * working around special cases:
3160+		 * btrfs doesn't maintain directory entries
3161+		 * which contain names "." and ".."
3162+		 */
3163+		if (!substring(".", *dirname)) {
3164+#ifndef STAGE1_5
3165+			if (do_possibilities) {
3166+				update_possibilities();
3167+				return 1;
3168+			}
3169+#endif
3170+			goto found;
3171+		}
3172+		if (!substring("..", *dirname)) {
3173+			if (di_key.type != BTRFS_INODE_REF_KEY)
3174+				continue;
3175+			sd_key->objectid = di_key.offset;
3176+			btrfs_set_key_type(sd_key, BTRFS_INODE_ITEM_KEY);
3177+			sd_key->offset = 0;
3178+#ifndef STAGE1_5
3179+			if (do_possibilities) {
3180+				update_possibilities();
3181+				return 1;
3182+			}
3183+#endif
3184+			goto found;
3185+		}
3186+		if (di_key.type != BTRFS_DIR_ITEM_KEY)
3187+			continue;
3188+		total = btrfs_item_size(&path->nodes[0], item);
3189+		/* scan a directory item */
3190+		while (cur < total) {
3191+			char tmp;
3192+			int result;
3193+			char *filename;
3194+			char *end_of_name;
3195+			int name_len;
3196+			int data_len;
3197+
3198+			btrfs_dir_item_key(&path->nodes[0], di, &location);
3199+
3200+			name_len = btrfs_dir_name_len(&path->nodes[0], di);
3201+			data_len = btrfs_dir_data_len(&path->nodes[0], di);
3202+
3203+			WARN_ON(name_len > BTRFS_NAME_LEN);
3204+
3205+			filename = (char *)(path->nodes[0].data +
3206+					    (unsigned long)(di + 1));
3207+			end_of_name = filename + name_len;
3208+			/*
3209+			 * working around not null-terminated
3210+			 * directory names in btrfs: just
3211+			 * a short-term overwrite of the
3212+			 * cache with the following rollback
3213+			 * of the change.
3214+			 */
3215+			tmp = *end_of_name;
3216+			*end_of_name = 0;
3217+			result = substring(*dirname, filename);
3218+			*end_of_name = tmp;
3219+#ifndef STAGE1_5
3220+			if (do_possibilities) {
3221+				if (result <= 0) {
3222+					update_possibilities();
3223+					*end_of_name = 0;
3224+					print_a_completion(filename);
3225+					*end_of_name = tmp;
3226+				}
3227+			}
3228+			else
3229+#endif
3230+				if (result == 0) {
3231+				      btrfs_dir_item_key_to_cpu(&path->nodes[0],
3232+								di, sd_key);
3233+				      goto found;
3234+				}
3235+			len = sizeof(*di) + name_len + data_len;
3236+			di = (struct btrfs_dir_item *)((char *)di + len);
3237+			cur += len;
3238+		}
3239+	}
3240+#ifndef STAGE1_5
3241+	if (print_possibilities < 0)
3242+		return 1;
3243+#endif
3244+	errnum = ERR_FILE_NOT_FOUND;
3245+	*rest = ch;
3246+	return 0;
3247+ found:
3248+	*rest = ch;
3249+	*dirname = rest;
3250+	return 1;
3251+}
3252+
3253+/*
3254+ * ->dir_func().
3255+ * Postcondition: on a non-zero return BTRFS_FS_INFO
3256+ * contains the latest fs_root of file's subvolume.
3257+ * BTRFS_FS_INFO points to a subvolume of a file we
3258+ * were trying to look up.
3259+ * BTRFS_FILE_INFO contains info of the file we were
3260+ * trying to look up.
3261+ */
3262+
3263+int btrfs_dir(char *dirname)
3264+{
3265+	int ret;
3266+	int mode;
3267+	u64 size;
3268+	int linkcount = 0;
3269+	char linkbuf[PATH_MAX];
3270+
3271+	struct btrfs_path *path;
3272+	struct btrfs_root *root;
3273+
3274+	struct btrfs_key sd_key;
3275+	struct btrfs_inode_item *sd;
3276+	struct btrfs_key parent_sd_key;
3277+
3278+	root = BTRFS_FS_ROOT;
3279+	path = btrfs_grab_path(FIRST_EXTERNAL_LOOKUP_POOL);
3280+
3281+	btrfs_set_root_dir_key(&sd_key);
3282+	while (1) {
3283+		struct extent_buffer *leaf;
3284+		ret = aux_tree_lookup(root, &sd_key, path);
3285+		if (ret)
3286+			return 0;
3287+		leaf = &path->nodes[0];
3288+		sd = btrfs_item_ptr(leaf,
3289+				    path->slots[0],
3290+				    struct btrfs_inode_item);
3291+		mode = btrfs_inode_mode(leaf, sd);
3292+		size = btrfs_inode_size(leaf, sd);
3293+		switch (btrfs_get_file_type(mode)) {
3294+		case BTRFS_SYMLINK_FILE:
3295+			ret = btrfs_follow_link(root,
3296+						path,
3297+						&dirname,
3298+						linkbuf,
3299+						&linkcount,
3300+						sd);
3301+			if (!ret)
3302+				return 0;
3303+			dirname = linkbuf;
3304+			if (*dirname == '/')
3305+				/* absolute name */
3306+				btrfs_set_root_dir_key(&sd_key);
3307+			else
3308+				memcpy(&sd_key, &parent_sd_key,
3309+				       sizeof(sd_key));
3310+			continue;
3311+		case BTRFS_REGULAR_FILE:
3312+			/*
3313+			 * normally we want to exit here
3314+			 */
3315+			if (*dirname && !isspace (*dirname)) {
3316+				errnum = ERR_BAD_FILETYPE;
3317+				return 0;
3318+			}
3319+			filepos = 0;
3320+			filemax = btrfs_inode_size(leaf, sd);
3321+			btrfs_update_file_info(path);
3322+			return 1;
3323+		case BTRFS_DIRECTORY_FILE:
3324+			memcpy(&parent_sd_key, &sd_key, sizeof(sd_key));
3325+			ret = btrfs_de_index_by_name(root,
3326+						     path,
3327+						     &dirname,
3328+						     &sd_key);
3329+			if (!ret)
3330+				return 0;
3331+#ifndef STAGE1_5
3332+			if (print_possibilities < 0)
3333+				return 1;
3334+#endif
3335+			/*
3336+			 * update fs_tree:
3337+			 * subvolume stuff goes here
3338+			 */
3339+			ret = update_fs_root(root, &sd_key);
3340+			if (ret)
3341+				return 0;
3342+			continue;
3343+		case BTRFS_UNKNOWN_FILE:
3344+		default:
3345+			btrfs_msg("Btrfs: bad file type\n");
3346+			errnum = ERR_BAD_FILETYPE;
3347+			return 0;
3348+		}
3349+	}
3350+}
3351+
3352+int btrfs_embed(int *start_sector, int needed_sectors)
3353+{
3354+	int ret;
3355+	init_btrfs_info();
3356+	init_btrfs_volatile_dev_cache();
3357+
3358+	ret = btrfs_find_super(BTRFS_VOLATILE_DEV_CACHE, NULL, NULL);
3359+	if (ret)
3360+		return 0;
3361+	ret = btrfs_uptodate_super_copy(BTRFS_FS_INFO);
3362+	if (ret)
3363+		return 0;
3364+	*start_sector = 1; /* reserve first sector for stage1 */
3365+	return needed_sectors <=
3366+		((BTRFS_SUPER_INFO_OFFSET >> SECTOR_BITS) - 1);
3367+}
3368+#endif /* FSYS_BTRFS */
3369+
3370+/*
3371+  Local variables:
3372+  c-indentation-style: "K&R"
3373+  mode-name: "LC"
3374+  c-basic-offset: 8
3375+  tab-width: 8
3376+  fill-column: 80
3377+  scroll-step: 1
3378+  End:
3379+*/
3380diff -up grub-upstream.wip/stage2/Makefile.am.btrfs grub-upstream.wip/stage2/Makefile.am
3381--- grub-upstream.wip/stage2/Makefile.am.btrfs	2012-03-20 05:06:49.000000000 +0000
3382+++ grub-upstream.wip/stage2/Makefile.am	2012-03-20 05:07:09.000000000 +0000
3383@@ -17,13 +17,13 @@ INCLUDES = -I$(top_srcdir)/stage1
3384 noinst_LIBRARIES = libgrub.a
3385 libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \
3386 	disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
3387-	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
3388+	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_btrfs.c fsys_ufs2.c \
3389 	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
3390 	terminfo.c tparm.c graphics.c
3391 libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
3392 	-DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
3393 	-DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
3394-	-DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
3395+	-DFSYS_BTRFS=1 -DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
3396 	-DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
3397
3398 # Stage 2 and Stage 1.5's.
3399@@ -34,24 +34,26 @@ EXTRA_PROGRAMS = nbloader.exec pxeloader
3400 if DISKLESS_SUPPORT
3401 pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
3402 	ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
3403-	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
3404-	nbgrub pxegrub
3405+	reiserfs_stage1_5 btrfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 \
3406+	xfs_stage1_5 nbgrub pxegrub
3407 noinst_DATA = pre_stage2 start start_eltorito nbloader pxeloader diskless
3408 noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
3409 	e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
3410 	iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
3411-	reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
3412-	xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
3413+	reiserfs_stage1_5.exec btrfs_stage1_5.exec ufs2_stage1_5.exec \
3414+	vstafs_stage1_5.exec xfs_stage1_5.exec nbloader.exec \
3415+	pxeloader.exec diskless.exec
3416 else
3417 pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
3418 	ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
3419-	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
3420+	reiserfs_stage1_5 btrfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 \
3421+	xfs_stage1_5
3422 noinst_DATA = pre_stage2 start start_eltorito
3423 noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
3424 	e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
3425 	iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
3426-	reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
3427-	xfs_stage1_5.exec
3428+	reiserfs_stage1_5.exec btrfs_stage1_5.exec ufs2_stage1_5.exec \
3429+	vstafs_stage1_5.exec xfs_stage1_5.exec
3430 endif
3431 MOSTLYCLEANFILES = $(noinst_PROGRAMS)
3432
3433@@ -95,15 +97,17 @@ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DN
3434 pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \
3435 	cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
3436 	fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
3437-	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
3438-	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
3439-	graphics.c
3440+	fsys_reiserfs.c fsys_btrfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c \
3441+	gunzip.c hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c \
3442+	tparm.c graphics.c
3443 pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
3444 pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
3445 pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
3446
3447 if NETBOOT_SUPPORT
3448-pre_stage2_exec_LDADD = ../netboot/libdrivers.a
3449+pre_stage2_exec_LDADD = ../netboot/libdrivers.a -lgcc
3450+else
3451+pre_stage2_exec_LDADD = -lgcc
3452 endif
3453
3454 if DISKLESS_SUPPORT
3455@@ -197,6 +201,16 @@ reiserfs_stage1_5_exec_CCASFLAGS = $(STA
3456 	-DNO_BLOCK_FILES=1
3457 reiserfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
3458
3459+# For btrfs_stage1_5 target.
3460+btrfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
3461+       disk_io.c stage1_5.c fsys_btrfs.c bios.c
3462+btrfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_BTRFS=1 \
3463+       -DNO_BLOCK_FILES=1
3464+btrfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_BTRFS=1 \
3465+       -DNO_BLOCK_FILES=1
3466+btrfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
3467+btrfs_stage1_5_exec_LDADD = -lgcc
3468+
3469 # For vstafs_stage1_5 target.
3470 vstafs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
3471 	disk_io.c stage1_5.c fsys_vstafs.c bios.c
3472@@ -240,7 +254,7 @@ diskless_exec_CFLAGS = $(STAGE2_COMPILE)
3473 diskless_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
3474 	-DSUPPORT_DISKLESS=1
3475 diskless_exec_LDFLAGS = $(PRE_STAGE2_LINK)
3476-diskless_exec_LDADD = ../netboot/libdrivers.a
3477+diskless_exec_LDADD = ../netboot/libdrivers.a -lgcc
3478
3479 diskless_size.h: diskless
3480 	-rm -f $@
3481diff -up grub-upstream.wip/stage2/shared.h.btrfs grub-upstream.wip/stage2/shared.h
3482--- grub-upstream.wip/stage2/shared.h.btrfs	2012-03-20 05:06:49.000000000 +0000
3483+++ grub-upstream.wip/stage2/shared.h	2012-03-20 05:07:09.000000000 +0000
3484@@ -207,11 +207,12 @@ extern char *grub_scratch_mem;
3485 #define STAGE2_ID_FAT_STAGE1_5		3
3486 #define STAGE2_ID_MINIX_STAGE1_5	4
3487 #define STAGE2_ID_REISERFS_STAGE1_5	5
3488-#define STAGE2_ID_VSTAFS_STAGE1_5	6
3489-#define STAGE2_ID_JFS_STAGE1_5		7
3490-#define STAGE2_ID_XFS_STAGE1_5		8
3491-#define STAGE2_ID_ISO9660_STAGE1_5	9
3492-#define STAGE2_ID_UFS2_STAGE1_5		10
3493+#define STAGE2_ID_BTRFS_STAGE1_5	6
3494+#define STAGE2_ID_VSTAFS_STAGE1_5	7
3495+#define STAGE2_ID_JFS_STAGE1_5		8
3496+#define STAGE2_ID_XFS_STAGE1_5		9
3497+#define STAGE2_ID_ISO9660_STAGE1_5	10
3498+#define STAGE2_ID_UFS2_STAGE1_5		11
3499
3500 #ifndef STAGE1_5
3501 # define STAGE2_ID	STAGE2_ID_STAGE2
3502@@ -226,6 +227,8 @@ extern char *grub_scratch_mem;
3503 #  define STAGE2_ID	STAGE2_ID_MINIX_STAGE1_5
3504 # elif defined(FSYS_REISERFS)
3505 #  define STAGE2_ID	STAGE2_ID_REISERFS_STAGE1_5
3506+# elif defined(FSYS_BTRFS)
3507+#  define STAGE2_ID	STAGE2_ID_BTRFS_STAGE1_5
3508 # elif defined(FSYS_VSTAFS)
3509 #  define STAGE2_ID	STAGE2_ID_VSTAFS_STAGE1_5
3510 # elif defined(FSYS_JFS)
3511