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