diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-06 13:13:54 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-06 13:13:54 -0400 |
| commit | 11e4afb49b7fa1fc8e1ffd850c1806dd86a08204 (patch) | |
| tree | 9e57efcb106ae912f7bec718feb3f8ec607559bb /fs/btrfs/tree-log.c | |
| parent | 162500b3a3ff39d941d29db49b41a16667ae44f0 (diff) | |
| parent | 9b2a606d3898fcb2eedb6faded3bb37549590ac4 (diff) | |
Merge branches 'gemini' and 'misc' into devel
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 242 |
1 files changed, 152 insertions, 90 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1255fcc8ade5..fb102a9aee9c 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]); |
| @@ -1698,9 +1702,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
| 1698 | 1702 | ||
| 1699 | next = btrfs_find_create_tree_block(root, bytenr, blocksize); | 1703 | next = btrfs_find_create_tree_block(root, bytenr, blocksize); |
| 1700 | 1704 | ||
| 1701 | wc->process_func(root, next, wc, ptr_gen); | ||
| 1702 | |||
| 1703 | if (*level == 1) { | 1705 | if (*level == 1) { |
| 1706 | wc->process_func(root, next, wc, ptr_gen); | ||
| 1707 | |||
| 1704 | path->slots[*level]++; | 1708 | path->slots[*level]++; |
| 1705 | if (wc->free) { | 1709 | if (wc->free) { |
| 1706 | btrfs_read_buffer(next, ptr_gen); | 1710 | btrfs_read_buffer(next, ptr_gen); |
| @@ -1733,35 +1737,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
| 1733 | WARN_ON(*level < 0); | 1737 | WARN_ON(*level < 0); |
| 1734 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 1738 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
| 1735 | 1739 | ||
| 1736 | if (path->nodes[*level] == root->node) | 1740 | 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 | 1741 | ||
| 1766 | cond_resched(); | 1742 | cond_resched(); |
| 1767 | return 0; | 1743 | return 0; |
| @@ -1780,7 +1756,7 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, | |||
| 1780 | 1756 | ||
| 1781 | for (i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 1757 | for (i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
| 1782 | slot = path->slots[i]; | 1758 | slot = path->slots[i]; |
| 1783 | if (slot < btrfs_header_nritems(path->nodes[i]) - 1) { | 1759 | if (slot + 1 < btrfs_header_nritems(path->nodes[i])) { |
| 1784 | struct extent_buffer *node; | 1760 | struct extent_buffer *node; |
| 1785 | node = path->nodes[i]; | 1761 | node = path->nodes[i]; |
| 1786 | path->slots[i]++; | 1762 | path->slots[i]++; |
| @@ -2046,7 +2022,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2046 | mutex_unlock(&log_root_tree->log_mutex); | 2022 | mutex_unlock(&log_root_tree->log_mutex); |
| 2047 | 2023 | ||
| 2048 | ret = update_log_root(trans, log); | 2024 | ret = update_log_root(trans, log); |
| 2049 | BUG_ON(ret); | ||
| 2050 | 2025 | ||
| 2051 | mutex_lock(&log_root_tree->log_mutex); | 2026 | mutex_lock(&log_root_tree->log_mutex); |
| 2052 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { | 2027 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { |
| @@ -2055,6 +2030,15 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2055 | wake_up(&log_root_tree->log_writer_wait); | 2030 | wake_up(&log_root_tree->log_writer_wait); |
| 2056 | } | 2031 | } |
| 2057 | 2032 | ||
| 2033 | if (ret) { | ||
| 2034 | BUG_ON(ret != -ENOSPC); | ||
| 2035 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
| 2036 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | ||
| 2037 | mutex_unlock(&log_root_tree->log_mutex); | ||
| 2038 | ret = -EAGAIN; | ||
| 2039 | goto out; | ||
| 2040 | } | ||
| 2041 | |||
| 2058 | index2 = log_root_tree->log_transid % 2; | 2042 | index2 = log_root_tree->log_transid % 2; |
| 2059 | if (atomic_read(&log_root_tree->log_commit[index2])) { | 2043 | if (atomic_read(&log_root_tree->log_commit[index2])) { |
| 2060 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2044 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
| @@ -2128,15 +2112,10 @@ out: | |||
| 2128 | return 0; | 2112 | return 0; |
| 2129 | } | 2113 | } |
| 2130 | 2114 | ||
| 2131 | /* | 2115 | static void free_log_tree(struct btrfs_trans_handle *trans, |
| 2132 | * free all the extents used by the tree log. This should be called | 2116 | 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 | { | 2117 | { |
| 2137 | int ret; | 2118 | int ret; |
| 2138 | struct btrfs_root *log; | ||
| 2139 | struct key; | ||
| 2140 | u64 start; | 2119 | u64 start; |
| 2141 | u64 end; | 2120 | u64 end; |
| 2142 | struct walk_control wc = { | 2121 | struct walk_control wc = { |
| @@ -2144,10 +2123,6 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
| 2144 | .process_func = process_one_buffer | 2123 | .process_func = process_one_buffer |
| 2145 | }; | 2124 | }; |
| 2146 | 2125 | ||
| 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); | 2126 | ret = walk_log_tree(trans, log, &wc); |
| 2152 | BUG_ON(ret); | 2127 | BUG_ON(ret); |
| 2153 | 2128 | ||
| @@ -2161,14 +2136,30 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
| 2161 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); | 2136 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); |
| 2162 | } | 2137 | } |
| 2163 | 2138 | ||
| 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); | 2139 | free_extent_buffer(log->node); |
| 2171 | kfree(log); | 2140 | kfree(log); |
| 2141 | } | ||
| 2142 | |||
| 2143 | /* | ||
| 2144 | * free all the extents used by the tree log. This should be called | ||
| 2145 | * at commit time of the full transaction | ||
| 2146 | */ | ||
| 2147 | int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | ||
| 2148 | { | ||
| 2149 | if (root->log_root) { | ||
| 2150 | free_log_tree(trans, root->log_root); | ||
| 2151 | root->log_root = NULL; | ||
| 2152 | } | ||
| 2153 | return 0; | ||
| 2154 | } | ||
| 2155 | |||
| 2156 | int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | ||
| 2157 | struct btrfs_fs_info *fs_info) | ||
| 2158 | { | ||
| 2159 | if (fs_info->log_root_tree) { | ||
| 2160 | free_log_tree(trans, fs_info->log_root_tree); | ||
| 2161 | fs_info->log_root_tree = NULL; | ||
| 2162 | } | ||
| 2172 | return 0; | 2163 | return 0; |
| 2173 | } | 2164 | } |
| 2174 | 2165 | ||
| @@ -2202,6 +2193,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
| 2202 | struct btrfs_dir_item *di; | 2193 | struct btrfs_dir_item *di; |
| 2203 | struct btrfs_path *path; | 2194 | struct btrfs_path *path; |
| 2204 | int ret; | 2195 | int ret; |
| 2196 | int err = 0; | ||
| 2205 | int bytes_del = 0; | 2197 | int bytes_del = 0; |
| 2206 | 2198 | ||
| 2207 | if (BTRFS_I(dir)->logged_trans < trans->transid) | 2199 | if (BTRFS_I(dir)->logged_trans < trans->transid) |
| @@ -2217,7 +2209,11 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
| 2217 | path = btrfs_alloc_path(); | 2209 | path = btrfs_alloc_path(); |
| 2218 | di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, | 2210 | di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, |
| 2219 | name, name_len, -1); | 2211 | name, name_len, -1); |
| 2220 | if (di && !IS_ERR(di)) { | 2212 | if (IS_ERR(di)) { |
| 2213 | err = PTR_ERR(di); | ||
| 2214 | goto fail; | ||
| 2215 | } | ||
| 2216 | if (di) { | ||
| 2221 | ret = btrfs_delete_one_dir_name(trans, log, path, di); | 2217 | ret = btrfs_delete_one_dir_name(trans, log, path, di); |
| 2222 | bytes_del += name_len; | 2218 | bytes_del += name_len; |
| 2223 | BUG_ON(ret); | 2219 | BUG_ON(ret); |
| @@ -2225,7 +2221,11 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
| 2225 | btrfs_release_path(log, path); | 2221 | btrfs_release_path(log, path); |
| 2226 | di = btrfs_lookup_dir_index_item(trans, log, path, dir->i_ino, | 2222 | di = btrfs_lookup_dir_index_item(trans, log, path, dir->i_ino, |
| 2227 | index, name, name_len, -1); | 2223 | index, name, name_len, -1); |
| 2228 | if (di && !IS_ERR(di)) { | 2224 | if (IS_ERR(di)) { |
| 2225 | err = PTR_ERR(di); | ||
| 2226 | goto fail; | ||
| 2227 | } | ||
| 2228 | if (di) { | ||
| 2229 | ret = btrfs_delete_one_dir_name(trans, log, path, di); | 2229 | ret = btrfs_delete_one_dir_name(trans, log, path, di); |
| 2230 | bytes_del += name_len; | 2230 | bytes_del += name_len; |
| 2231 | BUG_ON(ret); | 2231 | BUG_ON(ret); |
| @@ -2243,6 +2243,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
| 2243 | btrfs_release_path(log, path); | 2243 | btrfs_release_path(log, path); |
| 2244 | 2244 | ||
| 2245 | ret = btrfs_search_slot(trans, log, &key, path, 0, 1); | 2245 | ret = btrfs_search_slot(trans, log, &key, path, 0, 1); |
| 2246 | if (ret < 0) { | ||
| 2247 | err = ret; | ||
| 2248 | goto fail; | ||
| 2249 | } | ||
| 2246 | if (ret == 0) { | 2250 | if (ret == 0) { |
| 2247 | struct btrfs_inode_item *item; | 2251 | struct btrfs_inode_item *item; |
| 2248 | u64 i_size; | 2252 | u64 i_size; |
| @@ -2260,9 +2264,13 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
| 2260 | ret = 0; | 2264 | ret = 0; |
| 2261 | btrfs_release_path(log, path); | 2265 | btrfs_release_path(log, path); |
| 2262 | } | 2266 | } |
| 2263 | 2267 | fail: | |
| 2264 | btrfs_free_path(path); | 2268 | btrfs_free_path(path); |
| 2265 | mutex_unlock(&BTRFS_I(dir)->log_mutex); | 2269 | mutex_unlock(&BTRFS_I(dir)->log_mutex); |
| 2270 | if (ret == -ENOSPC) { | ||
| 2271 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
| 2272 | ret = 0; | ||
| 2273 | } | ||
| 2266 | btrfs_end_log_trans(root); | 2274 | btrfs_end_log_trans(root); |
| 2267 | 2275 | ||
| 2268 | return 0; | 2276 | return 0; |
| @@ -2290,6 +2298,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, | 2298 | ret = btrfs_del_inode_ref(trans, log, name, name_len, inode->i_ino, |
| 2291 | dirid, &index); | 2299 | dirid, &index); |
| 2292 | mutex_unlock(&BTRFS_I(inode)->log_mutex); | 2300 | mutex_unlock(&BTRFS_I(inode)->log_mutex); |
| 2301 | if (ret == -ENOSPC) { | ||
| 2302 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
| 2303 | ret = 0; | ||
| 2304 | } | ||
| 2293 | btrfs_end_log_trans(root); | 2305 | btrfs_end_log_trans(root); |
| 2294 | 2306 | ||
| 2295 | return ret; | 2307 | return ret; |
| @@ -2317,7 +2329,8 @@ static noinline int insert_dir_log_key(struct btrfs_trans_handle *trans, | |||
| 2317 | else | 2329 | else |
| 2318 | key.type = BTRFS_DIR_LOG_INDEX_KEY; | 2330 | key.type = BTRFS_DIR_LOG_INDEX_KEY; |
| 2319 | ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*item)); | 2331 | ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*item)); |
| 2320 | BUG_ON(ret); | 2332 | if (ret) |
| 2333 | return ret; | ||
| 2321 | 2334 | ||
| 2322 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | 2335 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| 2323 | struct btrfs_dir_log_item); | 2336 | struct btrfs_dir_log_item); |
| @@ -2342,6 +2355,7 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
| 2342 | struct btrfs_key max_key; | 2355 | struct btrfs_key max_key; |
| 2343 | struct btrfs_root *log = root->log_root; | 2356 | struct btrfs_root *log = root->log_root; |
| 2344 | struct extent_buffer *src; | 2357 | struct extent_buffer *src; |
| 2358 | int err = 0; | ||
| 2345 | int ret; | 2359 | int ret; |
| 2346 | int i; | 2360 | int i; |
| 2347 | int nritems; | 2361 | int nritems; |
| @@ -2404,6 +2418,10 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
| 2404 | ret = overwrite_item(trans, log, dst_path, | 2418 | ret = overwrite_item(trans, log, dst_path, |
| 2405 | path->nodes[0], path->slots[0], | 2419 | path->nodes[0], path->slots[0], |
| 2406 | &tmp); | 2420 | &tmp); |
| 2421 | if (ret) { | ||
| 2422 | err = ret; | ||
| 2423 | goto done; | ||
| 2424 | } | ||
| 2407 | } | 2425 | } |
| 2408 | } | 2426 | } |
| 2409 | btrfs_release_path(root, path); | 2427 | btrfs_release_path(root, path); |
| @@ -2431,7 +2449,10 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
| 2431 | goto done; | 2449 | goto done; |
| 2432 | ret = overwrite_item(trans, log, dst_path, src, i, | 2450 | ret = overwrite_item(trans, log, dst_path, src, i, |
| 2433 | &min_key); | 2451 | &min_key); |
| 2434 | BUG_ON(ret); | 2452 | if (ret) { |
| 2453 | err = ret; | ||
| 2454 | goto done; | ||
| 2455 | } | ||
| 2435 | } | 2456 | } |
| 2436 | path->slots[0] = nritems; | 2457 | path->slots[0] = nritems; |
| 2437 | 2458 | ||
| @@ -2453,22 +2474,30 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans, | |||
| 2453 | ret = overwrite_item(trans, log, dst_path, | 2474 | ret = overwrite_item(trans, log, dst_path, |
| 2454 | path->nodes[0], path->slots[0], | 2475 | path->nodes[0], path->slots[0], |
| 2455 | &tmp); | 2476 | &tmp); |
| 2456 | 2477 | if (ret) | |
| 2457 | BUG_ON(ret); | 2478 | err = ret; |
| 2458 | last_offset = tmp.offset; | 2479 | else |
| 2480 | last_offset = tmp.offset; | ||
| 2459 | goto done; | 2481 | goto done; |
| 2460 | } | 2482 | } |
| 2461 | } | 2483 | } |
| 2462 | done: | 2484 | done: |
| 2463 | *last_offset_ret = last_offset; | ||
| 2464 | btrfs_release_path(root, path); | 2485 | btrfs_release_path(root, path); |
| 2465 | btrfs_release_path(log, dst_path); | 2486 | btrfs_release_path(log, dst_path); |
| 2466 | 2487 | ||
| 2467 | /* insert the log range keys to indicate where the log is valid */ | 2488 | if (err == 0) { |
| 2468 | ret = insert_dir_log_key(trans, log, path, key_type, inode->i_ino, | 2489 | *last_offset_ret = last_offset; |
| 2469 | first_offset, last_offset); | 2490 | /* |
| 2470 | BUG_ON(ret); | 2491 | * insert the log range keys to indicate where the log |
| 2471 | return 0; | 2492 | * is valid |
| 2493 | */ | ||
| 2494 | ret = insert_dir_log_key(trans, log, path, key_type, | ||
| 2495 | inode->i_ino, first_offset, | ||
| 2496 | last_offset); | ||
| 2497 | if (ret) | ||
| 2498 | err = ret; | ||
| 2499 | } | ||
| 2500 | return err; | ||
| 2472 | } | 2501 | } |
| 2473 | 2502 | ||
| 2474 | /* | 2503 | /* |
| @@ -2500,7 +2529,8 @@ again: | |||
| 2500 | ret = log_dir_items(trans, root, inode, path, | 2529 | ret = log_dir_items(trans, root, inode, path, |
| 2501 | dst_path, key_type, min_key, | 2530 | dst_path, key_type, min_key, |
| 2502 | &max_key); | 2531 | &max_key); |
| 2503 | BUG_ON(ret); | 2532 | if (ret) |
| 2533 | return ret; | ||
| 2504 | if (max_key == (u64)-1) | 2534 | if (max_key == (u64)-1) |
| 2505 | break; | 2535 | break; |
| 2506 | min_key = max_key + 1; | 2536 | min_key = max_key + 1; |
| @@ -2534,8 +2564,8 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, | |||
| 2534 | 2564 | ||
| 2535 | while (1) { | 2565 | while (1) { |
| 2536 | ret = btrfs_search_slot(trans, log, &key, path, -1, 1); | 2566 | ret = btrfs_search_slot(trans, log, &key, path, -1, 1); |
| 2537 | 2567 | BUG_ON(ret == 0); | |
| 2538 | if (ret != 1) | 2568 | if (ret < 0) |
| 2539 | break; | 2569 | break; |
| 2540 | 2570 | ||
| 2541 | if (path->slots[0] == 0) | 2571 | if (path->slots[0] == 0) |
| @@ -2553,7 +2583,7 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, | |||
| 2553 | btrfs_release_path(log, path); | 2583 | btrfs_release_path(log, path); |
| 2554 | } | 2584 | } |
| 2555 | btrfs_release_path(log, path); | 2585 | btrfs_release_path(log, path); |
| 2556 | return 0; | 2586 | return ret; |
| 2557 | } | 2587 | } |
| 2558 | 2588 | ||
| 2559 | static noinline int copy_items(struct btrfs_trans_handle *trans, | 2589 | static noinline int copy_items(struct btrfs_trans_handle *trans, |
| @@ -2586,7 +2616,10 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
| 2586 | } | 2616 | } |
| 2587 | ret = btrfs_insert_empty_items(trans, log, dst_path, | 2617 | ret = btrfs_insert_empty_items(trans, log, dst_path, |
| 2588 | ins_keys, ins_sizes, nr); | 2618 | ins_keys, ins_sizes, nr); |
| 2589 | BUG_ON(ret); | 2619 | if (ret) { |
| 2620 | kfree(ins_data); | ||
| 2621 | return ret; | ||
| 2622 | } | ||
| 2590 | 2623 | ||
| 2591 | for (i = 0; i < nr; i++, dst_path->slots[0]++) { | 2624 | for (i = 0; i < nr; i++, dst_path->slots[0]++) { |
| 2592 | dst_offset = btrfs_item_ptr_offset(dst_path->nodes[0], | 2625 | dst_offset = btrfs_item_ptr_offset(dst_path->nodes[0], |
| @@ -2659,16 +2692,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 | 2692 | * we have to do this after the loop above to avoid changing the |
| 2660 | * log tree while trying to change the log tree. | 2693 | * log tree while trying to change the log tree. |
| 2661 | */ | 2694 | */ |
| 2695 | ret = 0; | ||
| 2662 | while (!list_empty(&ordered_sums)) { | 2696 | while (!list_empty(&ordered_sums)) { |
| 2663 | struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next, | 2697 | struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next, |
| 2664 | struct btrfs_ordered_sum, | 2698 | struct btrfs_ordered_sum, |
| 2665 | list); | 2699 | list); |
| 2666 | ret = btrfs_csum_file_blocks(trans, log, sums); | 2700 | if (!ret) |
| 2667 | BUG_ON(ret); | 2701 | ret = btrfs_csum_file_blocks(trans, log, sums); |
| 2668 | list_del(&sums->list); | 2702 | list_del(&sums->list); |
| 2669 | kfree(sums); | 2703 | kfree(sums); |
| 2670 | } | 2704 | } |
| 2671 | return 0; | 2705 | return ret; |
| 2672 | } | 2706 | } |
| 2673 | 2707 | ||
| 2674 | /* log a single inode in the tree log. | 2708 | /* log a single inode in the tree log. |
| @@ -2696,6 +2730,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
| 2696 | struct btrfs_root *log = root->log_root; | 2730 | struct btrfs_root *log = root->log_root; |
| 2697 | struct extent_buffer *src = NULL; | 2731 | struct extent_buffer *src = NULL; |
| 2698 | u32 size; | 2732 | u32 size; |
| 2733 | int err = 0; | ||
| 2699 | int ret; | 2734 | int ret; |
| 2700 | int nritems; | 2735 | int nritems; |
| 2701 | int ins_start_slot = 0; | 2736 | int ins_start_slot = 0; |
| @@ -2738,7 +2773,10 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
| 2738 | } else { | 2773 | } else { |
| 2739 | ret = btrfs_truncate_inode_items(trans, log, inode, 0, 0); | 2774 | ret = btrfs_truncate_inode_items(trans, log, inode, 0, 0); |
| 2740 | } | 2775 | } |
| 2741 | BUG_ON(ret); | 2776 | if (ret) { |
| 2777 | err = ret; | ||
| 2778 | goto out_unlock; | ||
| 2779 | } | ||
| 2742 | path->keep_locks = 1; | 2780 | path->keep_locks = 1; |
| 2743 | 2781 | ||
| 2744 | while (1) { | 2782 | while (1) { |
| @@ -2767,7 +2805,10 @@ again: | |||
| 2767 | 2805 | ||
| 2768 | ret = copy_items(trans, log, dst_path, src, ins_start_slot, | 2806 | ret = copy_items(trans, log, dst_path, src, ins_start_slot, |
| 2769 | ins_nr, inode_only); | 2807 | ins_nr, inode_only); |
| 2770 | BUG_ON(ret); | 2808 | if (ret) { |
| 2809 | err = ret; | ||
| 2810 | goto out_unlock; | ||
| 2811 | } | ||
| 2771 | ins_nr = 1; | 2812 | ins_nr = 1; |
| 2772 | ins_start_slot = path->slots[0]; | 2813 | ins_start_slot = path->slots[0]; |
| 2773 | next_slot: | 2814 | next_slot: |
| @@ -2783,7 +2824,10 @@ next_slot: | |||
| 2783 | ret = copy_items(trans, log, dst_path, src, | 2824 | ret = copy_items(trans, log, dst_path, src, |
| 2784 | ins_start_slot, | 2825 | ins_start_slot, |
| 2785 | ins_nr, inode_only); | 2826 | ins_nr, inode_only); |
| 2786 | BUG_ON(ret); | 2827 | if (ret) { |
| 2828 | err = ret; | ||
| 2829 | goto out_unlock; | ||
| 2830 | } | ||
| 2787 | ins_nr = 0; | 2831 | ins_nr = 0; |
| 2788 | } | 2832 | } |
| 2789 | btrfs_release_path(root, path); | 2833 | btrfs_release_path(root, path); |
| @@ -2801,7 +2845,10 @@ next_slot: | |||
| 2801 | ret = copy_items(trans, log, dst_path, src, | 2845 | ret = copy_items(trans, log, dst_path, src, |
| 2802 | ins_start_slot, | 2846 | ins_start_slot, |
| 2803 | ins_nr, inode_only); | 2847 | ins_nr, inode_only); |
| 2804 | BUG_ON(ret); | 2848 | if (ret) { |
| 2849 | err = ret; | ||
| 2850 | goto out_unlock; | ||
| 2851 | } | ||
| 2805 | ins_nr = 0; | 2852 | ins_nr = 0; |
| 2806 | } | 2853 | } |
| 2807 | WARN_ON(ins_nr); | 2854 | WARN_ON(ins_nr); |
| @@ -2809,14 +2856,18 @@ next_slot: | |||
| 2809 | btrfs_release_path(root, path); | 2856 | btrfs_release_path(root, path); |
| 2810 | btrfs_release_path(log, dst_path); | 2857 | btrfs_release_path(log, dst_path); |
| 2811 | ret = log_directory_changes(trans, root, inode, path, dst_path); | 2858 | ret = log_directory_changes(trans, root, inode, path, dst_path); |
| 2812 | BUG_ON(ret); | 2859 | if (ret) { |
| 2860 | err = ret; | ||
| 2861 | goto out_unlock; | ||
| 2862 | } | ||
| 2813 | } | 2863 | } |
| 2814 | BTRFS_I(inode)->logged_trans = trans->transid; | 2864 | BTRFS_I(inode)->logged_trans = trans->transid; |
| 2865 | out_unlock: | ||
| 2815 | mutex_unlock(&BTRFS_I(inode)->log_mutex); | 2866 | mutex_unlock(&BTRFS_I(inode)->log_mutex); |
| 2816 | 2867 | ||
| 2817 | btrfs_free_path(path); | 2868 | btrfs_free_path(path); |
| 2818 | btrfs_free_path(dst_path); | 2869 | btrfs_free_path(dst_path); |
| 2819 | return 0; | 2870 | return err; |
| 2820 | } | 2871 | } |
| 2821 | 2872 | ||
| 2822 | /* | 2873 | /* |
| @@ -2941,10 +2992,13 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 2941 | goto end_no_trans; | 2992 | goto end_no_trans; |
| 2942 | } | 2993 | } |
| 2943 | 2994 | ||
| 2944 | start_log_trans(trans, root); | 2995 | ret = start_log_trans(trans, root); |
| 2996 | if (ret) | ||
| 2997 | goto end_trans; | ||
| 2945 | 2998 | ||
| 2946 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 2999 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
| 2947 | BUG_ON(ret); | 3000 | if (ret) |
| 3001 | goto end_trans; | ||
| 2948 | 3002 | ||
| 2949 | /* | 3003 | /* |
| 2950 | * for regular files, if its inode is already on disk, we don't | 3004 | * for regular files, if its inode is already on disk, we don't |
| @@ -2954,8 +3008,10 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 2954 | */ | 3008 | */ |
| 2955 | if (S_ISREG(inode->i_mode) && | 3009 | if (S_ISREG(inode->i_mode) && |
| 2956 | BTRFS_I(inode)->generation <= last_committed && | 3010 | BTRFS_I(inode)->generation <= last_committed && |
| 2957 | BTRFS_I(inode)->last_unlink_trans <= last_committed) | 3011 | BTRFS_I(inode)->last_unlink_trans <= last_committed) { |
| 2958 | goto no_parent; | 3012 | ret = 0; |
| 3013 | goto end_trans; | ||
| 3014 | } | ||
| 2959 | 3015 | ||
| 2960 | inode_only = LOG_INODE_EXISTS; | 3016 | inode_only = LOG_INODE_EXISTS; |
| 2961 | while (1) { | 3017 | while (1) { |
| @@ -2969,15 +3025,21 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 2969 | if (BTRFS_I(inode)->generation > | 3025 | if (BTRFS_I(inode)->generation > |
| 2970 | root->fs_info->last_trans_committed) { | 3026 | root->fs_info->last_trans_committed) { |
| 2971 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 3027 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
| 2972 | BUG_ON(ret); | 3028 | if (ret) |
| 3029 | goto end_trans; | ||
| 2973 | } | 3030 | } |
| 2974 | if (IS_ROOT(parent)) | 3031 | if (IS_ROOT(parent)) |
| 2975 | break; | 3032 | break; |
| 2976 | 3033 | ||
| 2977 | parent = parent->d_parent; | 3034 | parent = parent->d_parent; |
| 2978 | } | 3035 | } |
| 2979 | no_parent: | ||
| 2980 | ret = 0; | 3036 | ret = 0; |
| 3037 | end_trans: | ||
| 3038 | if (ret < 0) { | ||
| 3039 | BUG_ON(ret != -ENOSPC); | ||
| 3040 | root->fs_info->last_trans_log_full_commit = trans->transid; | ||
| 3041 | ret = 1; | ||
| 3042 | } | ||
| 2981 | btrfs_end_log_trans(root); | 3043 | btrfs_end_log_trans(root); |
| 2982 | end_no_trans: | 3044 | end_no_trans: |
| 2983 | return ret; | 3045 | return ret; |
| @@ -3019,7 +3081,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) | |||
| 3019 | path = btrfs_alloc_path(); | 3081 | path = btrfs_alloc_path(); |
| 3020 | BUG_ON(!path); | 3082 | BUG_ON(!path); |
| 3021 | 3083 | ||
| 3022 | trans = btrfs_start_transaction(fs_info->tree_root, 1); | 3084 | trans = btrfs_start_transaction(fs_info->tree_root, 0); |
| 3023 | 3085 | ||
| 3024 | wc.trans = trans; | 3086 | wc.trans = trans; |
| 3025 | wc.pin = 1; | 3087 | wc.pin = 1; |
