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