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