diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 549 |
1 files changed, 289 insertions, 260 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 3d33c4e41e5f..a59674c3e69e 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -37,6 +37,7 @@ */ #define LOG_INODE_ALL 0 #define LOG_INODE_EXISTS 1 +#define LOG_OTHER_INODE 2 /* * directory trouble cases @@ -96,7 +97,7 @@ #define LOG_WALK_REPLAY_ALL 3 static int btrfs_log_inode(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode, + struct btrfs_root *root, struct btrfs_inode *inode, int inode_only, const loff_t start, const loff_t end, @@ -142,12 +143,13 @@ static int start_log_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_log_ctx *ctx) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret = 0; mutex_lock(&root->log_mutex); if (root->log_root) { - if (btrfs_need_log_full_commit(root->fs_info, trans)) { + if (btrfs_need_log_full_commit(fs_info, trans)) { ret = -EAGAIN; goto out; } @@ -159,10 +161,10 @@ static int start_log_trans(struct btrfs_trans_handle *trans, set_bit(BTRFS_ROOT_MULTI_LOG_TASKS, &root->state); } } else { - mutex_lock(&root->fs_info->tree_log_mutex); - if (!root->fs_info->log_root_tree) - ret = btrfs_init_log_root_tree(trans, root->fs_info); - mutex_unlock(&root->fs_info->tree_log_mutex); + mutex_lock(&fs_info->tree_log_mutex); + if (!fs_info->log_root_tree) + ret = btrfs_init_log_root_tree(trans, fs_info); + mutex_unlock(&fs_info->tree_log_mutex); if (ret) goto out; @@ -292,25 +294,26 @@ static int process_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, struct walk_control *wc, u64 gen) { + struct btrfs_fs_info *fs_info = log->fs_info; int ret = 0; /* * If this fs is mixed then we need to be able to process the leaves to * pin down any logged extents, so we have to read the block. */ - if (btrfs_fs_incompat(log->fs_info, MIXED_GROUPS)) { + if (btrfs_fs_incompat(fs_info, MIXED_GROUPS)) { ret = btrfs_read_buffer(eb, gen); if (ret) return ret; } if (wc->pin) - ret = btrfs_pin_extent_for_log_replay(log->fs_info->extent_root, - eb->start, eb->len); + ret = btrfs_pin_extent_for_log_replay(fs_info, eb->start, + eb->len); if (!ret && btrfs_buffer_uptodate(eb, gen, 0)) { if (wc->pin && btrfs_header_level(eb) == 0) - ret = btrfs_exclude_logged_extents(log, eb); + ret = btrfs_exclude_logged_extents(fs_info, eb); if (wc->write) btrfs_write_tree_block(eb); if (wc->wait) @@ -339,6 +342,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, struct extent_buffer *eb, int slot, struct btrfs_key *key) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; u32 item_size; u64 saved_i_size = 0; @@ -459,9 +463,9 @@ insert: found_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]); if (found_size > item_size) - btrfs_truncate_item(root, path, item_size, 1); + btrfs_truncate_item(fs_info, path, item_size, 1); else if (found_size < item_size) - btrfs_extend_item(root, path, + btrfs_extend_item(fs_info, path, item_size - found_size); } else if (ret) { return ret; @@ -582,6 +586,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, struct extent_buffer *eb, int slot, struct btrfs_key *key) { + struct btrfs_fs_info *fs_info = root->fs_info; int found_type; u64 extent_end; u64 start = key->offset; @@ -608,7 +613,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { size = btrfs_file_extent_inline_len(eb, slot, item); nbytes = btrfs_file_extent_ram_bytes(eb, item); - extent_end = ALIGN(start + size, root->sectorsize); + extent_end = ALIGN(start + size, + fs_info->sectorsize); } else { ret = 0; goto out; @@ -625,8 +631,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, * file. This must be done before the btrfs_drop_extents run * so we don't try to drop this extent. */ - ret = btrfs_lookup_file_extent(trans, root, path, btrfs_ino(inode), - start, 0); + ret = btrfs_lookup_file_extent(trans, root, path, + btrfs_ino(BTRFS_I(inode)), start, 0); if (ret == 0 && (found_type == BTRFS_FILE_EXTENT_REG || @@ -667,6 +673,10 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, unsigned long dest_offset; struct btrfs_key ins; + if (btrfs_file_extent_disk_bytenr(eb, item) == 0 && + btrfs_fs_incompat(fs_info, NO_HOLES)) + goto update_inode; + ret = btrfs_insert_empty_item(trans, root, path, key, sizeof(*item)); if (ret) @@ -689,7 +699,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, * as the owner of the file extent changed from log tree * (doesn't affect qgroup) to fs/file tree(affects qgroup) */ - ret = btrfs_qgroup_insert_dirty_extent(trans, root->fs_info, + ret = btrfs_qgroup_trace_extent(trans, fs_info, btrfs_file_extent_disk_bytenr(eb, item), btrfs_file_extent_disk_num_bytes(eb, item), GFP_NOFS); @@ -704,10 +714,10 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, * is this extent already allocated in the extent * allocation tree? If so, just add a reference */ - ret = btrfs_lookup_data_extent(root, ins.objectid, + ret = btrfs_lookup_data_extent(fs_info, ins.objectid, ins.offset); if (ret == 0) { - ret = btrfs_inc_extent_ref(trans, root, + ret = btrfs_inc_extent_ref(trans, fs_info, ins.objectid, ins.offset, 0, root->root_key.objectid, key->objectid, offset); @@ -719,7 +729,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, * allocation tree */ ret = btrfs_alloc_logged_file_extent(trans, - root, root->root_key.objectid, + fs_info, + root->root_key.objectid, key->objectid, offset, &ins); if (ret) goto out; @@ -796,14 +807,12 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, struct btrfs_ordered_sum, list); if (!ret) - ret = btrfs_del_csums(trans, - root->fs_info->csum_root, - sums->bytenr, - sums->len); + ret = btrfs_del_csums(trans, fs_info, + sums->bytenr, + sums->len); if (!ret) ret = btrfs_csum_file_blocks(trans, - root->fs_info->csum_root, - sums); + fs_info->csum_root, sums); list_del(&sums->list); kfree(sums); } @@ -820,6 +829,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, } inode_add_bytes(inode, nbytes); +update_inode: ret = btrfs_update_inode(trans, root, inode); out: if (inode) @@ -838,9 +848,10 @@ out: static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, - struct inode *dir, + struct btrfs_inode *dir, struct btrfs_dir_item *di) { + struct btrfs_fs_info *fs_info = root->fs_info; struct inode *inode; char *name; int name_len; @@ -869,11 +880,12 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans, if (ret) goto out; - ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len); + ret = btrfs_unlink_inode(trans, root, dir, BTRFS_I(inode), name, + name_len); if (ret) goto out; else - ret = btrfs_run_delayed_items(trans, root); + ret = btrfs_run_delayed_items(trans, fs_info); out: kfree(name); iput(inode); @@ -985,12 +997,13 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_root *log_root, - struct inode *dir, struct inode *inode, - struct extent_buffer *eb, + struct btrfs_inode *dir, + struct btrfs_inode *inode, u64 inode_objectid, u64 parent_objectid, u64 ref_index, char *name, int namelen, int *search_done) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; char *victim_name; int victim_name_len; @@ -1040,16 +1053,15 @@ again: parent_objectid, victim_name, victim_name_len)) { - inc_nlink(inode); + inc_nlink(&inode->vfs_inode); btrfs_release_path(path); - ret = btrfs_unlink_inode(trans, root, dir, - inode, victim_name, - victim_name_len); + ret = btrfs_unlink_inode(trans, root, dir, inode, + victim_name, victim_name_len); kfree(victim_name); if (ret) return ret; - ret = btrfs_run_delayed_items(trans, root); + ret = btrfs_run_delayed_items(trans, fs_info); if (ret) return ret; *search_done = 1; @@ -1108,19 +1120,20 @@ again: victim_name_len)) { ret = -ENOENT; victim_parent = read_one_inode(root, - parent_objectid); + parent_objectid); if (victim_parent) { - inc_nlink(inode); + inc_nlink(&inode->vfs_inode); btrfs_release_path(path); ret = btrfs_unlink_inode(trans, root, - victim_parent, - inode, - victim_name, - victim_name_len); + BTRFS_I(victim_parent), + inode, + victim_name, + victim_name_len); if (!ret) ret = btrfs_run_delayed_items( - trans, root); + trans, + fs_info); } iput(victim_parent); kfree(victim_name); @@ -1287,8 +1300,9 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, goto out; /* if we already have a perfect match, we're done */ - if (!inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode), - ref_index, name, namelen)) { + if (!inode_in_dir(root, path, btrfs_ino(BTRFS_I(dir)), + btrfs_ino(BTRFS_I(inode)), ref_index, + name, namelen)) { /* * look for a conflicting back reference in the * metadata. if we find one we have to unlink that name @@ -1299,7 +1313,8 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, if (!search_done) { ret = __add_inode_ref(trans, root, path, log, - dir, inode, eb, + BTRFS_I(dir), + BTRFS_I(inode), inode_objectid, parent_objectid, ref_index, name, namelen, @@ -1312,8 +1327,9 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, } /* insert our name */ - ret = btrfs_add_link(trans, dir, inode, name, namelen, - 0, ref_index); + ret = btrfs_add_link(trans, BTRFS_I(dir), + BTRFS_I(inode), + name, namelen, 0, ref_index); if (ret) goto out; @@ -1352,7 +1368,7 @@ static int insert_orphan_item(struct btrfs_trans_handle *trans, } static int count_inode_extrefs(struct btrfs_root *root, - struct inode *inode, struct btrfs_path *path) + struct btrfs_inode *inode, struct btrfs_path *path) { int ret = 0; int name_len; @@ -1396,7 +1412,7 @@ static int count_inode_extrefs(struct btrfs_root *root, } static int count_inode_refs(struct btrfs_root *root, - struct inode *inode, struct btrfs_path *path) + struct btrfs_inode *inode, struct btrfs_path *path) { int ret; struct btrfs_key key; @@ -1469,19 +1485,19 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, struct btrfs_path *path; int ret; u64 nlink = 0; - u64 ino = btrfs_ino(inode); + u64 ino = btrfs_ino(BTRFS_I(inode)); path = btrfs_alloc_path(); if (!path) return -ENOMEM; - ret = count_inode_refs(root, inode, path); + ret = count_inode_refs(root, BTRFS_I(inode), path); if (ret < 0) goto out; nlink = ret; - ret = count_inode_extrefs(root, inode, path); + ret = count_inode_extrefs(root, BTRFS_I(inode), path); if (ret < 0) goto out; @@ -1631,7 +1647,8 @@ static noinline int insert_one_name(struct btrfs_trans_handle *trans, return -EIO; } - ret = btrfs_add_link(trans, dir, inode, name, name_len, 1, index); + ret = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode), name, + name_len, 1, index); /* FIXME, put inode into FIXUP list */ @@ -1761,7 +1778,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, if (!exists) goto out; - ret = drop_one_dir_item(trans, root, path, dir, dst_di); + ret = drop_one_dir_item(trans, root, path, BTRFS_I(dir), dst_di); if (ret) goto out; @@ -1770,7 +1787,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, out: btrfs_release_path(path); if (!ret && update_size) { - btrfs_i_size_write(dir, dir->i_size + name_len * 2); + btrfs_i_size_write(BTRFS_I(dir), dir->i_size + name_len * 2); ret = btrfs_update_inode(trans, root, dir); } kfree(name); @@ -1811,6 +1828,7 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, struct extent_buffer *eb, int slot, struct btrfs_key *key) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret = 0; u32 item_size = btrfs_item_size_nr(eb, slot); struct btrfs_dir_item *di; @@ -1823,7 +1841,7 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, ptr_end = ptr + item_size; while (ptr < ptr_end) { di = (struct btrfs_dir_item *)ptr; - if (verify_dir_item(root, eb, di)) + if (verify_dir_item(fs_info, eb, di)) return -EIO; name_len = btrfs_dir_name_len(eb, di); ret = replay_one_name(trans, root, path, eb, di, key); @@ -1940,12 +1958,11 @@ static noinline int find_dir_range(struct btrfs_root *root, next: /* check the next slot in the tree to see if it is a valid item */ nritems = btrfs_header_nritems(path->nodes[0]); + path->slots[0]++; if (path->slots[0] >= nritems) { ret = btrfs_next_leaf(root, path); if (ret) goto out; - } else { - path->slots[0]++; } btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); @@ -1978,6 +1995,7 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans, struct inode *dir, struct btrfs_key *dir_key) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; struct extent_buffer *eb; int slot; @@ -1999,7 +2017,7 @@ again: ptr_end = ptr + item_size; while (ptr < ptr_end) { di = (struct btrfs_dir_item *)ptr; - if (verify_dir_item(root, eb, di)) { + if (verify_dir_item(fs_info, eb, di)) { ret = -EIO; goto out; } @@ -2043,10 +2061,10 @@ again: } inc_nlink(inode); - ret = btrfs_unlink_inode(trans, root, dir, inode, - name, name_len); + ret = btrfs_unlink_inode(trans, root, BTRFS_I(dir), + BTRFS_I(inode), name, name_len); if (!ret) - ret = btrfs_run_delayed_items(trans, root); + ret = btrfs_run_delayed_items(trans, fs_info); kfree(name); iput(inode); if (ret) @@ -2407,6 +2425,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, struct btrfs_path *path, int *level, struct walk_control *wc) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 root_owner; u64 bytenr; u64 ptr_gen; @@ -2432,12 +2451,12 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, bytenr = btrfs_node_blockptr(cur, path->slots[*level]); ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); - blocksize = root->nodesize; + blocksize = fs_info->nodesize; parent = path->nodes[*level]; root_owner = btrfs_header_owner(parent); - next = btrfs_find_create_tree_block(root, bytenr); + next = btrfs_find_create_tree_block(fs_info, bytenr); if (IS_ERR(next)) return PTR_ERR(next); @@ -2459,16 +2478,16 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, if (trans) { btrfs_tree_lock(next); btrfs_set_lock_blocking(next); - clean_tree_block(trans, root->fs_info, - next); + clean_tree_block(fs_info, next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); } WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); - ret = btrfs_free_and_pin_reserved_extent(root, - bytenr, blocksize); + ret = btrfs_free_and_pin_reserved_extent( + fs_info, bytenr, + blocksize); if (ret) { free_extent_buffer(next); return ret; @@ -2505,6 +2524,7 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, struct btrfs_path *path, int *level, struct walk_control *wc) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 root_owner; int i; int slot; @@ -2538,14 +2558,14 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, if (trans) { btrfs_tree_lock(next); btrfs_set_lock_blocking(next); - clean_tree_block(trans, root->fs_info, - next); + clean_tree_block(fs_info, next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); } WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); - ret = btrfs_free_and_pin_reserved_extent(root, + ret = btrfs_free_and_pin_reserved_extent( + fs_info, path->nodes[*level]->start, path->nodes[*level]->len); if (ret) @@ -2567,6 +2587,7 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, static int walk_log_tree(struct btrfs_trans_handle *trans, struct btrfs_root *log, struct walk_control *wc) { + struct btrfs_fs_info *fs_info = log->fs_info; int ret = 0; int wret; int level; @@ -2615,15 +2636,15 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, if (trans) { btrfs_tree_lock(next); btrfs_set_lock_blocking(next); - clean_tree_block(trans, log->fs_info, next); + clean_tree_block(fs_info, next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); } WARN_ON(log->root_key.objectid != BTRFS_TREE_LOG_OBJECTID); - ret = btrfs_free_and_pin_reserved_extent(log, next->start, - next->len); + ret = btrfs_free_and_pin_reserved_extent(fs_info, + next->start, next->len); if (ret) goto out; } @@ -2641,14 +2662,15 @@ out: static int update_log_root(struct btrfs_trans_handle *trans, struct btrfs_root *log) { + struct btrfs_fs_info *fs_info = log->fs_info; int ret; if (log->log_transid == 1) { /* insert root item on the first sync */ - ret = btrfs_insert_root(trans, log->fs_info->log_root_tree, + ret = btrfs_insert_root(trans, fs_info->log_root_tree, &log->root_key, &log->root_item); } else { - ret = btrfs_update_root(trans, log->fs_info->log_root_tree, + ret = btrfs_update_root(trans, fs_info->log_root_tree, &log->root_key, &log->root_item); } return ret; @@ -2742,8 +2764,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, int index2; int mark; int ret; + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *log = root->log_root; - struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; + struct btrfs_root *log_root_tree = fs_info->log_root_tree; int log_transid = 0; struct btrfs_log_ctx root_log_ctx; struct blk_plug plug; @@ -2771,7 +2794,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, while (1) { int batch = atomic_read(&root->log_batch); /* when we're on an ssd, just kick the log commit out */ - if (!btrfs_test_opt(root->fs_info, SSD) && + if (!btrfs_test_opt(fs_info, SSD) && test_bit(BTRFS_ROOT_MULTI_LOG_TASKS, &root->state)) { mutex_unlock(&root->log_mutex); schedule_timeout_uninterruptible(1); @@ -2783,7 +2806,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, } /* bail out if we need to do a full commit */ - if (btrfs_need_log_full_commit(root->fs_info, trans)) { + if (btrfs_need_log_full_commit(fs_info, trans)) { ret = -EAGAIN; btrfs_free_logged_extents(log, log_transid); mutex_unlock(&root->log_mutex); @@ -2799,12 +2822,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, * wait for them until later. */ blk_start_plug(&plug); - ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark); + ret = btrfs_write_marked_extents(fs_info, &log->dirty_log_pages, mark); if (ret) { blk_finish_plug(&plug); btrfs_abort_transaction(trans, ret); btrfs_free_logged_extents(log, log_transid); - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); mutex_unlock(&root->log_mutex); goto out; } @@ -2849,14 +2872,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, list_del_init(&root_log_ctx.list); blk_finish_plug(&plug); - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); if (ret != -ENOSPC) { btrfs_abort_transaction(trans, ret); mutex_unlock(&log_root_tree->log_mutex); goto out; } - btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); + btrfs_wait_tree_log_extents(log, mark); btrfs_free_logged_extents(log, log_transid); mutex_unlock(&log_root_tree->log_mutex); ret = -EAGAIN; @@ -2874,8 +2897,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, index2 = root_log_ctx.log_transid % 2; if (atomic_read(&log_root_tree->log_commit[index2])) { blk_finish_plug(&plug); - ret = btrfs_wait_marked_extents(log, &log->dirty_log_pages, - mark); + ret = btrfs_wait_tree_log_extents(log, mark); btrfs_wait_logged_extents(trans, log, log_transid); wait_log_commit(log_root_tree, root_log_ctx.log_transid); @@ -2898,43 +2920,42 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, * now that we've moved on to the tree of log tree roots, * check the full commit flag again */ - if (btrfs_need_log_full_commit(root->fs_info, trans)) { + if (btrfs_need_log_full_commit(fs_info, trans)) { blk_finish_plug(&plug); - btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); + btrfs_wait_tree_log_extents(log, mark); btrfs_free_logged_extents(log, log_transid); mutex_unlock(&log_root_tree->log_mutex); ret = -EAGAIN; goto out_wake_log_root; } - ret = btrfs_write_marked_extents(log_root_tree, + ret = btrfs_write_marked_extents(fs_info, &log_root_tree->dirty_log_pages, EXTENT_DIRTY | EXTENT_NEW); blk_finish_plug(&plug); if (ret) { - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); btrfs_abort_transaction(trans, ret); btrfs_free_logged_extents(log, log_transid); mutex_unlock(&log_root_tree->log_mutex); goto out_wake_log_root; } - ret = btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); + ret = btrfs_wait_tree_log_extents(log, mark); if (!ret) - ret = btrfs_wait_marked_extents(log_root_tree, - &log_root_tree->dirty_log_pages, - EXTENT_NEW | EXTENT_DIRTY); + ret = btrfs_wait_tree_log_extents(log_root_tree, + EXTENT_NEW | EXTENT_DIRTY); if (ret) { - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); btrfs_free_logged_extents(log, log_transid); mutex_unlock(&log_root_tree->log_mutex); goto out_wake_log_root; } btrfs_wait_logged_extents(trans, log, log_transid); - btrfs_set_super_log_root(root->fs_info->super_for_commit, - log_root_tree->node->start); - btrfs_set_super_log_root_level(root->fs_info->super_for_commit, - btrfs_header_level(log_root_tree->node)); + btrfs_set_super_log_root(fs_info->super_for_commit, + log_root_tree->node->start); + btrfs_set_super_log_root_level(fs_info->super_for_commit, + btrfs_header_level(log_root_tree->node)); log_root_tree->log_transid++; mutex_unlock(&log_root_tree->log_mutex); @@ -2946,9 +2967,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, * the running transaction open, so a full commit can't hop * in and cause problems either. */ - ret = write_ctree_super(trans, root->fs_info->tree_root, 1); + ret = write_all_supers(fs_info, 1); if (ret) { - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); btrfs_abort_transaction(trans, ret); goto out_wake_log_root; } @@ -3072,7 +3093,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, int name_len, - struct inode *dir, u64 index) + struct btrfs_inode *dir, u64 index) { struct btrfs_root *log; struct btrfs_dir_item *di; @@ -3082,14 +3103,14 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, int bytes_del = 0; u64 dir_ino = btrfs_ino(dir); - if (BTRFS_I(dir)->logged_trans < trans->transid) + if (dir->logged_trans < trans->transid) return 0; ret = join_running_log_trans(root); if (ret) return 0; - mutex_lock(&BTRFS_I(dir)->log_mutex); + mutex_lock(&dir->log_mutex); log = root->log_root; path = btrfs_alloc_path(); @@ -3164,7 +3185,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, fail: btrfs_free_path(path); out_unlock: - mutex_unlock(&BTRFS_I(dir)->log_mutex); + mutex_unlock(&dir->log_mutex); if (ret == -ENOSPC) { btrfs_set_log_full_commit(root->fs_info, trans); ret = 0; @@ -3180,26 +3201,27 @@ out_unlock: int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, int name_len, - struct inode *inode, u64 dirid) + struct btrfs_inode *inode, u64 dirid) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *log; u64 index; int ret; - if (BTRFS_I(inode)->logged_trans < trans->transid) + if (inode->logged_trans < trans->transid) return 0; ret = join_running_log_trans(root); if (ret) return 0; log = root->log_root; - mutex_lock(&BTRFS_I(inode)->log_mutex); + mutex_lock(&inode->log_mutex); ret = btrfs_del_inode_ref(trans, log, name, name_len, btrfs_ino(inode), dirid, &index); - mutex_unlock(&BTRFS_I(inode)->log_mutex); + mutex_unlock(&inode->log_mutex); if (ret == -ENOSPC) { - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); ret = 0; } else if (ret < 0 && ret != -ENOENT) btrfs_abort_transaction(trans, ret); @@ -3247,7 +3269,7 @@ static noinline int insert_dir_log_key(struct btrfs_trans_handle *trans, * to replay anything deleted before the fsync */ static noinline int log_dir_items(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode, + struct btrfs_root *root, struct btrfs_inode *inode, struct btrfs_path *path, struct btrfs_path *dst_path, int key_type, struct btrfs_log_ctx *ctx, @@ -3437,7 +3459,7 @@ done: * key logged by this transaction. */ static noinline int log_directory_changes(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode, + struct btrfs_root *root, struct btrfs_inode *inode, struct btrfs_path *path, struct btrfs_path *dst_path, struct btrfs_log_ctx *ctx) @@ -3451,9 +3473,8 @@ again: min_key = 0; max_key = 0; while (1) { - ret = log_dir_items(trans, root, inode, path, - dst_path, key_type, ctx, min_key, - &max_key); + ret = log_dir_items(trans, root, inode, path, dst_path, key_type, + ctx, min_key, &max_key); if (ret) return ret; if (max_key == (u64)-1) @@ -3582,33 +3603,34 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, static int log_inode_item(struct btrfs_trans_handle *trans, struct btrfs_root *log, struct btrfs_path *path, - struct inode *inode) + struct btrfs_inode *inode) { struct btrfs_inode_item *inode_item; int ret; ret = btrfs_insert_empty_item(trans, log, path, - &BTRFS_I(inode)->location, - sizeof(*inode_item)); + &inode->location, sizeof(*inode_item)); if (ret && ret != -EEXIST) return ret; inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_inode_item); - fill_inode_item(trans, path->nodes[0], inode_item, inode, 0, 0); + fill_inode_item(trans, path->nodes[0], inode_item, &inode->vfs_inode, + 0, 0); btrfs_release_path(path); return 0; } static noinline int copy_items(struct btrfs_trans_handle *trans, - struct inode *inode, + struct btrfs_inode *inode, struct btrfs_path *dst_path, struct btrfs_path *src_path, u64 *last_extent, int start_slot, int nr, int inode_only, u64 logged_isize) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); unsigned long src_offset; unsigned long dst_offset; - struct btrfs_root *log = BTRFS_I(inode)->root->log_root; + struct btrfs_root *log = inode->root->log_root; struct btrfs_file_extent_item *extent; struct btrfs_inode_item *inode_item; struct extent_buffer *src = src_path->nodes[0]; @@ -3619,7 +3641,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, char *ins_data; int i; struct list_head ordered_sums; - int skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; + int skip_csum = inode->flags & BTRFS_INODE_NODATASUM; bool has_extents = false; bool need_find_last_extent = true; bool done = false; @@ -3661,7 +3683,8 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, dst_path->slots[0], struct btrfs_inode_item); fill_inode_item(trans, dst_path->nodes[0], inode_item, - inode, inode_only == LOG_INODE_EXISTS, + &inode->vfs_inode, + inode_only == LOG_INODE_EXISTS, logged_isize); } else { copy_extent_buffer(dst_path->nodes[0], src, dst_offset, @@ -3716,7 +3739,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, } ret = btrfs_lookup_csums_range( - log->fs_info->csum_root, + fs_info->csum_root, ds + cs, ds + cs + cl - 1, &ordered_sums, 0); if (ret) { @@ -3769,7 +3792,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, if (need_find_last_extent) { u64 len; - ret = btrfs_prev_leaf(BTRFS_I(inode)->root, src_path); + ret = btrfs_prev_leaf(inode->root, src_path); if (ret < 0) return ret; if (ret) @@ -3789,7 +3812,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, src_path->slots[0], extent); *last_extent = ALIGN(key.offset + len, - log->sectorsize); + fs_info->sectorsize); } else { len = btrfs_file_extent_num_bytes(src, extent); *last_extent = key.offset + len; @@ -3811,8 +3834,8 @@ fill_holes: if (need_find_last_extent) { /* btrfs_prev_leaf could return 1 without releasing the path */ btrfs_release_path(src_path); - ret = btrfs_search_slot(NULL, BTRFS_I(inode)->root, &first_key, - src_path, 0, 0); + ret = btrfs_search_slot(NULL, inode->root, &first_key, + src_path, 0, 0); if (ret < 0) return ret; ASSERT(ret == 0); @@ -3832,7 +3855,7 @@ fill_holes: u64 extent_end; if (i >= btrfs_header_nritems(src_path->nodes[0])) { - ret = btrfs_next_leaf(BTRFS_I(inode)->root, src_path); + ret = btrfs_next_leaf(inode->root, src_path); if (ret < 0) return ret; ASSERT(ret == 0); @@ -3852,7 +3875,8 @@ fill_holes: if (btrfs_file_extent_type(src, extent) == BTRFS_FILE_EXTENT_INLINE) { len = btrfs_file_extent_inline_len(src, i, extent); - extent_end = ALIGN(key.offset + len, log->sectorsize); + extent_end = ALIGN(key.offset + len, + fs_info->sectorsize); } else { len = btrfs_file_extent_num_bytes(src, extent); extent_end = key.offset + len; @@ -3866,8 +3890,7 @@ fill_holes: offset = *last_extent; len = key.offset - *last_extent; ret = btrfs_insert_file_extent(trans, log, btrfs_ino(inode), - offset, 0, 0, len, 0, len, 0, - 0, 0); + offset, 0, 0, len, 0, len, 0, 0, 0); if (ret) break; *last_extent = extent_end; @@ -3902,6 +3925,7 @@ static int wait_ordered_extents(struct btrfs_trans_handle *trans, const struct list_head *logged_list, bool *ordered_io_error) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_ordered_extent *ordered; struct btrfs_root *log = root->log_root; u64 mod_start = em->mod_start; @@ -4018,7 +4042,7 @@ static int wait_ordered_extents(struct btrfs_trans_handle *trans, } /* block start is already adjusted for the file extent offset. */ - ret = btrfs_lookup_csums_range(log->fs_info->csum_root, + ret = btrfs_lookup_csums_range(fs_info->csum_root, em->block_start + csum_offset, em->block_start + csum_offset + csum_len - 1, &ordered_sums, 0); @@ -4039,7 +4063,7 @@ static int wait_ordered_extents(struct btrfs_trans_handle *trans, } static int log_one_extent(struct btrfs_trans_handle *trans, - struct inode *inode, struct btrfs_root *root, + struct btrfs_inode *inode, struct btrfs_root *root, const struct extent_map *em, struct btrfs_path *path, const struct list_head *logged_list, @@ -4056,8 +4080,8 @@ static int log_one_extent(struct btrfs_trans_handle *trans, int extent_inserted = 0; bool ordered_io_err = false; - ret = wait_ordered_extents(trans, inode, root, em, logged_list, - &ordered_io_err); + ret = wait_ordered_extents(trans, &inode->vfs_inode, root, em, + logged_list, &ordered_io_err); if (ret) return ret; @@ -4068,7 +4092,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, btrfs_init_map_token(&token); - ret = __btrfs_drop_extents(trans, log, inode, path, em->start, + ret = __btrfs_drop_extents(trans, log, &inode->vfs_inode, path, em->start, em->start + em->len, NULL, 0, 1, sizeof(*fi), &extent_inserted); if (ret) @@ -4134,7 +4158,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct inode *inode, + struct btrfs_inode *inode, struct btrfs_path *path, struct list_head *logged_list, struct btrfs_log_ctx *ctx, @@ -4143,14 +4167,14 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, { struct extent_map *em, *n; struct list_head extents; - struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree; + struct extent_map_tree *tree = &inode->extent_tree; u64 test_gen; int ret = 0; int num = 0; INIT_LIST_HEAD(&extents); - down_write(&BTRFS_I(inode)->dio_sem); + down_write(&inode->dio_sem); write_lock(&tree->lock); test_gen = root->fs_info->last_trans_committed; @@ -4190,7 +4214,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, * without writing to the log tree and the fsync must report the * file data write error and not commit the current transaction. */ - ret = filemap_check_errors(inode->i_mapping); + ret = filemap_check_errors(inode->vfs_inode.i_mapping); if (ret) ctx->io_err = ret; process: @@ -4219,13 +4243,13 @@ process: } WARN_ON(!list_empty(&extents)); write_unlock(&tree->lock); - up_write(&BTRFS_I(inode)->dio_sem); + up_write(&inode->dio_sem); btrfs_release_path(path); return ret; } -static int logged_inode_size(struct btrfs_root *log, struct inode *inode, +static int logged_inode_size(struct btrfs_root *log, struct btrfs_inode *inode, struct btrfs_path *path, u64 *size_ret) { struct btrfs_key key; @@ -4263,7 +4287,7 @@ static int logged_inode_size(struct btrfs_root *log, struct inode *inode, */ static int btrfs_log_all_xattrs(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct inode *inode, + struct btrfs_inode *inode, struct btrfs_path *path, struct btrfs_path *dst_path) { @@ -4358,9 +4382,10 @@ static int btrfs_log_all_xattrs(struct btrfs_trans_handle *trans, */ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct inode *inode, + struct btrfs_inode *inode, struct btrfs_path *path) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; struct btrfs_key key; u64 hole_start; @@ -4368,9 +4393,9 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; struct btrfs_root *log = root->log_root; const u64 ino = btrfs_ino(inode); - const u64 i_size = i_size_read(inode); + const u64 i_size = i_size_read(&inode->vfs_inode); - if (!btrfs_fs_incompat(root->fs_info, NO_HOLES)) + if (!btrfs_fs_incompat(fs_info, NO_HOLES)) return 0; key.objectid = ino; @@ -4427,7 +4452,7 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, if (hole_size == 0) return 0; - hole_size = ALIGN(hole_size, root->sectorsize); + hole_size = ALIGN(hole_size, fs_info->sectorsize); ret = btrfs_insert_file_extent(trans, log, ino, hole_start, 0, 0, hole_size, 0, hole_size, 0, 0, 0); return ret; @@ -4478,7 +4503,7 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, static int btrfs_check_ref_name_override(struct extent_buffer *eb, const int slot, const struct btrfs_key *key, - struct inode *inode, + struct btrfs_inode *inode, u64 *other_ino) { int ret; @@ -4534,9 +4559,8 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb, } read_extent_buffer(eb, name, name_ptr, this_name_len); - di = btrfs_lookup_dir_item(NULL, BTRFS_I(inode)->root, - search_path, parent, - name, this_name_len, 0); + di = btrfs_lookup_dir_item(NULL, inode->root, search_path, + parent, name, this_name_len, 0); if (di && !IS_ERR(di)) { struct btrfs_key di_key; @@ -4579,12 +4603,13 @@ out: * This handles both files and directories. */ static int btrfs_log_inode(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode, + struct btrfs_root *root, struct btrfs_inode *inode, int inode_only, const loff_t start, const loff_t end, struct btrfs_log_ctx *ctx) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_path *path; struct btrfs_path *dst_path; struct btrfs_key min_key; @@ -4600,7 +4625,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, int ins_nr; bool fast_search = false; u64 ino = btrfs_ino(inode); - struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; + struct extent_map_tree *em_tree = &inode->extent_tree; u64 logged_isize = 0; bool need_log_inode_item = true; @@ -4621,10 +4646,10 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, /* today the code can only do partial logging of directories */ - if (S_ISDIR(inode->i_mode) || + if (S_ISDIR(inode->vfs_inode.i_mode) || (!test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, - &BTRFS_I(inode)->runtime_flags) && - inode_only == LOG_INODE_EXISTS)) + &inode->runtime_flags) && + inode_only >= LOG_INODE_EXISTS)) max_key.type = BTRFS_XATTR_ITEM_KEY; else max_key.type = (u8)-1; @@ -4636,8 +4661,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, * order for the log replay code to mark inodes for link count * fixup (create temporary BTRFS_TREE_LOG_FIXUP_OBJECTID items). */ - if (S_ISDIR(inode->i_mode) || - BTRFS_I(inode)->generation > root->fs_info->last_trans_committed) + if (S_ISDIR(inode->vfs_inode.i_mode) || + inode->generation > fs_info->last_trans_committed) ret = btrfs_commit_inode_delayed_items(trans, inode); else ret = btrfs_commit_inode_delayed_inode(inode); @@ -4648,13 +4673,18 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, return ret; } - mutex_lock(&BTRFS_I(inode)->log_mutex); + if (inode_only == LOG_OTHER_INODE) { + inode_only = LOG_INODE_EXISTS; + mutex_lock_nested(&inode->log_mutex, SINGLE_DEPTH_NESTING); + } else { + mutex_lock(&inode->log_mutex); + } /* * a brute force approach to making sure we get the most uptodate * copies of everything. */ - if (S_ISDIR(inode->i_mode)) { + if (S_ISDIR(inode->vfs_inode.i_mode)) { int max_key_type = BTRFS_DIR_LOG_INDEX_KEY; if (inode_only == LOG_INODE_EXISTS) @@ -4675,31 +4705,30 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, * (zeroes), as if an expanding truncate happened, * instead of getting a file of 4Kb only. */ - err = logged_inode_size(log, inode, path, - &logged_isize); + err = logged_inode_size(log, inode, path, &logged_isize); if (err) goto out_unlock; } if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, - &BTRFS_I(inode)->runtime_flags)) { + &inode->runtime_flags)) { if (inode_only == LOG_INODE_EXISTS) { max_key.type = BTRFS_XATTR_ITEM_KEY; ret = drop_objectid_items(trans, log, path, ino, max_key.type); } else { clear_bit(BTRFS_INODE_NEEDS_FULL_SYNC, - &BTRFS_I(inode)->runtime_flags); + &inode->runtime_flags); clear_bit(BTRFS_INODE_COPY_EVERYTHING, - &BTRFS_I(inode)->runtime_flags); + &inode->runtime_flags); while(1) { ret = btrfs_truncate_inode_items(trans, - log, inode, 0, 0); + log, &inode->vfs_inode, 0, 0); if (ret != -EAGAIN) break; } } } else if (test_and_clear_bit(BTRFS_INODE_COPY_EVERYTHING, - &BTRFS_I(inode)->runtime_flags) || + &inode->runtime_flags) || inode_only == LOG_INODE_EXISTS) { if (inode_only == LOG_INODE_ALL) fast_search = true; @@ -4740,18 +4769,17 @@ again: if ((min_key.type == BTRFS_INODE_REF_KEY || min_key.type == BTRFS_INODE_EXTREF_KEY) && - BTRFS_I(inode)->generation == trans->transid) { + inode->generation == trans->transid) { u64 other_ino = 0; ret = btrfs_check_ref_name_override(path->nodes[0], - path->slots[0], - &min_key, inode, - &other_ino); + path->slots[0], &min_key, inode, + &other_ino); if (ret < 0) { err = ret; goto out_unlock; } else if (ret > 0 && ctx && - other_ino != btrfs_ino(ctx->inode)) { + other_ino != btrfs_ino(BTRFS_I(ctx->inode))) { struct btrfs_key inode_key; struct inode *other_inode; @@ -4774,7 +4802,7 @@ again: inode_key.objectid = other_ino; inode_key.type = BTRFS_INODE_ITEM_KEY; inode_key.offset = 0; - other_inode = btrfs_iget(root->fs_info->sb, + other_inode = btrfs_iget(fs_info->sb, &inode_key, root, NULL); /* @@ -4799,9 +4827,10 @@ again: * update the log with the new name before we * unpin it. */ - err = btrfs_log_inode(trans, root, other_inode, - LOG_INODE_EXISTS, - 0, LLONG_MAX, ctx); + err = btrfs_log_inode(trans, root, + BTRFS_I(other_inode), + LOG_OTHER_INODE, 0, LLONG_MAX, + ctx); iput(other_inode); if (err) goto out_unlock; @@ -4955,25 +4984,25 @@ log_extents: write_unlock(&em_tree->lock); } - if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) { + if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->vfs_inode.i_mode)) { ret = log_directory_changes(trans, root, inode, path, dst_path, - ctx); + ctx); if (ret) { err = ret; goto out_unlock; } } - spin_lock(&BTRFS_I(inode)->lock); - BTRFS_I(inode)->logged_trans = trans->transid; - BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans; - spin_unlock(&BTRFS_I(inode)->lock); + spin_lock(&inode->lock); + inode->logged_trans = trans->transid; + inode->last_log_commit = inode->last_sub_trans; + spin_unlock(&inode->lock); out_unlock: if (unlikely(err)) btrfs_put_logged_extents(&logged_list); else btrfs_submit_logged_extents(&logged_list, log); - mutex_unlock(&BTRFS_I(inode)->log_mutex); + mutex_unlock(&inode->log_mutex); btrfs_free_path(path); btrfs_free_path(dst_path); @@ -4997,13 +5026,13 @@ out_unlock: * we logged the inode or it might have also done the unlink). */ static bool btrfs_must_commit_transaction(struct btrfs_trans_handle *trans, - struct inode *inode) + struct btrfs_inode *inode) { - struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; + struct btrfs_fs_info *fs_info = inode->root->fs_info; bool ret = false; - mutex_lock(&BTRFS_I(inode)->log_mutex); - if (BTRFS_I(inode)->last_unlink_trans > fs_info->last_trans_committed) { + mutex_lock(&inode->log_mutex); + if (inode->last_unlink_trans > fs_info->last_trans_committed) { /* * Make sure any commits to the log are forced to be full * commits. @@ -5011,7 +5040,7 @@ static bool btrfs_must_commit_transaction(struct btrfs_trans_handle *trans, btrfs_set_log_full_commit(fs_info, trans); ret = true; } - mutex_unlock(&BTRFS_I(inode)->log_mutex); + mutex_unlock(&inode->log_mutex); return ret; } @@ -5023,14 +5052,14 @@ static bool btrfs_must_commit_transaction(struct btrfs_trans_handle *trans, * a full commit is required. */ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, - struct inode *inode, + struct btrfs_inode *inode, struct dentry *parent, struct super_block *sb, u64 last_committed) { int ret = 0; struct dentry *old_parent = NULL; - struct inode *orig_inode = inode; + struct btrfs_inode *orig_inode = inode; /* * for regular files, if its inode is already on disk, we don't @@ -5038,15 +5067,15 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, * we can use the last_unlink_trans field to record renames * and other fun in this file. */ - if (S_ISREG(inode->i_mode) && - BTRFS_I(inode)->generation <= last_committed && - BTRFS_I(inode)->last_unlink_trans <= last_committed) - goto out; + if (S_ISREG(inode->vfs_inode.i_mode) && + inode->generation <= last_committed && + inode->last_unlink_trans <= last_committed) + goto out; - if (!S_ISDIR(inode->i_mode)) { + if (!S_ISDIR(inode->vfs_inode.i_mode)) { if (!parent || d_really_is_negative(parent) || sb != parent->d_sb) goto out; - inode = d_inode(parent); + inode = BTRFS_I(d_inode(parent)); } while (1) { @@ -5057,7 +5086,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, * think this inode has already been logged. */ if (inode != orig_inode) - BTRFS_I(inode)->logged_trans = trans->transid; + inode->logged_trans = trans->transid; smp_mb(); if (btrfs_must_commit_transaction(trans, inode)) { @@ -5069,7 +5098,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, break; if (IS_ROOT(parent)) { - inode = d_inode(parent); + inode = BTRFS_I(d_inode(parent)); if (btrfs_must_commit_transaction(trans, inode)) ret = 1; break; @@ -5078,7 +5107,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, parent = dget_parent(parent); dput(old_parent); old_parent = parent; - inode = d_inode(parent); + inode = BTRFS_I(d_inode(parent)); } dput(old_parent); @@ -5135,9 +5164,10 @@ struct btrfs_dir_list { */ static int log_new_dir_dentries(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct inode *start_inode, + struct btrfs_inode *start_inode, struct btrfs_log_ctx *ctx) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *log = root->log_root; struct btrfs_path *path; LIST_HEAD(dir_list); @@ -5205,26 +5235,25 @@ process_leaf: if (di_key.type == BTRFS_ROOT_ITEM_KEY) continue; - di_inode = btrfs_iget(root->fs_info->sb, &di_key, - root, NULL); + btrfs_release_path(path); + di_inode = btrfs_iget(fs_info->sb, &di_key, root, NULL); if (IS_ERR(di_inode)) { ret = PTR_ERR(di_inode); goto next_dir_inode; } - if (btrfs_inode_in_log(di_inode, trans->transid)) { + if (btrfs_inode_in_log(BTRFS_I(di_inode), trans->transid)) { iput(di_inode); - continue; + break; } ctx->log_new_dentries = false; if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK) log_mode = LOG_INODE_ALL; - btrfs_release_path(path); - ret = btrfs_log_inode(trans, root, di_inode, + ret = btrfs_log_inode(trans, root, BTRFS_I(di_inode), log_mode, 0, LLONG_MAX, ctx); if (!ret && - btrfs_must_commit_transaction(trans, di_inode)) + btrfs_must_commit_transaction(trans, BTRFS_I(di_inode))) ret = 1; iput(di_inode); if (ret) @@ -5265,13 +5294,14 @@ next_dir_inode: } static int btrfs_log_all_parents(struct btrfs_trans_handle *trans, - struct inode *inode, + struct btrfs_inode *inode, struct btrfs_log_ctx *ctx) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); int ret; struct btrfs_path *path; struct btrfs_key key; - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_root *root = inode->root; const u64 ino = btrfs_ino(inode); path = btrfs_alloc_path(); @@ -5332,7 +5362,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans, cur_offset = item_size; } - dir_inode = btrfs_iget(root->fs_info->sb, &inode_key, + dir_inode = btrfs_iget(fs_info->sb, &inode_key, root, NULL); /* If parent inode was deleted, skip it. */ if (IS_ERR(dir_inode)) @@ -5340,14 +5370,14 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans, if (ctx) ctx->log_new_dentries = false; - ret = btrfs_log_inode(trans, root, dir_inode, + ret = btrfs_log_inode(trans, root, BTRFS_I(dir_inode), LOG_INODE_ALL, 0, LLONG_MAX, ctx); if (!ret && - btrfs_must_commit_transaction(trans, dir_inode)) + btrfs_must_commit_transaction(trans, BTRFS_I(dir_inode))) ret = 1; if (!ret && ctx && ctx->log_new_dentries) ret = log_new_dir_dentries(trans, root, - dir_inode, ctx); + BTRFS_I(dir_inode), ctx); iput(dir_inode); if (ret) goto out; @@ -5367,24 +5397,26 @@ out: * the last committed transaction */ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode, + struct btrfs_root *root, + struct btrfs_inode *inode, struct dentry *parent, const loff_t start, const loff_t end, int exists_only, struct btrfs_log_ctx *ctx) { + struct btrfs_fs_info *fs_info = root->fs_info; int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; struct super_block *sb; struct dentry *old_parent = NULL; int ret = 0; - u64 last_committed = root->fs_info->last_trans_committed; + u64 last_committed = fs_info->last_trans_committed; bool log_dentries = false; - struct inode *orig_inode = inode; + struct btrfs_inode *orig_inode = inode; - sb = inode->i_sb; + sb = inode->vfs_inode.i_sb; - if (btrfs_test_opt(root->fs_info, NOTREELOG)) { + if (btrfs_test_opt(fs_info, NOTREELOG)) { ret = 1; goto end_no_trans; } @@ -5393,20 +5425,19 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, * The prev transaction commit doesn't complete, we need do * full commit by ourselves. */ - if (root->fs_info->last_trans_log_full_commit > - root->fs_info->last_trans_committed) { + if (fs_info->last_trans_log_full_commit > + fs_info->last_trans_committed) { ret = 1; goto end_no_trans; } - if (root != BTRFS_I(inode)->root || - btrfs_root_refs(&root->root_item) == 0) { + if (root != inode->root || btrfs_root_refs(&root->root_item) == 0) { ret = 1; goto end_no_trans; } - ret = check_parent_dirs_for_sync(trans, inode, parent, - sb, last_committed); + ret = check_parent_dirs_for_sync(trans, inode, parent, sb, + last_committed); if (ret) goto end_no_trans; @@ -5429,14 +5460,14 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, * we can use the last_unlink_trans field to record renames * and other fun in this file. */ - if (S_ISREG(inode->i_mode) && - BTRFS_I(inode)->generation <= last_committed && - BTRFS_I(inode)->last_unlink_trans <= last_committed) { + if (S_ISREG(inode->vfs_inode.i_mode) && + inode->generation <= last_committed && + inode->last_unlink_trans <= last_committed) { ret = 0; goto end_trans; } - if (S_ISDIR(inode->i_mode) && ctx && ctx->log_new_dentries) + if (S_ISDIR(inode->vfs_inode.i_mode) && ctx && ctx->log_new_dentries) log_dentries = true; /* @@ -5480,7 +5511,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, * but the file inode does not have a matching BTRFS_INODE_REF_KEY item * and has a link count of 2. */ - if (BTRFS_I(inode)->last_unlink_trans > last_committed) { + if (inode->last_unlink_trans > last_committed) { ret = btrfs_log_all_parents(trans, orig_inode, ctx); if (ret) goto end_trans; @@ -5490,14 +5521,13 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, if (!parent || d_really_is_negative(parent) || sb != parent->d_sb) break; - inode = d_inode(parent); - if (root != BTRFS_I(inode)->root) + inode = BTRFS_I(d_inode(parent)); + if (root != inode->root) break; - if (BTRFS_I(inode)->generation > last_committed) { + if (inode->generation > last_committed) { ret = btrfs_log_inode(trans, root, inode, - LOG_INODE_EXISTS, - 0, LLONG_MAX, ctx); + LOG_INODE_EXISTS, 0, LLONG_MAX, ctx); if (ret) goto end_trans; } @@ -5515,7 +5545,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, end_trans: dput(old_parent); if (ret < 0) { - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); ret = 1; } @@ -5541,8 +5571,8 @@ int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans, struct dentry *parent = dget_parent(dentry); int ret; - ret = btrfs_log_inode_parent(trans, root, d_inode(dentry), parent, - start, end, 0, ctx); + ret = btrfs_log_inode_parent(trans, root, BTRFS_I(d_inode(dentry)), + parent, start, end, 0, ctx); dput(parent); return ret; @@ -5675,7 +5705,7 @@ again: btrfs_free_path(path); /* step 4: commit the transaction, which also unpins the blocks */ - ret = btrfs_commit_transaction(trans, fs_info->tree_root); + ret = btrfs_commit_transaction(trans); if (ret) return ret; @@ -5687,7 +5717,7 @@ again: return 0; error: if (wc.trans) - btrfs_end_transaction(wc.trans, fs_info->tree_root); + btrfs_end_transaction(wc.trans); btrfs_free_path(path); return ret; } @@ -5704,7 +5734,7 @@ error: * inodes, etc) are done. */ void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans, - struct inode *dir, struct inode *inode, + struct btrfs_inode *dir, struct btrfs_inode *inode, int for_rename) { /* @@ -5717,23 +5747,23 @@ void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans, * into the file. When the file is logged we check it and * don't log the parents if the file is fully on disk. */ - mutex_lock(&BTRFS_I(inode)->log_mutex); - BTRFS_I(inode)->last_unlink_trans = trans->transid; - mutex_unlock(&BTRFS_I(inode)->log_mutex); + mutex_lock(&inode->log_mutex); + inode->last_unlink_trans = trans->transid; + mutex_unlock(&inode->log_mutex); /* * if this directory was already logged any new * names for this file/dir will get recorded */ smp_mb(); - if (BTRFS_I(dir)->logged_trans == trans->transid) + if (dir->logged_trans == trans->transid) return; /* * if the inode we're about to unlink was logged, * the log will be properly updated for any new names */ - if (BTRFS_I(inode)->logged_trans == trans->transid) + if (inode->logged_trans == trans->transid) return; /* @@ -5750,9 +5780,9 @@ void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans, return; record: - mutex_lock(&BTRFS_I(dir)->log_mutex); - BTRFS_I(dir)->last_unlink_trans = trans->transid; - mutex_unlock(&BTRFS_I(dir)->log_mutex); + mutex_lock(&dir->log_mutex); + dir->last_unlink_trans = trans->transid; + mutex_unlock(&dir->log_mutex); } /* @@ -5768,11 +5798,11 @@ record: * parent root and tree of tree roots trees, etc) are done. */ void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans, - struct inode *dir) + struct btrfs_inode *dir) { - mutex_lock(&BTRFS_I(dir)->log_mutex); - BTRFS_I(dir)->last_unlink_trans = trans->transid; - mutex_unlock(&BTRFS_I(dir)->log_mutex); + mutex_lock(&dir->log_mutex); + dir->last_unlink_trans = trans->transid; + mutex_unlock(&dir->log_mutex); } /* @@ -5783,26 +5813,25 @@ void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans, * full transaction commit is required. */ int btrfs_log_new_name(struct btrfs_trans_handle *trans, - struct inode *inode, struct inode *old_dir, + struct btrfs_inode *inode, struct btrfs_inode *old_dir, struct dentry *parent) { - struct btrfs_root * root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_root *root = inode->root; /* * this will force the logging code to walk the dentry chain * up for the file */ - if (S_ISREG(inode->i_mode)) - BTRFS_I(inode)->last_unlink_trans = trans->transid; + if (S_ISREG(inode->vfs_inode.i_mode)) + inode->last_unlink_trans = trans->transid; /* * if this inode hasn't been logged and directory we're renaming it * from hasn't been logged, we don't need to log it */ - if (BTRFS_I(inode)->logged_trans <= - root->fs_info->last_trans_committed && - (!old_dir || BTRFS_I(old_dir)->logged_trans <= - root->fs_info->last_trans_committed)) + if (inode->logged_trans <= fs_info->last_trans_committed && + (!old_dir || old_dir->logged_trans <= fs_info->last_trans_committed)) return 0; return btrfs_log_inode_parent(trans, root, inode, parent, 0, |