From 94dab57ef9e594abb70f4a1180ba7c501dc96d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 26 Jan 2020 18:45:15 +0100 Subject: [PATCH] [FREELDR] Rework BTRFS filesystem to not be tied to a fixed global volume. CORE-16646 --- boot/freeldr/freeldr/include/fs/btrfs.h | 3 + boot/freeldr/freeldr/lib/fs/btrfs.c | 255 ++++++++++++++---------- 2 files changed, 153 insertions(+), 105 deletions(-) diff --git a/boot/freeldr/freeldr/include/fs/btrfs.h b/boot/freeldr/freeldr/include/fs/btrfs.h index b8fddc773c3..1cea4f36500 100644 --- a/boot/freeldr/freeldr/include/fs/btrfs.h +++ b/boot/freeldr/freeldr/include/fs/btrfs.h @@ -409,10 +409,13 @@ struct btrfs_chunk_map { u32 cur_length; }; +typedef struct _BTRFS_INFO *PBTRFS_INFO; + typedef struct { u64 inr; u64 position; struct btrfs_inode_item inode; + PBTRFS_INFO Volume; } btrfs_file_info, * pbtrfs_file_info; const DEVVTBL* BtrFsMount(ULONG DeviceId); diff --git a/boot/freeldr/freeldr/lib/fs/btrfs.c b/boot/freeldr/freeldr/lib/fs/btrfs.c index f808cd27b08..6b6a0c87d83 100644 --- a/boot/freeldr/freeldr/lib/fs/btrfs.c +++ b/boot/freeldr/freeldr/lib/fs/btrfs.c @@ -22,15 +22,16 @@ DBG_DEFAULT_CHANNEL(FILESYSTEM); #define INVALID_ADDRESS _UI64_MAX #define READ_ERROR _UI64_MAX -struct BTRFS_INFO { +typedef struct _BTRFS_INFO +{ ULONG DeviceId; struct btrfs_super_block SuperBlock; struct btrfs_chunk_map ChunkMap; struct btrfs_root_item FsRoot; struct btrfs_root_item ExtentRoot; -}; +} BTRFS_INFO; -struct BTRFS_INFO *BtrFsInfo; +PBTRFS_INFO BtrFsVolumes[MAX_FDS]; /* compare function used for bin_search */ typedef int (*cmp_func)(const void *ptr1, const void *ptr2); @@ -83,9 +84,8 @@ static int btrfs_comp_chunk_map(struct btrfs_chunk_map_item *m1, } /* insert a new chunk mapping item */ -static void insert_chunk_item(struct btrfs_chunk_map_item *item) +static void insert_chunk_item(struct btrfs_chunk_map *chunk_map, struct btrfs_chunk_map_item *item) { - struct btrfs_chunk_map *chunk_map = &BtrFsInfo->ChunkMap; int ret; int slot; int i; @@ -119,7 +119,9 @@ static void insert_chunk_item(struct btrfs_chunk_map_item *item) chunk_map->cur_length++; } -static inline void insert_map(const struct btrfs_disk_key *key, struct btrfs_chunk *chunk) +static inline void insert_map(struct btrfs_chunk_map *chunk_map, + const struct btrfs_disk_key *key, + struct btrfs_chunk *chunk) { struct btrfs_stripe *stripe = &chunk->stripe; struct btrfs_stripe *stripe_end = stripe + chunk->num_stripes; @@ -132,13 +134,12 @@ static inline void insert_map(const struct btrfs_disk_key *key, struct btrfs_chu TRACE("stripe: %p\n", stripe); item.devid = stripe->devid; item.physical = stripe->offset; - TRACE("inserting chunk log: %llx len: %llx devid: %llx phys: %llx\n", item.logical, item.length, item.devid, - item.physical); - insert_chunk_item(&item); + TRACE("inserting chunk log: %llx len: %llx devid: %llx phys: %llx\n", + item.logical, item.length, item.devid, item.physical); + insert_chunk_item(chunk_map, &item); } #if 0 - struct btrfs_chunk_map *chunk_map = &BtrFsInfo->ChunkMap; struct btrfs_chunk_map_item *itm; int i; @@ -152,8 +153,7 @@ static inline void insert_map(const struct btrfs_disk_key *key, struct btrfs_chu itm->logical + itm->length, itm->physical, itm->physical + itm->length, - itm->devid - ); + itm->devid); } #endif } @@ -164,10 +164,10 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes) sizeof(struct btrfs_stripe) * (num_stripes - 1); } -static inline void init_path(struct btrfs_path *path) +static inline void init_path(const struct btrfs_super_block *sb, struct btrfs_path *path) { memset(path, 0, sizeof(*path)); - path->tree_buf = FrLdrTempAlloc(BtrFsInfo->SuperBlock.nodesize, TAG_BTRFS_NODE); + path->tree_buf = FrLdrTempAlloc(sb->nodesize, TAG_BTRFS_NODE); } static inline void free_path(struct btrfs_path *path) @@ -187,7 +187,7 @@ static inline UCHAR *path_current_data(struct btrfs_path *path) static inline const struct btrfs_disk_key *path_current_disk_key(struct btrfs_path *path) { - return (const struct btrfs_disk_key *) &path_current_item(path)->key; + return &path_current_item(path)->key; } @@ -228,9 +228,8 @@ static int btrfs_comp_keys_type(const struct btrfs_disk_key *k1, * from sys_chunk_array or chunk_tree, we can convert a logical address to * a physical address we can not support multi device case yet */ -static u64 logical_physical(u64 logical) +static u64 logical_physical(struct btrfs_chunk_map *chunk_map, u64 logical) { - struct btrfs_chunk_map *chunk_map = &BtrFsInfo->ChunkMap; struct btrfs_chunk_map_item item; int slot, ret; @@ -251,7 +250,7 @@ static u64 logical_physical(u64 logical) return chunk_map->map[slot - 1].physical + logical - chunk_map->map[slot - 1].logical; } -static BOOLEAN disk_read(u64 physical, void *dest, u32 count) +static BOOLEAN disk_read(ULONG DeviceId, u64 physical, void *dest, u32 count) { LARGE_INTEGER Position; ULONG Count; @@ -261,14 +260,14 @@ static BOOLEAN disk_read(u64 physical, void *dest, u32 count) return FALSE; Position.QuadPart = physical; - Status = ArcSeek(BtrFsInfo->DeviceId, &Position, SeekAbsolute); + Status = ArcSeek(DeviceId, &Position, SeekAbsolute); if (Status != ESUCCESS) { ERR("ArcSeek returned status %lu\n", Status); return FALSE; } - Status = ArcRead(BtrFsInfo->DeviceId, dest, count, &Count); + Status = ArcRead(DeviceId, dest, count, &Count); if (Status != ESUCCESS || Count != count) { ERR("ArcRead returned status %lu\n", Status); @@ -278,13 +277,14 @@ static BOOLEAN disk_read(u64 physical, void *dest, u32 count) return TRUE; } -static BOOLEAN _BtrFsSearchTree(u64 loffset, u8 level, struct btrfs_disk_key *key, - struct btrfs_path *path) +static BOOLEAN +_BtrFsSearchTree(PBTRFS_INFO BtrFsInfo, u64 loffset, u8 level, + struct btrfs_disk_key *key, struct btrfs_path *path) { - struct btrfs_super_block *sb = &BtrFsInfo->SuperBlock; union tree_buf *tree_buf = path->tree_buf; int slot, ret, lvl; u64 physical, logical = loffset; + TRACE("BtrFsSearchTree called: offset: 0x%llx, level: %u (%llu %u %llu)\n", loffset, level, key->objectid, key->type, key->offset); @@ -296,18 +296,20 @@ static BOOLEAN _BtrFsSearchTree(u64 loffset, u8 level, struct btrfs_disk_key *ke for (lvl = level; lvl >= 0; lvl--) { - physical = logical_physical(logical); + physical = logical_physical(&BtrFsInfo->ChunkMap, logical); - if (!disk_read(physical, &tree_buf->header, sb->nodesize)) + if (!disk_read(BtrFsInfo->DeviceId, physical, &tree_buf->header, + BtrFsInfo->SuperBlock.nodesize)) { - ERR("Error when reading tree node, loffset: 0x%llx, poffset: 0x%llx, level: %u\n", logical, physical, lvl); + ERR("Error when reading tree node, loffset: 0x%llx, poffset: 0x%llx, level: %u\n", + logical, physical, lvl); return FALSE; } - if (tree_buf->header.level != lvl) { - ERR("Error when searching in tree: expected lvl=%u but got %u\n", lvl, tree_buf->header.level); + ERR("Error when searching in tree: expected lvl=%u but got %u\n", + lvl, tree_buf->header.level); return FALSE; } @@ -353,13 +355,15 @@ static BOOLEAN _BtrFsSearchTree(u64 loffset, u8 level, struct btrfs_disk_key *ke } static inline BOOLEAN -BtrFsSearchTree(const struct btrfs_root_item *root, struct btrfs_disk_key *key, struct btrfs_path *path) +BtrFsSearchTree(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, + struct btrfs_disk_key *key, struct btrfs_path *path) { - return _BtrFsSearchTree(root->bytenr, root->level, key, path); + return _BtrFsSearchTree(BtrFsInfo, root->bytenr, root->level, key, path); } static inline BOOLEAN -BtrFsSearchTreeType(const struct btrfs_root_item *root, u64 objectid, u8 type, struct btrfs_path *path) +BtrFsSearchTreeType(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, + u64 objectid, u8 type, struct btrfs_path *path) { struct btrfs_disk_key key; @@ -367,7 +371,8 @@ BtrFsSearchTreeType(const struct btrfs_root_item *root, u64 objectid, u8 type, s key.type = type; key.offset = 0; - _BtrFsSearchTree(root->bytenr, root->level, &key, path); + if (!_BtrFsSearchTree(BtrFsInfo, root->bytenr, root->level, &key, path)) + return FALSE; if (path_current_disk_key(path)->objectid && !btrfs_comp_keys_type(&key, path_current_disk_key(path))) return TRUE; @@ -376,8 +381,8 @@ BtrFsSearchTreeType(const struct btrfs_root_item *root, u64 objectid, u8 type, s } /* return 0 if slot found */ -static int next_slot(struct btrfs_disk_key *key, - struct btrfs_path *path) +static int next_slot(PBTRFS_INFO BtrFsInfo, + struct btrfs_disk_key *key, struct btrfs_path *path) { int slot, level = 1; @@ -395,13 +400,13 @@ static int next_slot(struct btrfs_disk_key *key, if (slot >= path->itemsnr[level]) { level++; - continue;; + continue; } path->slots[level] = slot; path->slots[level - 1] = 0; /* reset low level slots info */ path->itemsnr[level - 1] = 0; path->offsets[level - 1] = 0; - _BtrFsSearchTree(path->offsets[level], level, key, path); + _BtrFsSearchTree(BtrFsInfo, path->offsets[level], level, key, path); break; } if (level == BTRFS_MAX_LEVEL) @@ -432,9 +437,9 @@ static int prev_slot(struct btrfs_disk_key *key, /* * read chunk_array in super block */ -static void btrfs_read_sys_chunk_array() +static void btrfs_read_sys_chunk_array(PBTRFS_INFO BtrFsInfo) { - struct btrfs_super_block *sb = &BtrFsInfo->SuperBlock; + const struct btrfs_super_block *sb = &BtrFsInfo->SuperBlock; struct btrfs_disk_key *key; struct btrfs_chunk *chunk; u16 cur; @@ -445,7 +450,8 @@ static void btrfs_read_sys_chunk_array() while (cur < sb->sys_chunk_array_size) { key = (struct btrfs_disk_key *) (sb->sys_chunk_array + cur); - TRACE("chunk key objectid: %llx, offset: %llx, type: %u\n", key->objectid, key->offset, key->type); + TRACE("chunk key objectid: %llx, offset: %llx, type: %u\n", + key->objectid, key->offset, key->type); cur += sizeof(*key); chunk = (struct btrfs_chunk *) (sb->sys_chunk_array + cur); TRACE("chunk length: %llx\n", chunk->length); @@ -460,17 +466,16 @@ static void btrfs_read_sys_chunk_array() cur += btrfs_chunk_item_size(chunk->num_stripes); TRACE("read_sys_chunk_array() cur=%d\n", cur); - insert_map((const struct btrfs_disk_key *) key, chunk); + insert_map(&BtrFsInfo->ChunkMap, key, chunk); } } - /* * read chunk items from chunk_tree and insert them to chunk map * */ -static void btrfs_read_chunk_tree() +static void btrfs_read_chunk_tree(PBTRFS_INFO BtrFsInfo) { - struct btrfs_super_block *sb = &BtrFsInfo->SuperBlock; + const struct btrfs_super_block *sb = &BtrFsInfo->SuperBlock; struct btrfs_disk_key ignore_key; struct btrfs_disk_key search_key; struct btrfs_chunk *chunk; @@ -488,8 +493,8 @@ static void btrfs_read_chunk_tree() search_key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; search_key.type = BTRFS_CHUNK_ITEM_KEY; search_key.offset = 0; - init_path(&path); - _BtrFsSearchTree(sb->chunk_root, sb->chunk_root_level, &search_key, &path); + init_path(sb, &path); + _BtrFsSearchTree(BtrFsInfo, sb->chunk_root, sb->chunk_root_level, &search_key, &path); do { /* skip information about underlying block @@ -501,8 +506,8 @@ static void btrfs_read_chunk_tree() break; chunk = (struct btrfs_chunk *) (path_current_data(&path)); - insert_map(path_current_disk_key(&path), chunk); - } while (!next_slot(&search_key, &path)); + insert_map(&BtrFsInfo->ChunkMap, path_current_disk_key(&path), chunk); + } while (!next_slot(BtrFsInfo, &search_key, &path)); free_path(&path); } } @@ -536,7 +541,8 @@ static BOOLEAN verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total } -static struct btrfs_dir_item *BtrFsMatchDirItemName(struct btrfs_path *path, const char *name, int name_len) +static struct btrfs_dir_item * +BtrFsMatchDirItemName(struct btrfs_path *path, const char *name, int name_len) { struct btrfs_dir_item *item = (struct btrfs_dir_item *) path_current_data(path); u32 cur = 0, this_len; @@ -559,8 +565,11 @@ static struct btrfs_dir_item *BtrFsMatchDirItemName(struct btrfs_path *path, con return NULL; } -static BOOLEAN BtrFsLookupDirItem(const struct btrfs_root_item *root, u64 dir, const char *name, int name_len, - struct btrfs_dir_item *item) +static BOOLEAN +BtrFsLookupDirItem(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, u64 dir, + const char *name, int name_len, + struct btrfs_dir_item *item) { struct btrfs_path path; struct btrfs_disk_key key; @@ -569,9 +578,9 @@ static BOOLEAN BtrFsLookupDirItem(const struct btrfs_root_item *root, u64 dir, c key.objectid = dir; key.type = BTRFS_DIR_ITEM_KEY; key.offset = btrfs_crc32c(name, name_len); - init_path(&path); + init_path(&BtrFsInfo->SuperBlock, &path); - if (!BtrFsSearchTree(root, &key, &path)) + if (!BtrFsSearchTree(BtrFsInfo, root, &key, &path)) { free_path(&path); return FALSE; @@ -585,8 +594,11 @@ static BOOLEAN BtrFsLookupDirItem(const struct btrfs_root_item *root, u64 dir, c return res != NULL; } -static BOOLEAN BtrFsLookupDirItemI(const struct btrfs_root_item *root, u64 dir_haystack, const char *name, int name_len, - struct btrfs_dir_item *ret_item) +static BOOLEAN +BtrFsLookupDirItemI(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, u64 dir_haystack, + const char *name, int name_len, + struct btrfs_dir_item *ret_item) { struct btrfs_path path; struct btrfs_disk_key key; @@ -597,9 +609,9 @@ static BOOLEAN BtrFsLookupDirItemI(const struct btrfs_root_item *root, u64 dir_h key.objectid = dir_haystack; key.type = BTRFS_DIR_INDEX_KEY; key.offset = 0; - init_path(&path); + init_path(&BtrFsInfo->SuperBlock, &path); - BtrFsSearchTree(root, &key, &path); + BtrFsSearchTree(BtrFsInfo, root, &key, &path); if (btrfs_comp_keys_type(&key, path_current_disk_key(&path))) goto cleanup; @@ -608,8 +620,8 @@ static BOOLEAN BtrFsLookupDirItemI(const struct btrfs_root_item *root, u64 dir_h { item = (struct btrfs_dir_item *) path_current_data(&path); // TRACE("slot: %ld, KEY (%llu %u %llu) %.*s\n", - // path.slots[0], path.item.key.objectid, path.item.key.type, - // path.item.key.offset, item->name_len, (char *)item + sizeof(*item)); + // path.slots[0], path.item.key.objectid, path.item.key.type, + // path.item.key.offset, item->name_len, (char *)item + sizeof(*item)); if (verify_dir_item(item, 0, sizeof(*item) + item->name_len)) continue; @@ -626,7 +638,7 @@ static BOOLEAN BtrFsLookupDirItemI(const struct btrfs_root_item *root, u64 dir_h goto cleanup; } - } while (!next_slot(&key, &path)); + } while (!next_slot(BtrFsInfo, &key, &path)); cleanup: free_path(&path); @@ -638,13 +650,13 @@ cleanup: //////////////////////////////////////// static u64 btrfs_read_extent_inline(struct btrfs_path *path, - struct btrfs_file_extent_item *extent, u64 offset, - u64 size, char *out) + struct btrfs_file_extent_item *extent, + u64 offset, u64 size, char *out) { u32 dlen; const char *cbuf; const int data_off = offsetof( - struct btrfs_file_extent_item, disk_bytenr); + struct btrfs_file_extent_item, disk_bytenr); cbuf = (const char *) extent + data_off; dlen = extent->ram_bytes; @@ -671,7 +683,9 @@ static u64 btrfs_read_extent_inline(struct btrfs_path *path, return READ_ERROR; } -static u64 btrfs_read_extent_reg(struct btrfs_path *path, struct btrfs_file_extent_item *extent, +static u64 btrfs_read_extent_reg(PBTRFS_INFO BtrFsInfo, + struct btrfs_path *path, + struct btrfs_file_extent_item *extent, u64 offset, u64 size, char *out) { u64 physical, dlen; @@ -694,7 +708,7 @@ static u64 btrfs_read_extent_reg(struct btrfs_path *path, struct btrfs_file_exte return size; } - physical = logical_physical(extent->disk_bytenr); + physical = logical_physical(&BtrFsInfo->ChunkMap, extent->disk_bytenr); if (physical == INVALID_ADDRESS) { ERR("Unable to convert logical address to physical: %llu\n", extent->disk_bytenr); @@ -712,7 +726,9 @@ static u64 btrfs_read_extent_reg(struct btrfs_path *path, struct btrfs_file_exte temp_out = FrLdrTempAlloc(SECTOR_SIZE, TAG_BTRFS_FILE); - if (!disk_read(ALIGN_DOWN_BY(physical, SECTOR_SIZE), temp_out, SECTOR_SIZE)) + if (!disk_read(BtrFsInfo->DeviceId, + ALIGN_DOWN_BY(physical, SECTOR_SIZE), + temp_out, SECTOR_SIZE)) { FrLdrTempFree(temp_out, TAG_BTRFS_FILE); return READ_ERROR; @@ -730,11 +746,16 @@ static u64 btrfs_read_extent_reg(struct btrfs_path *path, struct btrfs_file_exte memcpy(out, temp_out + shift, SECTOR_SIZE - shift); FrLdrTempFree(temp_out, TAG_BTRFS_FILE); - if (!disk_read(physical + SECTOR_SIZE - shift, out + SECTOR_SIZE - shift, size - SECTOR_SIZE + shift)) + if (!disk_read(BtrFsInfo->DeviceId, + physical + SECTOR_SIZE - shift, + out + SECTOR_SIZE - shift, + size - SECTOR_SIZE + shift)) + { return READ_ERROR; + } } else { - if (!disk_read(physical, out, size)) + if (!disk_read(BtrFsInfo->DeviceId, physical, out, size)) return READ_ERROR; } @@ -745,7 +766,9 @@ static u64 btrfs_read_extent_reg(struct btrfs_path *path, struct btrfs_file_exte return READ_ERROR; } -static u64 btrfs_file_read(const struct btrfs_root_item *root, u64 inr, u64 offset, u64 size, char *buf) +static u64 btrfs_file_read(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, + u64 inr, u64 offset, u64 size, char *buf) { struct btrfs_path path; struct btrfs_disk_key key; @@ -759,9 +782,9 @@ static u64 btrfs_file_read(const struct btrfs_root_item *root, u64 inr, u64 offs key.objectid = inr; key.type = BTRFS_EXTENT_DATA_KEY; key.offset = offset; - init_path(&path); + init_path(&BtrFsInfo->SuperBlock, &path); - find_res = BtrFsSearchTree(root, &key, &path); + find_res = BtrFsSearchTree(BtrFsInfo, root, &key, &path); /* if we found greater key, switch to the previous one */ if (!find_res && btrfs_comp_keys(&key, path_current_disk_key(&path)) < 0) @@ -796,7 +819,7 @@ static u64 btrfs_file_read(const struct btrfs_root_item *root, u64 inr, u64 offs } else { - rd = btrfs_read_extent_reg(&path, extent, offset_in_extent, size, buf); + rd = btrfs_read_extent_reg(BtrFsInfo, &path, extent, offset_in_extent, size, buf); } if (rd == READ_ERROR) @@ -813,7 +836,7 @@ static u64 btrfs_file_read(const struct btrfs_root_item *root, u64 inr, u64 offs if (!size) break; - } while (!(res = next_slot(&key, &path))); + } while (!(res = next_slot(BtrFsInfo, &key, &path))); if (res) { @@ -832,15 +855,16 @@ out: //////////////////////////////////////// -static u64 btrfs_lookup_inode_ref(const struct btrfs_root_item *root, u64 inr, +static u64 btrfs_lookup_inode_ref(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, u64 inr, struct btrfs_inode_ref *refp, char *name) { struct btrfs_path path; struct btrfs_inode_ref *ref; u64 ret = INVALID_INODE; - init_path(&path); + init_path(&BtrFsInfo->SuperBlock, &path); - if (BtrFsSearchTreeType(root, inr, BTRFS_INODE_REF_KEY, &path)) + if (BtrFsSearchTreeType(BtrFsInfo, root, inr, BTRFS_INODE_REF_KEY, &path)) { ref = (struct btrfs_inode_ref *) path_current_data(&path); @@ -853,7 +877,8 @@ static u64 btrfs_lookup_inode_ref(const struct btrfs_root_item *root, u64 inr, return ret; } -static int btrfs_lookup_inode(const struct btrfs_root_item *root, +static int btrfs_lookup_inode(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, struct btrfs_disk_key *location, struct btrfs_inode_item *item, struct btrfs_root_item *new_root) @@ -870,10 +895,10 @@ static int btrfs_lookup_inode(const struct btrfs_root_item *root, // location->type = BTRFS_INODE_ITEM_KEY; // location->offset = 0; // } - init_path(&path); + init_path(&BtrFsInfo->SuperBlock, &path); TRACE("Searching inode (%llu %u %llu)\n", location->objectid, location->type, location->offset); - if (BtrFsSearchTree(&tmp_root, location, &path)) + if (BtrFsSearchTree(BtrFsInfo, &tmp_root, location, &path)) { if (item) *item = *((struct btrfs_inode_item *) path_current_data(&path)); @@ -888,16 +913,18 @@ static int btrfs_lookup_inode(const struct btrfs_root_item *root, return res; } -static BOOLEAN btrfs_readlink(const struct btrfs_root_item *root, u64 inr, char **target) +static BOOLEAN btrfs_readlink(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, + u64 inr, char **target) { struct btrfs_path path; struct btrfs_file_extent_item *extent; char *data_ptr; BOOLEAN res = FALSE; - init_path(&path); + init_path(&BtrFsInfo->SuperBlock, &path); - if (!BtrFsSearchTreeType(root, inr, BTRFS_EXTENT_DATA_KEY, &path)) + if (!BtrFsSearchTreeType(BtrFsInfo, root, inr, BTRFS_EXTENT_DATA_KEY, &path)) goto out; extent = (struct btrfs_file_extent_item *) path_current_data(&path); @@ -924,7 +951,7 @@ static BOOLEAN btrfs_readlink(const struct btrfs_root_item *root, u64 inr, char } data_ptr = (char *) extent + offsetof( - struct btrfs_file_extent_item, disk_bytenr); + struct btrfs_file_extent_item, disk_bytenr); *target = FrLdrTempAlloc(extent->ram_bytes + 1, TAG_BTRFS_LINK); if (!*target) @@ -945,7 +972,8 @@ out: /* inr must be a directory (for regular files with multiple hard links this function returns only one of the parents of the file) */ -static u64 get_parent_inode(const struct btrfs_root_item *root, u64 inr, +static u64 get_parent_inode(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, u64 inr, struct btrfs_inode_item *inode_item) { struct btrfs_disk_key key; @@ -974,14 +1002,14 @@ static u64 get_parent_inode(const struct btrfs_root_item *root, u64 inr, key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - if (btrfs_lookup_inode(root, &key, inode_item, NULL)) + if (btrfs_lookup_inode(BtrFsInfo, root, &key, inode_item, NULL)) return INVALID_INODE; } return inr; } - res = btrfs_lookup_inode_ref(root, inr, NULL, NULL); + res = btrfs_lookup_inode_ref(BtrFsInfo, root, inr, NULL, NULL); if (res == INVALID_INODE) return INVALID_INODE; @@ -991,7 +1019,7 @@ static u64 get_parent_inode(const struct btrfs_root_item *root, u64 inr, key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - if (btrfs_lookup_inode(root, &key, inode_item, NULL)) + if (btrfs_lookup_inode(BtrFsInfo, root, &key, inode_item, NULL)) return INVALID_INODE; } @@ -1021,7 +1049,8 @@ static inline const char *skip_current_directories(const char *cur) return cur; } -static u64 btrfs_lookup_path(const struct btrfs_root_item *root, u64 inr, const char *path, +static u64 btrfs_lookup_path(PBTRFS_INFO BtrFsInfo, + const struct btrfs_root_item *root, u64 inr, const char *path, u8 *type_p, struct btrfs_inode_item *inode_item_p, int symlink_limit) { struct btrfs_dir_item item; @@ -1055,7 +1084,7 @@ static u64 btrfs_lookup_path(const struct btrfs_root_item *root, u64 inr, const if (len == 2 && cur[0] == '.' && cur[1] == '.') { cur += 2; - inr = get_parent_inode(root, inr, &inode_item); + inr = get_parent_inode(BtrFsInfo, root, inr, &inode_item); if (inr == INVALID_INODE) return INVALID_INODE; @@ -1066,16 +1095,16 @@ static u64 btrfs_lookup_path(const struct btrfs_root_item *root, u64 inr, const if (!*cur) break; - if (!BtrFsLookupDirItem(root, inr, cur, len, &item)) + if (!BtrFsLookupDirItem(BtrFsInfo, root, inr, cur, len, &item)) { TRACE("Try to find case-insensitive, path=%s inr=%llu s=%.*s\n", path, inr, len, cur); - if (!BtrFsLookupDirItemI(root, inr, cur, len, &item)) + if (!BtrFsLookupDirItemI(BtrFsInfo, root, inr, cur, len, &item)) return INVALID_INODE; } type = item.type; have_inode = 1; - if (btrfs_lookup_inode(root, &item.location, &inode_item, NULL)) + if (btrfs_lookup_inode(BtrFsInfo, root, &item.location, &inode_item, NULL)) return INVALID_INODE; if (type == BTRFS_FT_SYMLINK && symlink_limit >= 0) @@ -1087,10 +1116,10 @@ static u64 btrfs_lookup_path(const struct btrfs_root_item *root, u64 inr, const } /* btrfs_readlink allocates link_target by itself */ - if (!btrfs_readlink(root, item.location.objectid, &link_target)) + if (!btrfs_readlink(BtrFsInfo, root, item.location.objectid, &link_target)) return INVALID_INODE; - inr = btrfs_lookup_path(root, inr, link_target, &type, &inode_item, symlink_limit - 1); + inr = btrfs_lookup_path(BtrFsInfo, root, inr, link_target, &type, &inode_item, symlink_limit - 1); FrLdrTempFree(link_target, TAG_BTRFS_LINK); @@ -1119,7 +1148,7 @@ static u64 btrfs_lookup_path(const struct btrfs_root_item *root, u64 inr, const key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - if (btrfs_lookup_inode(root, &key, &inode_item, NULL)) + if (btrfs_lookup_inode(BtrFsInfo, root, &key, &inode_item, NULL)) return INVALID_INODE; } @@ -1155,6 +1184,8 @@ ARC_STATUS BtrFsGetFileInformation(ULONG FileId, FILEINFORMATION *Information) ARC_STATUS BtrFsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId) { + PBTRFS_INFO BtrFsInfo; + ULONG DeviceId; u64 inr; u8 type; @@ -1163,10 +1194,17 @@ ARC_STATUS BtrFsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId) TRACE("BtrFsOpen %s\n", Path); + /* Check parameters */ if (OpenMode != OpenReadOnly) return EACCES; - inr = btrfs_lookup_path(&BtrFsInfo->FsRoot, BtrFsInfo->FsRoot.root_dirid, Path, &type, &temp_file_info.inode, 40); + /* Get underlying device */ + DeviceId = FsGetDeviceId(*FileId); + BtrFsInfo = BtrFsVolumes[DeviceId]; + + inr = btrfs_lookup_path(BtrFsInfo, &BtrFsInfo->FsRoot, + BtrFsInfo->FsRoot.root_dirid, + Path, &type, &temp_file_info.inode, 40); if (inr == INVALID_INODE) { @@ -1189,7 +1227,8 @@ ARC_STATUS BtrFsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId) if (!phandle) return ENOMEM; - memcpy(phandle, &temp_file_info, sizeof(btrfs_file_info)); + RtlCopyMemory(phandle, &temp_file_info, sizeof(btrfs_file_info)); + phandle->Volume = BtrFsInfo; FsSetDeviceSpecific(*FileId, phandle); return ESUCCESS; @@ -1208,7 +1247,8 @@ ARC_STATUS BtrFsRead(ULONG FileId, VOID *Buffer, ULONG Size, ULONG *BytesRead) if (Size > phandle->inode.size) Size = phandle->inode.size; - rd = btrfs_file_read(&BtrFsInfo->FsRoot, phandle->inr, phandle->position, Size, Buffer); + rd = btrfs_file_read(phandle->Volume, &phandle->Volume->FsRoot, + phandle->inr, phandle->position, Size, Buffer); if (rd == READ_ERROR) { TRACE("An error occured while reading file %lu\n", FileId); @@ -1256,18 +1296,20 @@ const DEVVTBL BtrFsFuncTable = const DEVVTBL *BtrFsMount(ULONG DeviceId) { + PBTRFS_INFO BtrFsInfo; struct btrfs_path path; struct btrfs_root_item fs_root_item; TRACE("Enter BtrFsMount(%lu)\n", DeviceId); - BtrFsInfo = FrLdrTempAlloc(sizeof(struct BTRFS_INFO), TAG_BTRFS_INFO); + BtrFsInfo = FrLdrTempAlloc(sizeof(BTRFS_INFO), TAG_BTRFS_INFO); if (!BtrFsInfo) return NULL; - RtlZeroMemory(BtrFsInfo, sizeof(struct BTRFS_INFO)); + RtlZeroMemory(BtrFsInfo, sizeof(BTRFS_INFO)); /* Read the SuperBlock */ - if (!disk_read(BTRFS_SUPER_INFO_OFFSET, &BtrFsInfo->SuperBlock, sizeof(struct btrfs_super_block))) + if (!disk_read(DeviceId, BTRFS_SUPER_INFO_OFFSET, + &BtrFsInfo->SuperBlock, sizeof(BtrFsInfo->SuperBlock))) { FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO); return NULL; @@ -1285,18 +1327,18 @@ const DEVVTBL *BtrFsMount(ULONG DeviceId) btrfs_init_crc32c(); - btrfs_read_sys_chunk_array(); - btrfs_read_chunk_tree(); + btrfs_read_sys_chunk_array(BtrFsInfo); + btrfs_read_chunk_tree(BtrFsInfo); /* setup roots */ fs_root_item.bytenr = BtrFsInfo->SuperBlock.root; fs_root_item.level = BtrFsInfo->SuperBlock.root_level; - init_path(&path); - if (!BtrFsSearchTreeType(&fs_root_item, BTRFS_FS_TREE_OBJECTID, BTRFS_ROOT_ITEM_KEY, &path)) + init_path(&BtrFsInfo->SuperBlock, &path); + if (!BtrFsSearchTreeType(BtrFsInfo, &fs_root_item, BTRFS_FS_TREE_OBJECTID, BTRFS_ROOT_ITEM_KEY, &path)) { - FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO); free_path(&path); + FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO); return NULL; } @@ -1304,6 +1346,9 @@ const DEVVTBL *BtrFsMount(ULONG DeviceId) free_path(&path); + /* Remember BTRFS volume information */ + BtrFsVolumes[DeviceId] = BtrFsInfo; + TRACE("BtrFsMount(%lu) success\n", DeviceId); return &BtrFsFuncTable; }