Loading fs/btrfs/ctree.h +15 −2 Original line number Diff line number Diff line Loading @@ -122,12 +122,12 @@ struct btrfs_super_block { u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* this block number */ __le64 magic; __le32 blocksize; __le64 generation; __le64 root; __le64 total_blocks; __le64 blocks_used; __le64 root_dir_objectid; __le32 blocksize; } __attribute__ ((__packed__)); /* Loading Loading @@ -226,10 +226,12 @@ struct btrfs_root_item { struct btrfs_inode_item inode; __le64 root_dirid; __le64 blocknr; __le32 flags; __le64 block_limit; __le64 blocks_used; __le32 flags; __le32 refs; struct btrfs_disk_key drop_progress; u8 drop_level; } __attribute__ ((__packed__)); #define BTRFS_FILE_EXTENT_REG 0 Loading Loading @@ -800,6 +802,16 @@ static inline void btrfs_set_root_refs(struct btrfs_root_item *item, u32 val) item->refs = cpu_to_le32(val); } static inline u32 btrfs_root_flags(struct btrfs_root_item *item) { return le32_to_cpu(item->flags); } static inline void btrfs_set_root_flags(struct btrfs_root_item *item, u32 val) { item->flags = cpu_to_le32(val); } static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s) { return le64_to_cpu(s->blocknr); Loading Loading @@ -1076,6 +1088,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *item); int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key); int btrfs_find_dead_roots(struct btrfs_root *root); /* dir-item.c */ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, int name_len, u64 dir, Loading fs/btrfs/disk-io.c +30 −14 Original line number Diff line number Diff line Loading @@ -326,7 +326,7 @@ static int find_and_setup_root(int blocksize, return 0; } struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, struct btrfs_key *location) { struct btrfs_root *root; Loading @@ -336,11 +336,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, u64 highest_inode; int ret = 0; root = radix_tree_lookup(&fs_info->fs_roots_radix, (unsigned long)location->objectid); if (root) return root; root = kmalloc(sizeof(*root), GFP_NOFS); root = kzalloc(sizeof(*root), GFP_NOFS); if (!root) return ERR_PTR(-ENOMEM); if (location->offset == (u64)-1) { Loading Loading @@ -383,6 +379,28 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, BUG_ON(!root->node); insert: root->ref_cows = 1; ret = btrfs_find_highest_inode(root, &highest_inode); if (ret == 0) { root->highest_inode = highest_inode; root->last_inode_alloc = highest_inode; } return root; } struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_key *location) { struct btrfs_root *root; int ret; root = radix_tree_lookup(&fs_info->fs_roots_radix, (unsigned long)location->objectid); if (root) return root; root = btrfs_read_fs_root_no_radix(fs_info, location); if (IS_ERR(root)) return root; ret = radix_tree_insert(&fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, root); Loading @@ -391,11 +409,6 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, kfree(root); return ERR_PTR(ret); } ret = btrfs_find_highest_inode(root, &highest_inode); if (ret == 0) { root->highest_inode = highest_inode; root->last_inode_alloc = highest_inode; } return root; } Loading Loading @@ -489,6 +502,9 @@ struct btrfs_root *open_ctree(struct super_block *sb) btrfs_read_block_groups(extent_root); fs_info->generation = btrfs_super_generation(disk_super) + 1; ret = btrfs_find_dead_roots(tree_root); if (ret) goto fail_tree_root; mutex_unlock(&fs_info->fs_mutex); return tree_root; Loading Loading @@ -538,7 +554,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root return 0; } static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) { radix_tree_delete(&fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid); Loading @@ -565,7 +581,7 @@ static int del_fs_roots(struct btrfs_fs_info *fs_info) if (!ret) break; for (i = 0; i < ret; i++) free_fs_root(fs_info, gang[i]); btrfs_free_fs_root(fs_info, gang[i]); } return 0; } Loading fs/btrfs/disk-io.h +3 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,8 @@ int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, char *result); struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_key *location); struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, struct btrfs_key *location); u64 bh_blocknr(struct buffer_head *bh); int btrfs_insert_dev_radix(struct btrfs_root *root, struct block_device *bdev, Loading @@ -75,4 +77,5 @@ int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, u64 logical); int btrfs_releasepage(struct page *page, gfp_t flags); void btrfs_btree_balance_dirty(struct btrfs_root *root); int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); #endif fs/btrfs/inode.c +2 −0 Original line number Diff line number Diff line Loading @@ -2028,6 +2028,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) btrfs_set_root_blocknr(&root_item, bh_blocknr(subvol)); btrfs_set_root_refs(&root_item, 1); memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); root_item.drop_level = 0; brelse(subvol); subvol = NULL; Loading fs/btrfs/root-tree.c +66 −9 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/module.h> #include "ctree.h" #include "transaction.h" #include "disk-io.h" #include "print-tree.h" Loading @@ -32,7 +33,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, search_key.objectid = objectid; search_key.flags = (u32)-1; search_key.offset = (u32)-1; search_key.offset = (u64)-1; path = btrfs_alloc_path(); BUG_ON(!path); Loading @@ -50,6 +51,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item), sizeof(*item)); btrfs_disk_key_to_cpu(key, &l->items[slot].key); printk("find last finds key %Lu %u %Lu slot %d search for obj %Lu\n", key->objectid, key->flags, key->offset, slot, objectid); ret = 0; out: btrfs_release_path(root, path); Loading Loading @@ -93,6 +95,67 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root return ret; } int btrfs_find_dead_roots(struct btrfs_root *root) { struct btrfs_root *dead_root; struct btrfs_item *item; struct btrfs_root_item *ri; struct btrfs_key key; struct btrfs_path *path; int ret; u32 nritems; struct btrfs_leaf *leaf; int slot; key.objectid = 0; key.flags = 0; btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); key.offset = 0; path = btrfs_alloc_path(); if (!path) return -ENOMEM; ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto err; while(1) { leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; if (slot >= nritems) { ret = btrfs_next_leaf(root, path); if (ret) break; leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; } item = leaf->items + slot; btrfs_disk_key_to_cpu(&key, &item->key); if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) goto next; ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); if (btrfs_root_refs(ri) != 0) goto next; dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key); if (IS_ERR(root)) { ret = PTR_ERR(root); goto err; } printk("found dead root %Lu %u %Lu\n", key.objectid, key.flags, key.offset); ret = btrfs_add_dead_root(dead_root, &root->fs_info->dead_roots); if (ret) goto err; next: slot++; path->slots[0]++; } ret = 0; err: btrfs_free_path(path); return ret; } int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key) { Loading @@ -111,14 +174,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, path->slots[0], struct btrfs_root_item); refs = btrfs_root_refs(ri); BUG_ON(refs == 0); if (refs == 1) { BUG_ON(refs != 0); ret = btrfs_del_item(trans, root, path); } else { btrfs_set_root_refs(ri, refs - 1); WARN_ON(1); mark_buffer_dirty(path->nodes[0]); } out: btrfs_release_path(root, path); btrfs_free_path(path); Loading Loading
fs/btrfs/ctree.h +15 −2 Original line number Diff line number Diff line Loading @@ -122,12 +122,12 @@ struct btrfs_super_block { u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* this block number */ __le64 magic; __le32 blocksize; __le64 generation; __le64 root; __le64 total_blocks; __le64 blocks_used; __le64 root_dir_objectid; __le32 blocksize; } __attribute__ ((__packed__)); /* Loading Loading @@ -226,10 +226,12 @@ struct btrfs_root_item { struct btrfs_inode_item inode; __le64 root_dirid; __le64 blocknr; __le32 flags; __le64 block_limit; __le64 blocks_used; __le32 flags; __le32 refs; struct btrfs_disk_key drop_progress; u8 drop_level; } __attribute__ ((__packed__)); #define BTRFS_FILE_EXTENT_REG 0 Loading Loading @@ -800,6 +802,16 @@ static inline void btrfs_set_root_refs(struct btrfs_root_item *item, u32 val) item->refs = cpu_to_le32(val); } static inline u32 btrfs_root_flags(struct btrfs_root_item *item) { return le32_to_cpu(item->flags); } static inline void btrfs_set_root_flags(struct btrfs_root_item *item, u32 val) { item->flags = cpu_to_le32(val); } static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s) { return le64_to_cpu(s->blocknr); Loading Loading @@ -1076,6 +1088,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *item); int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key); int btrfs_find_dead_roots(struct btrfs_root *root); /* dir-item.c */ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, int name_len, u64 dir, Loading
fs/btrfs/disk-io.c +30 −14 Original line number Diff line number Diff line Loading @@ -326,7 +326,7 @@ static int find_and_setup_root(int blocksize, return 0; } struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, struct btrfs_key *location) { struct btrfs_root *root; Loading @@ -336,11 +336,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, u64 highest_inode; int ret = 0; root = radix_tree_lookup(&fs_info->fs_roots_radix, (unsigned long)location->objectid); if (root) return root; root = kmalloc(sizeof(*root), GFP_NOFS); root = kzalloc(sizeof(*root), GFP_NOFS); if (!root) return ERR_PTR(-ENOMEM); if (location->offset == (u64)-1) { Loading Loading @@ -383,6 +379,28 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, BUG_ON(!root->node); insert: root->ref_cows = 1; ret = btrfs_find_highest_inode(root, &highest_inode); if (ret == 0) { root->highest_inode = highest_inode; root->last_inode_alloc = highest_inode; } return root; } struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_key *location) { struct btrfs_root *root; int ret; root = radix_tree_lookup(&fs_info->fs_roots_radix, (unsigned long)location->objectid); if (root) return root; root = btrfs_read_fs_root_no_radix(fs_info, location); if (IS_ERR(root)) return root; ret = radix_tree_insert(&fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, root); Loading @@ -391,11 +409,6 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, kfree(root); return ERR_PTR(ret); } ret = btrfs_find_highest_inode(root, &highest_inode); if (ret == 0) { root->highest_inode = highest_inode; root->last_inode_alloc = highest_inode; } return root; } Loading Loading @@ -489,6 +502,9 @@ struct btrfs_root *open_ctree(struct super_block *sb) btrfs_read_block_groups(extent_root); fs_info->generation = btrfs_super_generation(disk_super) + 1; ret = btrfs_find_dead_roots(tree_root); if (ret) goto fail_tree_root; mutex_unlock(&fs_info->fs_mutex); return tree_root; Loading Loading @@ -538,7 +554,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root return 0; } static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) { radix_tree_delete(&fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid); Loading @@ -565,7 +581,7 @@ static int del_fs_roots(struct btrfs_fs_info *fs_info) if (!ret) break; for (i = 0; i < ret; i++) free_fs_root(fs_info, gang[i]); btrfs_free_fs_root(fs_info, gang[i]); } return 0; } Loading
fs/btrfs/disk-io.h +3 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,8 @@ int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, char *result); struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_key *location); struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, struct btrfs_key *location); u64 bh_blocknr(struct buffer_head *bh); int btrfs_insert_dev_radix(struct btrfs_root *root, struct block_device *bdev, Loading @@ -75,4 +77,5 @@ int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, u64 logical); int btrfs_releasepage(struct page *page, gfp_t flags); void btrfs_btree_balance_dirty(struct btrfs_root *root); int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); #endif
fs/btrfs/inode.c +2 −0 Original line number Diff line number Diff line Loading @@ -2028,6 +2028,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) btrfs_set_root_blocknr(&root_item, bh_blocknr(subvol)); btrfs_set_root_refs(&root_item, 1); memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); root_item.drop_level = 0; brelse(subvol); subvol = NULL; Loading
fs/btrfs/root-tree.c +66 −9 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/module.h> #include "ctree.h" #include "transaction.h" #include "disk-io.h" #include "print-tree.h" Loading @@ -32,7 +33,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, search_key.objectid = objectid; search_key.flags = (u32)-1; search_key.offset = (u32)-1; search_key.offset = (u64)-1; path = btrfs_alloc_path(); BUG_ON(!path); Loading @@ -50,6 +51,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item), sizeof(*item)); btrfs_disk_key_to_cpu(key, &l->items[slot].key); printk("find last finds key %Lu %u %Lu slot %d search for obj %Lu\n", key->objectid, key->flags, key->offset, slot, objectid); ret = 0; out: btrfs_release_path(root, path); Loading Loading @@ -93,6 +95,67 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root return ret; } int btrfs_find_dead_roots(struct btrfs_root *root) { struct btrfs_root *dead_root; struct btrfs_item *item; struct btrfs_root_item *ri; struct btrfs_key key; struct btrfs_path *path; int ret; u32 nritems; struct btrfs_leaf *leaf; int slot; key.objectid = 0; key.flags = 0; btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); key.offset = 0; path = btrfs_alloc_path(); if (!path) return -ENOMEM; ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto err; while(1) { leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; if (slot >= nritems) { ret = btrfs_next_leaf(root, path); if (ret) break; leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; } item = leaf->items + slot; btrfs_disk_key_to_cpu(&key, &item->key); if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) goto next; ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item); if (btrfs_root_refs(ri) != 0) goto next; dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key); if (IS_ERR(root)) { ret = PTR_ERR(root); goto err; } printk("found dead root %Lu %u %Lu\n", key.objectid, key.flags, key.offset); ret = btrfs_add_dead_root(dead_root, &root->fs_info->dead_roots); if (ret) goto err; next: slot++; path->slots[0]++; } ret = 0; err: btrfs_free_path(path); return ret; } int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key) { Loading @@ -111,14 +174,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, path->slots[0], struct btrfs_root_item); refs = btrfs_root_refs(ri); BUG_ON(refs == 0); if (refs == 1) { BUG_ON(refs != 0); ret = btrfs_del_item(trans, root, path); } else { btrfs_set_root_refs(ri, refs - 1); WARN_ON(1); mark_buffer_dirty(path->nodes[0]); } out: btrfs_release_path(root, path); btrfs_free_path(path); Loading