diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 282 |
1 files changed, 171 insertions, 111 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 4a9434b622ec..054744ac5719 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/slab.h> | ||
20 | #include "ctree.h" | 21 | #include "ctree.h" |
21 | #include "transaction.h" | 22 | #include "transaction.h" |
22 | #include "disk-io.h" | 23 | #include "disk-io.h" |
@@ -134,6 +135,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans, | |||
134 | struct btrfs_root *root) | 135 | struct btrfs_root *root) |
135 | { | 136 | { |
136 | int ret; | 137 | int ret; |
138 | int err = 0; | ||
137 | 139 | ||
138 | mutex_lock(&root->log_mutex); | 140 | mutex_lock(&root->log_mutex); |
139 | if (root->log_root) { | 141 | if (root->log_root) { |
@@ -154,17 +156,19 @@ static int start_log_trans(struct btrfs_trans_handle *trans, | |||
154 | mutex_lock(&root->fs_info->tree_log_mutex); | 156 | mutex_lock(&root->fs_info->tree_log_mutex); |
155 | if (!root->fs_info->log_root_tree) { | 157 | if (!root->fs_info->log_root_tree) { |
156 | ret = btrfs_init_log_root_tree(trans, root->fs_info); | 158 | ret = btrfs_init_log_root_tree(trans, root->fs_info); |
157 | BUG_ON(ret); | 159 | if (ret) |
160 | err = ret; | ||
158 | } | 161 | } |
159 | if (!root->log_root) { | 162 | if (err == 0 && !root->log_root) { |
160 | ret = btrfs_add_log_tree(trans, root); | 163 | ret = btrfs_add_log_tree(trans, root); |
161 | BUG_ON(ret); | 164 | if (ret) |
165 | err = ret; | ||
162 | } | 166 | } |
163 | mutex_unlock(&root->fs_info->tree_log_mutex); | 167 | mutex_unlock(&root->fs_info->tree_log_mutex); |
164 | root->log_batch++; | 168 | root->log_batch++; |
165 | atomic_inc(&root->log_writers); | 169 | atomic_inc(&root->log_writers); |
166 | mutex_unlock(&root->log_mutex); | 170 | mutex_unlock(&root->log_mutex); |
167 | return 0; | 171 | return err; |
168 | } | 172 | } |
169 | 173 | ||
170 | /* | 174 | /* |
@@ -375,7 +379,7 @@ insert: | |||
375 | BUG_ON(ret); | 379 | BUG_ON(ret); |
376 | } | 380 | } |
377 | } else if (ret) { | 381 | } else if (ret) { |
378 | BUG(); | 382 | return ret; |
379 | } | 383 | } |
380 | dst_ptr = btrfs_item_ptr_offset(path->nodes[0], | 384 | dst_ptr = btrfs_item_ptr_offset(path->nodes[0], |
381 | path->slots[0]); | 385 | path->slots[0]); |
@@ -445,7 +449,7 @@ static noinline struct inode *read_one_inode(struct btrfs_root *root, | |||
445 | key.objectid = objectid; | 449 | key.objectid = objectid; |
446 | key.type = BTRFS_INODE_ITEM_KEY; | 450 | key.type = BTRFS_INODE_ITEM_KEY; |
447 | key.offset = 0; | 451 | key.offset = 0; |
448 | inode = btrfs_iget(root->fs_info->sb, &key, root); | 452 | inode = btrfs_iget(root->fs_info->sb, &key, root, NULL); |
449 | if (IS_ERR(inode)) { | 453 | if (IS_ERR(inode)) { |
450 | inode = NULL; | 454 | inode = NULL; |
451 | } else if (is_bad_inode(inode)) { | 455 | } else if (is_bad_inode(inode)) { |
@@ -782,7 +786,6 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
782 | { | 786 | { |
783 | struct inode *dir; | 787 | struct inode *dir; |
784 | int ret; | 788 | int ret; |
785 | struct btrfs_key location; | ||
786 | struct btrfs_inode_ref *ref; | 789 | struct btrfs_inode_ref *ref; |
787 | struct btrfs_dir_item *di; | 790 | struct btrfs_dir_item *di; |
788 | struct inode *inode; | 791 | struct inode *inode; |
@@ -791,10 +794,6 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
791 | unsigned long ref_ptr; | 794 | unsigned long ref_ptr; |
792 | unsigned long ref_end; | 795 | unsigned long ref_end; |
793 | 796 | ||
794 | location.objectid = key->objectid; | ||
795 | location.type = BTRFS_INODE_ITEM_KEY; | ||
796 | location.offset = 0; | ||
797 | |||
798 | /* | 797 | /* |
799 | * it is possible that we didn't log all the parent directories | 798 | * it is possible that we didn't log all the parent directories |
800 | * for a given inode. If we don't find the dir, just don't | 799 | * for a given inode. If we don't find the dir, just don't |
@@ -1579,7 +1578,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1579 | struct btrfs_path *path; | 1578 | struct btrfs_path *path; |
1580 | struct btrfs_root *root = wc->replay_dest; | 1579 | struct btrfs_root *root = wc->replay_dest; |
1581 | struct btrfs_key key; | 1580 | struct btrfs_key key; |
1582 | u32 item_size; | ||
1583 | int level; | 1581 | int level; |
1584 | int i; | 1582 | int i; |
1585 | int ret; | 1583 | int ret; |
@@ -1597,7 +1595,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1597 | nritems = btrfs_header_nritems(eb); | 1595 | nritems = btrfs_header_nritems(eb); |
1598 | for (i = 0; i < nritems; i++) { | 1596 | for (i = 0; i < nritems; i++) { |
1599 | btrfs_item_key_to_cpu(eb, &key, i); | 1597 | btrfs_item_key_to_cpu(eb, &key, i); |
1600 | item_size = btrfs_item_size_nr(eb, i); | ||
1601 | 1598 | ||
1602 | /* inode keys are done during the first stage */ | 1599 | /* inode keys are done during the first stage */ |
1603 | if (key.type == BTRFS_INODE_ITEM_KEY && | 1600 | if (key.type == BTRFS_INODE_ITEM_KEY && |
@@ -1664,7 +1661,6 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
1664 | struct walk_control *wc) | 1661 | struct walk_control *wc) |
1665 | { | 1662 | { |
1666 | u64 root_owner; | 1663 | u64 root_owner; |
1667 | u64 root_gen; | ||
1668 | u64 bytenr; | 1664 | u64 bytenr; |
1669 | u64 ptr_gen; | 1665 | u64 ptr_gen; |
1670 | struct extent_buffer *next; | 1666 | struct extent_buffer *next; |
@@ -1694,13 +1690,12 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
1694 | 1690 | ||
1695 | parent = path->nodes[*level]; | 1691 | parent = path->nodes[*level]; |
1696 | root_owner = btrfs_header_owner(parent); | 1692 | root_owner = btrfs_header_owner(parent); |
1697 | root_gen = btrfs_header_generation(parent); | ||
1698 | 1693 | ||
1699 | next = btrfs_find_create_tree_block(root, bytenr, blocksize); | 1694 | next = btrfs_find_create_tree_block(root, bytenr, blocksize); |
1700 | 1695 | ||
1701 | wc->process_func(root, next, wc, ptr_gen); | ||
1702 | |||
1703 | if (*level == 1) { | 1696 | if (*level == 1) { |
1697 | wc->process_func(root, next, wc, ptr_gen); | ||
1698 | |||
1704 | path->slots[*level]++; | 1699 | path->slots[*level]++; |
1705 | if (wc->free) { | 1700 | if (wc->free) { |
1706 | btrfs_read_buffer(next, ptr_gen); | 1701 | btrfs_read_buffer(next, ptr_gen); |
@@ -1733,35 +1728,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
1733 | WARN_ON(*level < 0); | 1728 | WARN_ON(*level < 0); |
1734 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 1729 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
1735 | 1730 | ||
1736 | if (path->nodes[*level] == root->node) | 1731 | path->slots[*level] = btrfs_header_nritems(path->nodes[*level]); |
1737 | parent = path->nodes[*level]; | ||
1738 | else | ||
1739 | parent = path->nodes[*level + 1]; | ||
1740 | |||
1741 | bytenr = path->nodes[*level]->start; | ||
1742 | |||
1743 | blocksize = btrfs_level_size(root, *level); | ||
1744 | root_owner = btrfs_header_owner(parent); | ||
1745 | root_gen = btrfs_header_generation(parent); | ||
1746 | |||
1747 | wc->process_func(root, path->nodes[*level], wc, | ||
1748 | btrfs_header_generation(path->nodes[*level])); | ||
1749 | |||
1750 | if (wc->free) { | ||
1751 | next = path->nodes[*level]; | ||
1752 | btrfs_tree_lock(next); | ||
1753 | clean_tree_block(trans, root, next); | ||
1754 | btrfs_set_lock_blocking(next); | ||
1755 | btrfs_wait_tree_block_writeback(next); | ||
1756 | btrfs_tree_unlock(next); | ||
1757 | |||
1758 | WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); | ||
1759 | ret = btrfs_free_reserved_extent(root, bytenr, blocksize); | ||
1760 | BUG_ON(ret); | ||
1761 | } | ||
1762 | free_extent_buffer(path->nodes[*level]); | ||
1763 | path->nodes[*level] = NULL; | ||
1764 | *level += 1; | ||
1765 | 1732 | ||
1766 | cond_resched(); | 1733 | cond_resched(); |
1767 | return 0; | 1734 | return 0; |
@@ -1773,16 +1740,13 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, | |||
1773 | struct walk_control *wc) | 1740 | struct walk_control *wc) |
1774 | { | 1741 | { |
1775 | u64 root_owner; | 1742 | u64 root_owner; |
1776 | u64 root_gen; | ||
1777 | int i; | 1743 | int i; |
1778 | int slot; | 1744 | int slot; |
1779 | int ret; | 1745 | int ret; |
1780 | 1746 | ||
1781 | for (i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 1747 | for (i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
1782 | slot = path->slots[i]; | 1748 | slot = path->slots[i]; |
1783 | if (slot < btrfs_header_nritems(path->nodes[i]) - 1) { | 1749 | if (slot + 1 < btrfs_header_nritems(path->nodes[i])) { |
1784 | struct extent_buffer *node; | ||
1785 | node = path->nodes[i]; | ||
1786 | path->slots[i]++; | 1750 | path->slots[i]++; |
1787 | *level = i; | 1751 | *level = i; |
1788 | WARN_ON(*level == 0); | 1752 | WARN_ON(*level == 0); |
@@ -1795,7 +1759,6 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, | |||
1795 | parent = path->nodes[*level + 1]; | 1759 | parent = path->nodes[*level + 1]; |
1796 | 1760 | ||
1797 | root_owner = btrfs_header_owner(parent); | 1761 | root_owner = btrfs_header_owner(parent); |
1798 | root_gen = btrfs_header_generation(parent); | ||
1799 | wc->process_func(root, path->nodes[*level], wc, | 1762 | wc->process_func(root, path->nodes[*level], wc, |
1800 | btrfs_header_generation(path->nodes[*level])); | 1763 | btrfs_header_generation(path->nodes[*level])); |
1801 | if (wc->free) { | 1764 | if (wc->free) { |
@@ -2046,7 +2009,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2046 | mutex_unlock(&log_root_tree->log_mutex); | 2009 | mutex_unlock(&log_root_tree->log_mutex); |
2047 | 2010 | ||
2048 | ret = update_log_root(trans, log); | 2011 | ret = update_log_root(trans, log); |
2049 | BUG_ON(ret); | ||
2050 | 2012 | ||
2051 | mutex_lock(&log_root_tree->log_mutex); | 2013 | mutex_lock(&log_root_tree->log_mutex); |
2052 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { | 2014 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { |
@@ -2055,6 +2017,15 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2055 | wake_up(&log_root_tree->log_writer_wait); | 2017 | wake_up(&log_root_tree->log_writer_wait); |
2056 | } | 2018 | } |
2057 | 2019 | ||
2020 | if (ret) { | ||
2021 | BUG_ON(ret != -ENOSPC); | ||
2022 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
2023 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | ||
2024 | mutex_unlock(&log_root_tree->log_mutex); | ||
2025 | ret = -EAGAIN; | ||
2026 | goto out; | ||
2027 | } | ||
2028 | |||
2058 | index2 = log_root_tree->log_transid % 2; | 2029 | index2 = log_root_tree->log_transid % 2; |
2059 | if (atomic_read(&log_root_tree->log_commit[index2])) { | 2030 | if (atomic_read(&log_root_tree->log_commit[index2])) { |
2060 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2031 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
@@ -2128,15 +2099,10 @@ out: | |||
2128 | return 0; | 2099 | return 0; |
2129 | } | 2100 | } |
2130 | 2101 | ||
2131 | /* | 2102 | static void free_log_tree(struct btrfs_trans_handle *trans, |
2132 | * free all the extents used by the tree log. This should be called | 2103 | struct btrfs_root *log) |
2133 | * at commit time of the full transaction | ||
2134 | */ | ||
2135 | int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | ||
2136 | { | 2104 | { |
2137 | int ret; | 2105 | int ret; |
2138 | struct btrfs_root *log; | ||
2139 | struct key; | ||
2140 | u64 start; | 2106 | u64 start; |
2141 | u64 end; | 2107 | u64 end; |
2142 | struct walk_control wc = { | 2108 | struct walk_control wc = { |
@@ -2144,10 +2110,6 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
2144 | .process_func = process_one_buffer | 2110 | .process_func = process_one_buffer |
2145 | }; | 2111 | }; |
2146 | 2112 | ||
2147 | if (!root->log_root || root->fs_info->log_root_recovering) | ||
2148 | return 0; | ||
2149 | |||
2150 | log = root->log_root; | ||
2151 | ret = walk_log_tree(trans, log, &wc); | 2113 | ret = walk_log_tree(trans, log, &wc); |
2152 | BUG_ON(ret); | 2114 | BUG_ON(ret); |
2153 | 2115 | ||
@@ -2161,14 +2123,30 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
2161 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); | 2123 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); |
2162 | } | 2124 | } |
2163 | 2125 | ||
2164 | if (log->log_transid > 0) { | ||
2165 | ret = btrfs_del_root(trans, root->fs_info->log_root_tree, | ||
2166 | &log->root_key); | ||
2167 | BUG_ON(ret); | ||
2168 | } | ||
2169 | root->log_root = NULL; | ||
2170 | free_extent_buffer(log->node); | 2126 | free_extent_buffer(log->node); |
2171 | kfree(log); | 2127 | kfree(log); |
2128 | } | ||
2129 | |||
2130 | /* | ||
2131 | * free all the extents used by the tree log. This should be called | ||
2132 | * at commit time of the full transaction | ||
2133 | */ | ||
2134 | int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | ||
2135 | { | ||
2136 | if (root->log_root) { | ||
2137 | free_log_tree(trans, root->log_root); | ||
2138 | root->log_root = NULL; | ||
2139 | } | ||
2140 | return 0; | ||
2141 | } | ||
2142 | |||
2143 | int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | ||
2144 | struct btrfs_fs_info *fs_info) | ||
2145 | { | ||
2146 | if (fs_info->log_root_tree) { | ||
2147 | free_log_tree(trans, fs_info->log_root_tree); | ||
2148 | fs_info->log_root_tree = NULL; | ||
2149 | } | ||
2172 | return 0; | 2150 | return 0; |
2173 | } | 2151 | } |
2174 | 2152 | ||
@@ -2202,6 +2180,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2202 | struct btrfs_dir_item *di; | 2180 | struct btrfs_dir_item *di; |
2203 | struct btrfs_path *path; | 2181 | struct btrfs_path *path; |
2204 | int ret; | 2182 | int ret; |
2183 | int err = 0; | ||
2205 | int bytes_del = 0; | 2184 | int bytes_del = 0; |
2206 | 2185 | ||
2207 | if (BTRFS_I(dir)->logged_trans < trans->transid) | 2186 | if (BTRFS_I(dir)->logged_trans < trans->transid) |
@@ -2217,7 +2196,11 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2217 | path = btrfs_alloc_path(); | 2196 | path = btrfs_alloc_path(); |
2218 | di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, | 2197 | di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, |
2219 | name, name_len, -1); | 2198 | name, name_len, -1); |
2220 | if (di && !IS_ERR(di)) { | 2199 | if (IS_ERR(di)) { |
2200 | err = PTR_ERR(di); | ||
2201 | goto fail; | ||
2202 | } | ||
2203 | if (di) { | ||
2221 | ret = btrfs_delete_one_dir_name(trans, log, path, di); | 2204 | ret = btrfs_delete_one_dir_name(trans, log, path, di); |
2222 | bytes_del += name_len; | 2205 | bytes_del += name_len; |
2223 | BUG_ON(ret); | 2206 | BUG_ON(ret); |
@@ -2225,7 +2208,11 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2225 | btrfs_release_path(log, path); | 2208 | btrfs_release_path(log, path); |
2226 | di = btrfs_lookup_dir_index_item(trans, log, path, dir->i_ino, | 2209 | di = btrfs_lookup_dir_index_item(trans, log, path, dir->i_ino, |
2227 | index, name, name_len, -1); | 2210 | index, name, name_len, -1); |
2228 | if (di && !IS_ERR(di)) { | 2211 | if (IS_ERR(di)) { |
2212 | err = PTR_ERR(di); | ||
2213 | goto fail; | ||
2214 | } | ||
2215 | if (di) { | ||
2229 | ret = btrfs_delete_one_dir_name(trans, log, path, di); | 2216 | ret = btrfs_delete_one_dir_name(trans, log, path, di); |
2230 | bytes_del += name_len; | 2217 | bytes_del += name_len; |
2231 | BUG_ON(ret); | 2218 | BUG_ON(ret); |
@@ -2243,6 +2230,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2243 | btrfs_release_path(log, path); | 2230 | btrfs_release_path(log, path); |
2244 | 2231 | ||
2245 | ret = btrfs_search_slot(trans, log, &key, path, 0, 1); | 2232 | ret = btrfs_search_slot(trans, log, &key, path, 0, 1); |
2233 | if (ret < 0) { | ||
2234 | err = ret; | ||
2235 | goto fail; | ||
2236 | } | ||
2246 | if (ret == 0) { | 2237 | if (ret == 0) { |
2247 | struct btrfs_inode_item *item; | 2238 | struct btrfs_inode_item *item; |
2248 | u64 i_size; | 2239 | u64 i_size; |
@@ -2260,12 +2251,16 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2260 | ret = 0; | 2251 | ret = 0; |
2261 | btrfs_release_path(log, path); | 2252 | btrfs_release_path(log, path); |
2262 | } | 2253 | } |
2263 | 2254 | fail: | |
2264 | btrfs_free_path(path); | 2255 | btrfs_free_path(path); |
2265 | mutex_unlock(&BTRFS_I(dir)->log_mutex); | 2256 | mutex_unlock(&BTRFS_I(dir)->log_mutex); |
2257 | if (ret == -ENOSPC) { | ||
2258 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
2259 | ret = 0; | ||
2260 | } | ||
2266 | btrfs_end_log_trans(root); | 2261 | btrfs_end_log_trans(root); |
2267 | 2262 | ||
2268 | return 0; | 2263 | return err; |
2269 | } | 2264 | } |
2270 | 2265 | ||
2271 | /* see comments for btrfs_del_dir_entries_in_log */ | 2266 | /* see comments for btrfs_del_dir_entries_in_log */ |
@@ -2290,6 +2285,10 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans, | |||
2290 | ret = btrfs_del_inode_ref(trans, log, name, name_len, inode->i_ino, | 2285 | ret = btrfs_del_inode_ref(trans, log, name, name_len, inode->i_ino, |
2291 | dirid, &index); | 2286 | dirid, &index); |
2292 | mutex_unlock(&BTRFS_I(inode)->log_mutex); | 2287 | mutex_unlock(&BTRFS_I(inode)->log_mutex); |
2288 | if (ret == -ENOSPC) { | ||
2289 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
2290 | ret = 0; | ||
2291 | } | ||
2293 | btrfs_end_log_trans(root); | 2292 | btrfs_end_log_trans(root); |
2294 | 2293 | ||
2295 | return ret; | 2294 | return ret; |
@@ -2317,7 +2316,8 @@ static noinline int insert_dir_log_key(struct btrfs_trans_handle *trans, | |||
2317 | else | 2316 | else |
2318 | key.type = BTRFS_DIR_LOG_INDEX_KEY; | 2317 | key.type = BTRFS_DIR_LOG_INDEX_KEY; |
2319 | ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*item)); | 2318 | ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*item)); |
2320 | BUG_ON(ret); | 2319 | if (ret) |
2320 | return ret; | ||
2321 | 2321 | ||
2322 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | 2322 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], |
2323 | struct btrfs_dir_log_item); | 2323 | struct btrfs_dir_log_item); |
@@ -2342,6 +2342,7 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
2342 | struct btrfs_key max_key; | 2342 | struct btrfs_key max_key; |
2343 | struct btrfs_root *log = root->log_root; | 2343 | struct btrfs_root *log = root->log_root; |
2344 | struct extent_buffer *src; | 2344 | struct extent_buffer *src; |
2345 | int err = 0; | ||
2345 | int ret; | 2346 | int ret; |
2346 | int i; | 2347 | int i; |
2347 | int nritems; | 2348 | int nritems; |
@@ -2404,6 +2405,10 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
2404 | ret = overwrite_item(trans, log, dst_path, | 2405 | ret = overwrite_item(trans, log, dst_path, |
2405 | path->nodes[0], path->slots[0], | 2406 | path->nodes[0], path->slots[0], |
2406 | &tmp); | 2407 | &tmp); |
2408 | if (ret) { | ||
2409 | err = ret; | ||
2410 | goto done; | ||
2411 | } | ||
2407 | } | 2412 | } |
2408 | } | 2413 | } |
2409 | btrfs_release_path(root, path); | 2414 | btrfs_release_path(root, path); |
@@ -2431,7 +2436,10 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
2431 | goto done; | 2436 | goto done; |
2432 | ret = overwrite_item(trans, log, dst_path, src, i, | 2437 | ret = overwrite_item(trans, log, dst_path, src, i, |
2433 | &min_key); | 2438 | &min_key); |
2434 | BUG_ON(ret); | 2439 | if (ret) { |
2440 | err = ret; | ||
2441 | goto done; | ||
2442 | } | ||
2435 | } | 2443 | } |
2436 | path->slots[0] = nritems; | 2444 | path->slots[0] = nritems; |
2437 | 2445 | ||
@@ -2453,22 +2461,30 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
2453 | ret = overwrite_item(trans, log, dst_path, | 2461 | ret = overwrite_item(trans, log, dst_path, |
2454 | path->nodes[0], path->slots[0], | 2462 | path->nodes[0], path->slots[0], |
2455 | &tmp); | 2463 | &tmp); |
2456 | 2464 | if (ret) | |
2457 | BUG_ON(ret); | 2465 | err = ret; |
2458 | last_offset = tmp.offset; | 2466 | else |
2467 | last_offset = tmp.offset; | ||
2459 | goto done; | 2468 | goto done; |
2460 | } | 2469 | } |
2461 | } | 2470 | } |
2462 | done: | 2471 | done: |
2463 | *last_offset_ret = last_offset; | ||
2464 | btrfs_release_path(root, path); | 2472 | btrfs_release_path(root, path); |
2465 | btrfs_release_path(log, dst_path); | 2473 | btrfs_release_path(log, dst_path); |
2466 | 2474 | ||
2467 | /* insert the log range keys to indicate where the log is valid */ | 2475 | if (err == 0) { |
2468 | ret = insert_dir_log_key(trans, log, path, key_type, inode->i_ino, | 2476 | *last_offset_ret = last_offset; |
2469 | first_offset, last_offset); | 2477 | /* |
2470 | BUG_ON(ret); | 2478 | * insert the log range keys to indicate where the log |
2471 | return 0; | 2479 | * is valid |
2480 | */ | ||
2481 | ret = insert_dir_log_key(trans, log, path, key_type, | ||
2482 | inode->i_ino, first_offset, | ||
2483 | last_offset); | ||
2484 | if (ret) | ||
2485 | err = ret; | ||
2486 | } | ||
2487 | return err; | ||
2472 | } | 2488 | } |
2473 | 2489 | ||
2474 | /* | 2490 | /* |
@@ -2500,7 +2516,8 @@ again: | |||
2500 | ret = log_dir_items(trans, root, inode, path, | 2516 | ret = log_dir_items(trans, root, inode, path, |
2501 | dst_path, key_type, min_key, | 2517 | dst_path, key_type, min_key, |
2502 | &max_key); | 2518 | &max_key); |
2503 | BUG_ON(ret); | 2519 | if (ret) |
2520 | return ret; | ||
2504 | if (max_key == (u64)-1) | 2521 | if (max_key == (u64)-1) |
2505 | break; | 2522 | break; |
2506 | min_key = max_key + 1; | 2523 | min_key = max_key + 1; |
@@ -2534,8 +2551,8 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, | |||
2534 | 2551 | ||
2535 | while (1) { | 2552 | while (1) { |
2536 | ret = btrfs_search_slot(trans, log, &key, path, -1, 1); | 2553 | ret = btrfs_search_slot(trans, log, &key, path, -1, 1); |
2537 | 2554 | BUG_ON(ret == 0); | |
2538 | if (ret != 1) | 2555 | if (ret < 0) |
2539 | break; | 2556 | break; |
2540 | 2557 | ||
2541 | if (path->slots[0] == 0) | 2558 | if (path->slots[0] == 0) |
@@ -2553,7 +2570,7 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, | |||
2553 | btrfs_release_path(log, path); | 2570 | btrfs_release_path(log, path); |
2554 | } | 2571 | } |
2555 | btrfs_release_path(log, path); | 2572 | btrfs_release_path(log, path); |
2556 | return 0; | 2573 | return ret; |
2557 | } | 2574 | } |
2558 | 2575 | ||
2559 | static noinline int copy_items(struct btrfs_trans_handle *trans, | 2576 | static noinline int copy_items(struct btrfs_trans_handle *trans, |
@@ -2586,7 +2603,10 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
2586 | } | 2603 | } |
2587 | ret = btrfs_insert_empty_items(trans, log, dst_path, | 2604 | ret = btrfs_insert_empty_items(trans, log, dst_path, |
2588 | ins_keys, ins_sizes, nr); | 2605 | ins_keys, ins_sizes, nr); |
2589 | BUG_ON(ret); | 2606 | if (ret) { |
2607 | kfree(ins_data); | ||
2608 | return ret; | ||
2609 | } | ||
2590 | 2610 | ||
2591 | for (i = 0; i < nr; i++, dst_path->slots[0]++) { | 2611 | for (i = 0; i < nr; i++, dst_path->slots[0]++) { |
2592 | dst_offset = btrfs_item_ptr_offset(dst_path->nodes[0], | 2612 | dst_offset = btrfs_item_ptr_offset(dst_path->nodes[0], |
@@ -2659,16 +2679,17 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
2659 | * we have to do this after the loop above to avoid changing the | 2679 | * we have to do this after the loop above to avoid changing the |
2660 | * log tree while trying to change the log tree. | 2680 | * log tree while trying to change the log tree. |
2661 | */ | 2681 | */ |
2682 | ret = 0; | ||
2662 | while (!list_empty(&ordered_sums)) { | 2683 | while (!list_empty(&ordered_sums)) { |
2663 | struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next, | 2684 | struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next, |
2664 | struct btrfs_ordered_sum, | 2685 | struct btrfs_ordered_sum, |
2665 | list); | 2686 | list); |
2666 | ret = btrfs_csum_file_blocks(trans, log, sums); | 2687 | if (!ret) |
2667 | BUG_ON(ret); | 2688 | ret = btrfs_csum_file_blocks(trans, log, sums); |
2668 | list_del(&sums->list); | 2689 | list_del(&sums->list); |
2669 | kfree(sums); | 2690 | kfree(sums); |
2670 | } | 2691 | } |
2671 | return 0; | 2692 | return ret; |
2672 | } | 2693 | } |
2673 | 2694 | ||
2674 | /* log a single inode in the tree log. | 2695 | /* log a single inode in the tree log. |
@@ -2695,7 +2716,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
2695 | struct btrfs_key max_key; | 2716 | struct btrfs_key max_key; |
2696 | struct btrfs_root *log = root->log_root; | 2717 | struct btrfs_root *log = root->log_root; |
2697 | struct extent_buffer *src = NULL; | 2718 | struct extent_buffer *src = NULL; |
2698 | u32 size; | 2719 | int err = 0; |
2699 | int ret; | 2720 | int ret; |
2700 | int nritems; | 2721 | int nritems; |
2701 | int ins_start_slot = 0; | 2722 | int ins_start_slot = 0; |
@@ -2738,7 +2759,10 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
2738 | } else { | 2759 | } else { |
2739 | ret = btrfs_truncate_inode_items(trans, log, inode, 0, 0); | 2760 | ret = btrfs_truncate_inode_items(trans, log, inode, 0, 0); |
2740 | } | 2761 | } |
2741 | BUG_ON(ret); | 2762 | if (ret) { |
2763 | err = ret; | ||
2764 | goto out_unlock; | ||
2765 | } | ||
2742 | path->keep_locks = 1; | 2766 | path->keep_locks = 1; |
2743 | 2767 | ||
2744 | while (1) { | 2768 | while (1) { |
@@ -2755,7 +2779,6 @@ again: | |||
2755 | break; | 2779 | break; |
2756 | 2780 | ||
2757 | src = path->nodes[0]; | 2781 | src = path->nodes[0]; |
2758 | size = btrfs_item_size_nr(src, path->slots[0]); | ||
2759 | if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) { | 2782 | if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) { |
2760 | ins_nr++; | 2783 | ins_nr++; |
2761 | goto next_slot; | 2784 | goto next_slot; |
@@ -2767,7 +2790,10 @@ again: | |||
2767 | 2790 | ||
2768 | ret = copy_items(trans, log, dst_path, src, ins_start_slot, | 2791 | ret = copy_items(trans, log, dst_path, src, ins_start_slot, |
2769 | ins_nr, inode_only); | 2792 | ins_nr, inode_only); |
2770 | BUG_ON(ret); | 2793 | if (ret) { |
2794 | err = ret; | ||
2795 | goto out_unlock; | ||
2796 | } | ||
2771 | ins_nr = 1; | 2797 | ins_nr = 1; |
2772 | ins_start_slot = path->slots[0]; | 2798 | ins_start_slot = path->slots[0]; |
2773 | next_slot: | 2799 | next_slot: |
@@ -2783,7 +2809,10 @@ next_slot: | |||
2783 | ret = copy_items(trans, log, dst_path, src, | 2809 | ret = copy_items(trans, log, dst_path, src, |
2784 | ins_start_slot, | 2810 | ins_start_slot, |
2785 | ins_nr, inode_only); | 2811 | ins_nr, inode_only); |
2786 | BUG_ON(ret); | 2812 | if (ret) { |
2813 | err = ret; | ||
2814 | goto out_unlock; | ||
2815 | } | ||
2787 | ins_nr = 0; | 2816 | ins_nr = 0; |
2788 | } | 2817 | } |
2789 | btrfs_release_path(root, path); | 2818 | btrfs_release_path(root, path); |
@@ -2801,7 +2830,10 @@ next_slot: | |||
2801 | ret = copy_items(trans, log, dst_path, src, | 2830 | ret = copy_items(trans, log, dst_path, src, |
2802 | ins_start_slot, | 2831 | ins_start_slot, |
2803 | ins_nr, inode_only); | 2832 | ins_nr, inode_only); |
2804 | BUG_ON(ret); | 2833 | if (ret) { |
2834 | err = ret; | ||
2835 | goto out_unlock; | ||
2836 | } | ||
2805 | ins_nr = 0; | 2837 | ins_nr = 0; |
2806 | } | 2838 | } |
2807 | WARN_ON(ins_nr); | 2839 | WARN_ON(ins_nr); |
@@ -2809,14 +2841,18 @@ next_slot: | |||
2809 | btrfs_release_path(root, path); | 2841 | btrfs_release_path(root, path); |
2810 | btrfs_release_path(log, dst_path); | 2842 | btrfs_release_path(log, dst_path); |
2811 | ret = log_directory_changes(trans, root, inode, path, dst_path); | 2843 | ret = log_directory_changes(trans, root, inode, path, dst_path); |
2812 | BUG_ON(ret); | 2844 | if (ret) { |
2845 | err = ret; | ||
2846 | goto out_unlock; | ||
2847 | } | ||
2813 | } | 2848 | } |
2814 | BTRFS_I(inode)->logged_trans = trans->transid; | 2849 | BTRFS_I(inode)->logged_trans = trans->transid; |
2850 | out_unlock: | ||
2815 | mutex_unlock(&BTRFS_I(inode)->log_mutex); | 2851 | mutex_unlock(&BTRFS_I(inode)->log_mutex); |
2816 | 2852 | ||
2817 | btrfs_free_path(path); | 2853 | btrfs_free_path(path); |
2818 | btrfs_free_path(dst_path); | 2854 | btrfs_free_path(dst_path); |
2819 | return 0; | 2855 | return err; |
2820 | } | 2856 | } |
2821 | 2857 | ||
2822 | /* | 2858 | /* |
@@ -2833,6 +2869,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, | |||
2833 | { | 2869 | { |
2834 | int ret = 0; | 2870 | int ret = 0; |
2835 | struct btrfs_root *root; | 2871 | struct btrfs_root *root; |
2872 | struct dentry *old_parent = NULL; | ||
2836 | 2873 | ||
2837 | /* | 2874 | /* |
2838 | * for regular files, if its inode is already on disk, we don't | 2875 | * for regular files, if its inode is already on disk, we don't |
@@ -2874,10 +2911,13 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, | |||
2874 | if (IS_ROOT(parent)) | 2911 | if (IS_ROOT(parent)) |
2875 | break; | 2912 | break; |
2876 | 2913 | ||
2877 | parent = parent->d_parent; | 2914 | parent = dget_parent(parent); |
2915 | dput(old_parent); | ||
2916 | old_parent = parent; | ||
2878 | inode = parent->d_inode; | 2917 | inode = parent->d_inode; |
2879 | 2918 | ||
2880 | } | 2919 | } |
2920 | dput(old_parent); | ||
2881 | out: | 2921 | out: |
2882 | return ret; | 2922 | return ret; |
2883 | } | 2923 | } |
@@ -2909,6 +2949,7 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
2909 | { | 2949 | { |
2910 | int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; | 2950 | int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; |
2911 | struct super_block *sb; | 2951 | struct super_block *sb; |
2952 | struct dentry *old_parent = NULL; | ||
2912 | int ret = 0; | 2953 | int ret = 0; |
2913 | u64 last_committed = root->fs_info->last_trans_committed; | 2954 | u64 last_committed = root->fs_info->last_trans_committed; |
2914 | 2955 | ||
@@ -2941,10 +2982,13 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
2941 | goto end_no_trans; | 2982 | goto end_no_trans; |
2942 | } | 2983 | } |
2943 | 2984 | ||
2944 | start_log_trans(trans, root); | 2985 | ret = start_log_trans(trans, root); |
2986 | if (ret) | ||
2987 | goto end_trans; | ||
2945 | 2988 | ||
2946 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 2989 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
2947 | BUG_ON(ret); | 2990 | if (ret) |
2991 | goto end_trans; | ||
2948 | 2992 | ||
2949 | /* | 2993 | /* |
2950 | * for regular files, if its inode is already on disk, we don't | 2994 | * for regular files, if its inode is already on disk, we don't |
@@ -2954,8 +2998,10 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
2954 | */ | 2998 | */ |
2955 | if (S_ISREG(inode->i_mode) && | 2999 | if (S_ISREG(inode->i_mode) && |
2956 | BTRFS_I(inode)->generation <= last_committed && | 3000 | BTRFS_I(inode)->generation <= last_committed && |
2957 | BTRFS_I(inode)->last_unlink_trans <= last_committed) | 3001 | BTRFS_I(inode)->last_unlink_trans <= last_committed) { |
2958 | goto no_parent; | 3002 | ret = 0; |
3003 | goto end_trans; | ||
3004 | } | ||
2959 | 3005 | ||
2960 | inode_only = LOG_INODE_EXISTS; | 3006 | inode_only = LOG_INODE_EXISTS; |
2961 | while (1) { | 3007 | while (1) { |
@@ -2969,15 +3015,24 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
2969 | if (BTRFS_I(inode)->generation > | 3015 | if (BTRFS_I(inode)->generation > |
2970 | root->fs_info->last_trans_committed) { | 3016 | root->fs_info->last_trans_committed) { |
2971 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 3017 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
2972 | BUG_ON(ret); | 3018 | if (ret) |
3019 | goto end_trans; | ||
2973 | } | 3020 | } |
2974 | if (IS_ROOT(parent)) | 3021 | if (IS_ROOT(parent)) |
2975 | break; | 3022 | break; |
2976 | 3023 | ||
2977 | parent = parent->d_parent; | 3024 | parent = dget_parent(parent); |
3025 | dput(old_parent); | ||
3026 | old_parent = parent; | ||
2978 | } | 3027 | } |
2979 | no_parent: | ||
2980 | ret = 0; | 3028 | ret = 0; |
3029 | end_trans: | ||
3030 | dput(old_parent); | ||
3031 | if (ret < 0) { | ||
3032 | BUG_ON(ret != -ENOSPC); | ||
3033 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
3034 | ret = 1; | ||
3035 | } | ||
2981 | btrfs_end_log_trans(root); | 3036 | btrfs_end_log_trans(root); |
2982 | end_no_trans: | 3037 | end_no_trans: |
2983 | return ret; | 3038 | return ret; |
@@ -2992,8 +3047,13 @@ end_no_trans: | |||
2992 | int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans, | 3047 | int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans, |
2993 | struct btrfs_root *root, struct dentry *dentry) | 3048 | struct btrfs_root *root, struct dentry *dentry) |
2994 | { | 3049 | { |
2995 | return btrfs_log_inode_parent(trans, root, dentry->d_inode, | 3050 | struct dentry *parent = dget_parent(dentry); |
2996 | dentry->d_parent, 0); | 3051 | int ret; |
3052 | |||
3053 | ret = btrfs_log_inode_parent(trans, root, dentry->d_inode, parent, 0); | ||
3054 | dput(parent); | ||
3055 | |||
3056 | return ret; | ||
2997 | } | 3057 | } |
2998 | 3058 | ||
2999 | /* | 3059 | /* |
@@ -3019,7 +3079,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) | |||
3019 | path = btrfs_alloc_path(); | 3079 | path = btrfs_alloc_path(); |
3020 | BUG_ON(!path); | 3080 | BUG_ON(!path); |
3021 | 3081 | ||
3022 | trans = btrfs_start_transaction(fs_info->tree_root, 1); | 3082 | trans = btrfs_start_transaction(fs_info->tree_root, 0); |
3023 | 3083 | ||
3024 | wc.trans = trans; | 3084 | wc.trans = trans; |
3025 | wc.pin = 1; | 3085 | wc.pin = 1; |