diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/backref.c | 28 | ||||
| -rw-r--r-- | fs/btrfs/backref.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/ctree.c | 70 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/qgroup.c | 17 | ||||
| -rw-r--r-- | fs/btrfs/send.c | 156 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 7 |
11 files changed, 199 insertions, 105 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index f3187938e081..208d8aa5b07e 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
| 283 | goto out; | 283 | goto out; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | rcu_read_lock(); | 286 | root_level = btrfs_old_root_level(root, time_seq); |
| 287 | root_level = btrfs_header_level(root->node); | ||
| 288 | rcu_read_unlock(); | ||
| 289 | 287 | ||
| 290 | if (root_level + 1 == level) | 288 | if (root_level + 1 == level) |
| 291 | goto out; | 289 | goto out; |
| @@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, | |||
| 1177 | return ret; | 1175 | return ret; |
| 1178 | } | 1176 | } |
| 1179 | 1177 | ||
| 1180 | static char *ref_to_path(struct btrfs_root *fs_root, | 1178 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
| 1181 | struct btrfs_path *path, | 1179 | u32 name_len, unsigned long name_off, |
| 1182 | u32 name_len, unsigned long name_off, | 1180 | struct extent_buffer *eb_in, u64 parent, |
| 1183 | struct extent_buffer *eb_in, u64 parent, | 1181 | char *dest, u32 size) |
| 1184 | char *dest, u32 size) | ||
| 1185 | { | 1182 | { |
| 1186 | int slot; | 1183 | int slot; |
| 1187 | u64 next_inum; | 1184 | u64 next_inum; |
| 1188 | int ret; | 1185 | int ret; |
| 1189 | s64 bytes_left = size - 1; | 1186 | s64 bytes_left = ((s64)size) - 1; |
| 1190 | struct extent_buffer *eb = eb_in; | 1187 | struct extent_buffer *eb = eb_in; |
| 1191 | struct btrfs_key found_key; | 1188 | struct btrfs_key found_key; |
| 1192 | int leave_spinning = path->leave_spinning; | 1189 | int leave_spinning = path->leave_spinning; |
| @@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, | |||
| 1266 | struct extent_buffer *eb_in, u64 parent, | 1263 | struct extent_buffer *eb_in, u64 parent, |
| 1267 | char *dest, u32 size) | 1264 | char *dest, u32 size) |
| 1268 | { | 1265 | { |
| 1269 | return ref_to_path(fs_root, path, | 1266 | return btrfs_ref_to_path(fs_root, path, |
| 1270 | btrfs_inode_ref_name_len(eb_in, iref), | 1267 | btrfs_inode_ref_name_len(eb_in, iref), |
| 1271 | (unsigned long)(iref + 1), | 1268 | (unsigned long)(iref + 1), |
| 1272 | eb_in, parent, dest, size); | 1269 | eb_in, parent, dest, size); |
| 1273 | } | 1270 | } |
| 1274 | 1271 | ||
| 1275 | /* | 1272 | /* |
| @@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off, | |||
| 1715 | ipath->fspath->bytes_left - s_ptr : 0; | 1712 | ipath->fspath->bytes_left - s_ptr : 0; |
| 1716 | 1713 | ||
| 1717 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; | 1714 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; |
| 1718 | fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, | 1715 | fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, |
| 1719 | name_off, eb, inum, fspath_min, | 1716 | name_off, eb, inum, fspath_min, bytes_left); |
| 1720 | bytes_left); | ||
| 1721 | if (IS_ERR(fspath)) | 1717 | if (IS_ERR(fspath)) |
| 1722 | return PTR_ERR(fspath); | 1718 | return PTR_ERR(fspath); |
| 1723 | 1719 | ||
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index e75533043a5f..d61feca79455 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h | |||
| @@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | |||
| 62 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | 62 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
| 63 | struct btrfs_inode_ref *iref, struct extent_buffer *eb, | 63 | struct btrfs_inode_ref *iref, struct extent_buffer *eb, |
| 64 | u64 parent, char *dest, u32 size); | 64 | u64 parent, char *dest, u32 size); |
| 65 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | ||
| 66 | u32 name_len, unsigned long name_off, | ||
| 67 | struct extent_buffer *eb_in, u64 parent, | ||
| 68 | char *dest, u32 size); | ||
| 65 | 69 | ||
| 66 | struct btrfs_data_container *init_data_container(u32 total_bytes); | 70 | struct btrfs_data_container *init_data_container(u32 total_bytes); |
| 67 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, | 71 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b33436211000..cdfb4c49a806 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, | |||
| 596 | if (tree_mod_dont_log(fs_info, eb)) | 596 | if (tree_mod_dont_log(fs_info, eb)) |
| 597 | return 0; | 597 | return 0; |
| 598 | 598 | ||
| 599 | /* | ||
| 600 | * When we override something during the move, we log these removals. | ||
| 601 | * This can only happen when we move towards the beginning of the | ||
| 602 | * buffer, i.e. dst_slot < src_slot. | ||
| 603 | */ | ||
| 599 | for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { | 604 | for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { |
| 600 | ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, | 605 | ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, |
| 601 | MOD_LOG_KEY_REMOVE_WHILE_MOVING); | 606 | MOD_LOG_KEY_REMOVE_WHILE_MOVING); |
| @@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, | |||
| 647 | if (tree_mod_dont_log(fs_info, NULL)) | 652 | if (tree_mod_dont_log(fs_info, NULL)) |
| 648 | return 0; | 653 | return 0; |
| 649 | 654 | ||
| 650 | __tree_mod_log_free_eb(fs_info, old_root); | ||
| 651 | |||
| 652 | ret = tree_mod_alloc(fs_info, flags, &tm); | 655 | ret = tree_mod_alloc(fs_info, flags, &tm); |
| 653 | if (ret < 0) | 656 | if (ret < 0) |
| 654 | goto out; | 657 | goto out; |
| @@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
| 926 | ret = btrfs_dec_ref(trans, root, buf, 1, 1); | 929 | ret = btrfs_dec_ref(trans, root, buf, 1, 1); |
| 927 | BUG_ON(ret); /* -ENOMEM */ | 930 | BUG_ON(ret); /* -ENOMEM */ |
| 928 | } | 931 | } |
| 929 | /* | 932 | tree_mod_log_free_eb(root->fs_info, buf); |
| 930 | * don't log freeing in case we're freeing the root node, this | ||
| 931 | * is done by tree_mod_log_set_root_pointer later | ||
| 932 | */ | ||
| 933 | if (buf != root->node && btrfs_header_level(buf) != 0) | ||
| 934 | tree_mod_log_free_eb(root->fs_info, buf); | ||
| 935 | clean_tree_block(trans, root, buf); | 933 | clean_tree_block(trans, root, buf); |
| 936 | *last_ref = 1; | 934 | *last_ref = 1; |
| 937 | } | 935 | } |
| @@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
| 1225 | free_extent_buffer(eb); | 1223 | free_extent_buffer(eb); |
| 1226 | 1224 | ||
| 1227 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); | 1225 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); |
| 1226 | WARN_ON(btrfs_header_nritems(eb_rewin) > | ||
| 1227 | BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root)); | ||
| 1228 | 1228 | ||
| 1229 | return eb_rewin; | 1229 | return eb_rewin; |
| 1230 | } | 1230 | } |
| @@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1241 | { | 1241 | { |
| 1242 | struct tree_mod_elem *tm; | 1242 | struct tree_mod_elem *tm; |
| 1243 | struct extent_buffer *eb; | 1243 | struct extent_buffer *eb; |
| 1244 | struct extent_buffer *old; | ||
| 1244 | struct tree_mod_root *old_root = NULL; | 1245 | struct tree_mod_root *old_root = NULL; |
| 1245 | u64 old_generation = 0; | 1246 | u64 old_generation = 0; |
| 1246 | u64 logical; | 1247 | u64 logical; |
| 1248 | u32 blocksize; | ||
| 1247 | 1249 | ||
| 1248 | eb = btrfs_read_lock_root_node(root); | 1250 | eb = btrfs_read_lock_root_node(root); |
| 1249 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); | 1251 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); |
| @@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1259 | } | 1261 | } |
| 1260 | 1262 | ||
| 1261 | tm = tree_mod_log_search(root->fs_info, logical, time_seq); | 1263 | tm = tree_mod_log_search(root->fs_info, logical, time_seq); |
| 1262 | if (old_root) | 1264 | if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) { |
| 1265 | btrfs_tree_read_unlock(root->node); | ||
| 1266 | free_extent_buffer(root->node); | ||
| 1267 | blocksize = btrfs_level_size(root, old_root->level); | ||
| 1268 | old = read_tree_block(root, logical, blocksize, 0); | ||
| 1269 | if (!old) { | ||
| 1270 | pr_warn("btrfs: failed to read tree block %llu from get_old_root\n", | ||
| 1271 | logical); | ||
| 1272 | WARN_ON(1); | ||
| 1273 | } else { | ||
| 1274 | eb = btrfs_clone_extent_buffer(old); | ||
| 1275 | free_extent_buffer(old); | ||
| 1276 | } | ||
| 1277 | } else if (old_root) { | ||
| 1278 | btrfs_tree_read_unlock(root->node); | ||
| 1279 | free_extent_buffer(root->node); | ||
| 1263 | eb = alloc_dummy_extent_buffer(logical, root->nodesize); | 1280 | eb = alloc_dummy_extent_buffer(logical, root->nodesize); |
| 1264 | else | 1281 | } else { |
| 1265 | eb = btrfs_clone_extent_buffer(root->node); | 1282 | eb = btrfs_clone_extent_buffer(root->node); |
| 1266 | btrfs_tree_read_unlock(root->node); | 1283 | btrfs_tree_read_unlock(root->node); |
| 1267 | free_extent_buffer(root->node); | 1284 | free_extent_buffer(root->node); |
| 1285 | } | ||
| 1286 | |||
| 1268 | if (!eb) | 1287 | if (!eb) |
| 1269 | return NULL; | 1288 | return NULL; |
| 1289 | extent_buffer_get(eb); | ||
| 1270 | btrfs_tree_read_lock(eb); | 1290 | btrfs_tree_read_lock(eb); |
| 1271 | if (old_root) { | 1291 | if (old_root) { |
| 1272 | btrfs_set_header_bytenr(eb, eb->start); | 1292 | btrfs_set_header_bytenr(eb, eb->start); |
| @@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1279 | __tree_mod_log_rewind(eb, time_seq, tm); | 1299 | __tree_mod_log_rewind(eb, time_seq, tm); |
| 1280 | else | 1300 | else |
| 1281 | WARN_ON(btrfs_header_level(eb) != 0); | 1301 | WARN_ON(btrfs_header_level(eb) != 0); |
| 1282 | extent_buffer_get(eb); | 1302 | WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); |
| 1283 | 1303 | ||
| 1284 | return eb; | 1304 | return eb; |
| 1285 | } | 1305 | } |
| 1286 | 1306 | ||
| 1307 | int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq) | ||
| 1308 | { | ||
| 1309 | struct tree_mod_elem *tm; | ||
| 1310 | int level; | ||
| 1311 | |||
| 1312 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); | ||
| 1313 | if (tm && tm->op == MOD_LOG_ROOT_REPLACE) { | ||
| 1314 | level = tm->old_root.level; | ||
| 1315 | } else { | ||
| 1316 | rcu_read_lock(); | ||
| 1317 | level = btrfs_header_level(root->node); | ||
| 1318 | rcu_read_unlock(); | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | return level; | ||
| 1322 | } | ||
| 1323 | |||
| 1287 | static inline int should_cow_block(struct btrfs_trans_handle *trans, | 1324 | static inline int should_cow_block(struct btrfs_trans_handle *trans, |
| 1288 | struct btrfs_root *root, | 1325 | struct btrfs_root *root, |
| 1289 | struct extent_buffer *buf) | 1326 | struct extent_buffer *buf) |
| @@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1725 | goto enospc; | 1762 | goto enospc; |
| 1726 | } | 1763 | } |
| 1727 | 1764 | ||
| 1765 | tree_mod_log_free_eb(root->fs_info, root->node); | ||
| 1728 | tree_mod_log_set_root_pointer(root, child); | 1766 | tree_mod_log_set_root_pointer(root, child); |
| 1729 | rcu_assign_pointer(root->node, child); | 1767 | rcu_assign_pointer(root->node, child); |
| 1730 | 1768 | ||
| @@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans, | |||
| 2970 | push_items * sizeof(struct btrfs_key_ptr)); | 3008 | push_items * sizeof(struct btrfs_key_ptr)); |
| 2971 | 3009 | ||
| 2972 | if (push_items < src_nritems) { | 3010 | if (push_items < src_nritems) { |
| 2973 | tree_mod_log_eb_move(root->fs_info, src, 0, push_items, | 3011 | /* |
| 2974 | src_nritems - push_items); | 3012 | * don't call tree_mod_log_eb_move here, key removal was already |
| 3013 | * fully logged by tree_mod_log_eb_copy above. | ||
| 3014 | */ | ||
| 2975 | memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), | 3015 | memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), |
| 2976 | btrfs_node_key_ptr_offset(push_items), | 3016 | btrfs_node_key_ptr_offset(push_items), |
| 2977 | (src_nritems - push_items) * | 3017 | (src_nritems - push_items) * |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 926c9ffc66d9..c72ead869507 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info) | |||
| 3120 | { | 3120 | { |
| 3121 | return atomic_inc_return(&fs_info->tree_mod_seq); | 3121 | return atomic_inc_return(&fs_info->tree_mod_seq); |
| 3122 | } | 3122 | } |
| 3123 | int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq); | ||
| 3123 | 3124 | ||
| 3124 | /* root-item.c */ | 3125 | /* root-item.c */ |
| 3125 | int btrfs_find_root_ref(struct btrfs_root *tree_root, | 3126 | int btrfs_find_root_ref(struct btrfs_root *tree_root, |
| @@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
| 3338 | int btrfs_update_inode(struct btrfs_trans_handle *trans, | 3339 | int btrfs_update_inode(struct btrfs_trans_handle *trans, |
| 3339 | struct btrfs_root *root, | 3340 | struct btrfs_root *root, |
| 3340 | struct inode *inode); | 3341 | struct inode *inode); |
| 3342 | int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
| 3343 | struct btrfs_root *root, struct inode *inode); | ||
| 3341 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); | 3344 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); |
| 3342 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); | 3345 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); |
| 3343 | int btrfs_orphan_cleanup(struct btrfs_root *root); | 3346 | int btrfs_orphan_cleanup(struct btrfs_root *root); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8036d3a84853..472873a94d96 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len) | |||
| 4110 | 4110 | ||
| 4111 | return eb; | 4111 | return eb; |
| 4112 | err: | 4112 | err: |
| 4113 | for (i--; i >= 0; i--) | 4113 | for (; i > 0; i--) |
| 4114 | __free_page(eb->pages[i]); | 4114 | __free_page(eb->pages[i - 1]); |
| 4115 | __free_extent_buffer(eb); | 4115 | __free_extent_buffer(eb); |
| 4116 | return NULL; | 4116 | return NULL; |
| 4117 | } | 4117 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 85a1e5053fe6..95542a1b3dfc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode, | |||
| 94 | struct page *locked_page, | 94 | struct page *locked_page, |
| 95 | u64 start, u64 end, int *page_started, | 95 | u64 start, u64 end, int *page_started, |
| 96 | unsigned long *nr_written, int unlock); | 96 | unsigned long *nr_written, int unlock); |
| 97 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
| 98 | struct btrfs_root *root, struct inode *inode); | ||
| 99 | 97 | ||
| 100 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 98 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, |
| 101 | struct inode *inode, struct inode *dir, | 99 | struct inode *inode, struct inode *dir, |
| @@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
| 2746 | return btrfs_update_inode_item(trans, root, inode); | 2744 | return btrfs_update_inode_item(trans, root, inode); |
| 2747 | } | 2745 | } |
| 2748 | 2746 | ||
| 2749 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | 2747 | noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, |
| 2750 | struct btrfs_root *root, struct inode *inode) | 2748 | struct btrfs_root *root, |
| 2749 | struct inode *inode) | ||
| 2751 | { | 2750 | { |
| 2752 | int ret; | 2751 | int ret; |
| 2753 | 2752 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 61168805f175..8fcf9a59c28d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
| 343 | return -EOPNOTSUPP; | 343 | return -EOPNOTSUPP; |
| 344 | if (copy_from_user(&range, arg, sizeof(range))) | 344 | if (copy_from_user(&range, arg, sizeof(range))) |
| 345 | return -EFAULT; | 345 | return -EFAULT; |
| 346 | if (range.start > total_bytes) | 346 | if (range.start > total_bytes || |
| 347 | range.len < fs_info->sb->s_blocksize) | ||
| 347 | return -EINVAL; | 348 | return -EINVAL; |
| 348 | 349 | ||
| 349 | range.len = min(range.len, total_bytes - range.start); | 350 | range.len = min(range.len, total_bytes - range.start); |
| @@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 570 | ret = btrfs_commit_transaction(trans, | 571 | ret = btrfs_commit_transaction(trans, |
| 571 | root->fs_info->extent_root); | 572 | root->fs_info->extent_root); |
| 572 | } | 573 | } |
| 573 | BUG_ON(ret); | 574 | if (ret) |
| 575 | goto fail; | ||
| 574 | 576 | ||
| 575 | ret = pending_snapshot->error; | 577 | ret = pending_snapshot->error; |
| 576 | if (ret) | 578 | if (ret) |
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 5039686df6ae..fe9d02c45f8e 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
| @@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | path = btrfs_alloc_path(); | 792 | path = btrfs_alloc_path(); |
| 793 | if (!path) | 793 | if (!path) { |
| 794 | return -ENOMEM; | 794 | ret = -ENOMEM; |
| 795 | goto out_free_root; | ||
| 796 | } | ||
| 795 | 797 | ||
| 796 | key.objectid = 0; | 798 | key.objectid = 0; |
| 797 | key.type = BTRFS_QGROUP_STATUS_KEY; | 799 | key.type = BTRFS_QGROUP_STATUS_KEY; |
| @@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
| 800 | ret = btrfs_insert_empty_item(trans, quota_root, path, &key, | 802 | ret = btrfs_insert_empty_item(trans, quota_root, path, &key, |
| 801 | sizeof(*ptr)); | 803 | sizeof(*ptr)); |
| 802 | if (ret) | 804 | if (ret) |
| 803 | goto out; | 805 | goto out_free_path; |
| 804 | 806 | ||
| 805 | leaf = path->nodes[0]; | 807 | leaf = path->nodes[0]; |
| 806 | ptr = btrfs_item_ptr(leaf, path->slots[0], | 808 | ptr = btrfs_item_ptr(leaf, path->slots[0], |
| @@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
| 818 | fs_info->quota_root = quota_root; | 820 | fs_info->quota_root = quota_root; |
| 819 | fs_info->pending_quota_state = 1; | 821 | fs_info->pending_quota_state = 1; |
| 820 | spin_unlock(&fs_info->qgroup_lock); | 822 | spin_unlock(&fs_info->qgroup_lock); |
| 821 | out: | 823 | out_free_path: |
| 822 | btrfs_free_path(path); | 824 | btrfs_free_path(path); |
| 825 | out_free_root: | ||
| 826 | if (ret) { | ||
| 827 | free_extent_buffer(quota_root->node); | ||
| 828 | free_extent_buffer(quota_root->commit_root); | ||
| 829 | kfree(quota_root); | ||
| 830 | } | ||
| 831 | out: | ||
| 823 | return ret; | 832 | return ret; |
| 824 | } | 833 | } |
| 825 | 834 | ||
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c7beb543a4a8..e78b297b0b00 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
| @@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index, | |||
| 745 | void *ctx); | 745 | void *ctx); |
| 746 | 746 | ||
| 747 | /* | 747 | /* |
| 748 | * Helper function to iterate the entries in ONE btrfs_inode_ref. | 748 | * Helper function to iterate the entries in ONE btrfs_inode_ref or |
| 749 | * btrfs_inode_extref. | ||
| 749 | * The iterate callback may return a non zero value to stop iteration. This can | 750 | * The iterate callback may return a non zero value to stop iteration. This can |
| 750 | * be a negative value for error codes or 1 to simply stop it. | 751 | * be a negative value for error codes or 1 to simply stop it. |
| 751 | * | 752 | * |
| 752 | * path must point to the INODE_REF when called. | 753 | * path must point to the INODE_REF or INODE_EXTREF when called. |
| 753 | */ | 754 | */ |
| 754 | static int iterate_inode_ref(struct send_ctx *sctx, | 755 | static int iterate_inode_ref(struct send_ctx *sctx, |
| 755 | struct btrfs_root *root, struct btrfs_path *path, | 756 | struct btrfs_root *root, struct btrfs_path *path, |
| 756 | struct btrfs_key *found_key, int resolve, | 757 | struct btrfs_key *found_key, int resolve, |
| 757 | iterate_inode_ref_t iterate, void *ctx) | 758 | iterate_inode_ref_t iterate, void *ctx) |
| 758 | { | 759 | { |
| 759 | struct extent_buffer *eb; | 760 | struct extent_buffer *eb = path->nodes[0]; |
| 760 | struct btrfs_item *item; | 761 | struct btrfs_item *item; |
| 761 | struct btrfs_inode_ref *iref; | 762 | struct btrfs_inode_ref *iref; |
| 763 | struct btrfs_inode_extref *extref; | ||
| 762 | struct btrfs_path *tmp_path; | 764 | struct btrfs_path *tmp_path; |
| 763 | struct fs_path *p; | 765 | struct fs_path *p; |
| 764 | u32 cur; | 766 | u32 cur = 0; |
| 765 | u32 len; | ||
| 766 | u32 total; | 767 | u32 total; |
| 767 | int slot; | 768 | int slot = path->slots[0]; |
| 768 | u32 name_len; | 769 | u32 name_len; |
| 769 | char *start; | 770 | char *start; |
| 770 | int ret = 0; | 771 | int ret = 0; |
| 771 | int num; | 772 | int num = 0; |
| 772 | int index; | 773 | int index; |
| 774 | u64 dir; | ||
| 775 | unsigned long name_off; | ||
| 776 | unsigned long elem_size; | ||
| 777 | unsigned long ptr; | ||
| 773 | 778 | ||
| 774 | p = fs_path_alloc_reversed(sctx); | 779 | p = fs_path_alloc_reversed(sctx); |
| 775 | if (!p) | 780 | if (!p) |
| @@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
| 781 | return -ENOMEM; | 786 | return -ENOMEM; |
| 782 | } | 787 | } |
| 783 | 788 | ||
| 784 | eb = path->nodes[0]; | ||
| 785 | slot = path->slots[0]; | ||
| 786 | item = btrfs_item_nr(eb, slot); | ||
| 787 | iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); | ||
| 788 | cur = 0; | ||
| 789 | len = 0; | ||
| 790 | total = btrfs_item_size(eb, item); | ||
| 791 | 789 | ||
| 792 | num = 0; | 790 | if (found_key->type == BTRFS_INODE_REF_KEY) { |
| 791 | ptr = (unsigned long)btrfs_item_ptr(eb, slot, | ||
| 792 | struct btrfs_inode_ref); | ||
| 793 | item = btrfs_item_nr(eb, slot); | ||
| 794 | total = btrfs_item_size(eb, item); | ||
| 795 | elem_size = sizeof(*iref); | ||
| 796 | } else { | ||
| 797 | ptr = btrfs_item_ptr_offset(eb, slot); | ||
| 798 | total = btrfs_item_size_nr(eb, slot); | ||
| 799 | elem_size = sizeof(*extref); | ||
| 800 | } | ||
| 801 | |||
| 793 | while (cur < total) { | 802 | while (cur < total) { |
| 794 | fs_path_reset(p); | 803 | fs_path_reset(p); |
| 795 | 804 | ||
| 796 | name_len = btrfs_inode_ref_name_len(eb, iref); | 805 | if (found_key->type == BTRFS_INODE_REF_KEY) { |
| 797 | index = btrfs_inode_ref_index(eb, iref); | 806 | iref = (struct btrfs_inode_ref *)(ptr + cur); |
| 807 | name_len = btrfs_inode_ref_name_len(eb, iref); | ||
| 808 | name_off = (unsigned long)(iref + 1); | ||
| 809 | index = btrfs_inode_ref_index(eb, iref); | ||
| 810 | dir = found_key->offset; | ||
| 811 | } else { | ||
| 812 | extref = (struct btrfs_inode_extref *)(ptr + cur); | ||
| 813 | name_len = btrfs_inode_extref_name_len(eb, extref); | ||
| 814 | name_off = (unsigned long)&extref->name; | ||
| 815 | index = btrfs_inode_extref_index(eb, extref); | ||
| 816 | dir = btrfs_inode_extref_parent(eb, extref); | ||
| 817 | } | ||
| 818 | |||
| 798 | if (resolve) { | 819 | if (resolve) { |
| 799 | start = btrfs_iref_to_path(root, tmp_path, iref, eb, | 820 | start = btrfs_ref_to_path(root, tmp_path, name_len, |
| 800 | found_key->offset, p->buf, | 821 | name_off, eb, dir, |
| 801 | p->buf_len); | 822 | p->buf, p->buf_len); |
| 802 | if (IS_ERR(start)) { | 823 | if (IS_ERR(start)) { |
| 803 | ret = PTR_ERR(start); | 824 | ret = PTR_ERR(start); |
| 804 | goto out; | 825 | goto out; |
| @@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
| 809 | p->buf_len + p->buf - start); | 830 | p->buf_len + p->buf - start); |
| 810 | if (ret < 0) | 831 | if (ret < 0) |
| 811 | goto out; | 832 | goto out; |
| 812 | start = btrfs_iref_to_path(root, tmp_path, iref, | 833 | start = btrfs_ref_to_path(root, tmp_path, |
| 813 | eb, found_key->offset, p->buf, | 834 | name_len, name_off, |
| 814 | p->buf_len); | 835 | eb, dir, |
| 836 | p->buf, p->buf_len); | ||
| 815 | if (IS_ERR(start)) { | 837 | if (IS_ERR(start)) { |
| 816 | ret = PTR_ERR(start); | 838 | ret = PTR_ERR(start); |
| 817 | goto out; | 839 | goto out; |
| @@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
| 820 | } | 842 | } |
| 821 | p->start = start; | 843 | p->start = start; |
| 822 | } else { | 844 | } else { |
| 823 | ret = fs_path_add_from_extent_buffer(p, eb, | 845 | ret = fs_path_add_from_extent_buffer(p, eb, name_off, |
| 824 | (unsigned long)(iref + 1), name_len); | 846 | name_len); |
| 825 | if (ret < 0) | 847 | if (ret < 0) |
| 826 | goto out; | 848 | goto out; |
| 827 | } | 849 | } |
| 828 | 850 | ||
| 829 | 851 | cur += elem_size + name_len; | |
| 830 | len = sizeof(*iref) + name_len; | 852 | ret = iterate(num, dir, index, p, ctx); |
| 831 | iref = (struct btrfs_inode_ref *)((char *)iref + len); | ||
| 832 | cur += len; | ||
| 833 | |||
| 834 | ret = iterate(num, found_key->offset, index, p, ctx); | ||
| 835 | if (ret) | 853 | if (ret) |
| 836 | goto out; | 854 | goto out; |
| 837 | |||
| 838 | num++; | 855 | num++; |
| 839 | } | 856 | } |
| 840 | 857 | ||
| @@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root, | |||
| 998 | } | 1015 | } |
| 999 | btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); | 1016 | btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); |
| 1000 | if (found_key.objectid != ino || | 1017 | if (found_key.objectid != ino || |
| 1001 | found_key.type != BTRFS_INODE_REF_KEY) { | 1018 | (found_key.type != BTRFS_INODE_REF_KEY && |
| 1019 | found_key.type != BTRFS_INODE_EXTREF_KEY)) { | ||
| 1002 | ret = -ENOENT; | 1020 | ret = -ENOENT; |
| 1003 | goto out; | 1021 | goto out; |
| 1004 | } | 1022 | } |
| @@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx, | |||
| 1551 | struct btrfs_key key; | 1569 | struct btrfs_key key; |
| 1552 | struct btrfs_key found_key; | 1570 | struct btrfs_key found_key; |
| 1553 | struct btrfs_path *path; | 1571 | struct btrfs_path *path; |
| 1554 | struct btrfs_inode_ref *iref; | ||
| 1555 | int len; | 1572 | int len; |
| 1573 | u64 parent_dir; | ||
| 1556 | 1574 | ||
| 1557 | path = alloc_path_for_send(); | 1575 | path = alloc_path_for_send(); |
| 1558 | if (!path) | 1576 | if (!path) |
| @@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx, | |||
| 1568 | if (!ret) | 1586 | if (!ret) |
| 1569 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | 1587 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, |
| 1570 | path->slots[0]); | 1588 | path->slots[0]); |
| 1571 | if (ret || found_key.objectid != key.objectid || | 1589 | if (ret || found_key.objectid != ino || |
| 1572 | found_key.type != key.type) { | 1590 | (found_key.type != BTRFS_INODE_REF_KEY && |
| 1591 | found_key.type != BTRFS_INODE_EXTREF_KEY)) { | ||
| 1573 | ret = -ENOENT; | 1592 | ret = -ENOENT; |
| 1574 | goto out; | 1593 | goto out; |
| 1575 | } | 1594 | } |
| 1576 | 1595 | ||
| 1577 | iref = btrfs_item_ptr(path->nodes[0], path->slots[0], | 1596 | if (key.type == BTRFS_INODE_REF_KEY) { |
| 1578 | struct btrfs_inode_ref); | 1597 | struct btrfs_inode_ref *iref; |
| 1579 | len = btrfs_inode_ref_name_len(path->nodes[0], iref); | 1598 | iref = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| 1580 | ret = fs_path_add_from_extent_buffer(name, path->nodes[0], | 1599 | struct btrfs_inode_ref); |
| 1581 | (unsigned long)(iref + 1), len); | 1600 | len = btrfs_inode_ref_name_len(path->nodes[0], iref); |
| 1601 | ret = fs_path_add_from_extent_buffer(name, path->nodes[0], | ||
| 1602 | (unsigned long)(iref + 1), | ||
| 1603 | len); | ||
| 1604 | parent_dir = found_key.offset; | ||
| 1605 | } else { | ||
| 1606 | struct btrfs_inode_extref *extref; | ||
| 1607 | extref = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
| 1608 | struct btrfs_inode_extref); | ||
| 1609 | len = btrfs_inode_extref_name_len(path->nodes[0], extref); | ||
| 1610 | ret = fs_path_add_from_extent_buffer(name, path->nodes[0], | ||
| 1611 | (unsigned long)&extref->name, len); | ||
| 1612 | parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref); | ||
| 1613 | } | ||
| 1582 | if (ret < 0) | 1614 | if (ret < 0) |
| 1583 | goto out; | 1615 | goto out; |
| 1584 | btrfs_release_path(path); | 1616 | btrfs_release_path(path); |
| 1585 | 1617 | ||
| 1586 | ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL, | 1618 | ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL, |
| 1587 | NULL, NULL); | 1619 | NULL, NULL); |
| 1588 | if (ret < 0) | 1620 | if (ret < 0) |
| 1589 | goto out; | 1621 | goto out; |
| 1590 | 1622 | ||
| 1591 | *dir = found_key.offset; | 1623 | *dir = parent_dir; |
| 1592 | 1624 | ||
| 1593 | out: | 1625 | out: |
| 1594 | btrfs_free_path(path); | 1626 | btrfs_free_path(path); |
| @@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino); | |||
| 2430 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); | 2462 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); |
| 2431 | } else if (S_ISCHR(mode) || S_ISBLK(mode) || | 2463 | } else if (S_ISCHR(mode) || S_ISBLK(mode) || |
| 2432 | S_ISFIFO(mode) || S_ISSOCK(mode)) { | 2464 | S_ISFIFO(mode) || S_ISSOCK(mode)) { |
| 2433 | TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev); | 2465 | TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev)); |
| 2466 | TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode); | ||
| 2434 | } | 2467 | } |
| 2435 | 2468 | ||
| 2436 | ret = send_cmd(sctx); | 2469 | ret = send_cmd(sctx); |
| @@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx, | |||
| 3226 | btrfs_item_key_to_cpu(eb, &found_key, slot); | 3259 | btrfs_item_key_to_cpu(eb, &found_key, slot); |
| 3227 | 3260 | ||
| 3228 | if (found_key.objectid != key.objectid || | 3261 | if (found_key.objectid != key.objectid || |
| 3229 | found_key.type != key.type) | 3262 | (found_key.type != BTRFS_INODE_REF_KEY && |
| 3263 | found_key.type != BTRFS_INODE_EXTREF_KEY)) | ||
| 3230 | break; | 3264 | break; |
| 3231 | 3265 | ||
| 3232 | ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, | 3266 | ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, |
| @@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end) | |||
| 3987 | if (sctx->cur_ino == 0) | 4021 | if (sctx->cur_ino == 0) |
| 3988 | goto out; | 4022 | goto out; |
| 3989 | if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && | 4023 | if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && |
| 3990 | sctx->cmp_key->type <= BTRFS_INODE_REF_KEY) | 4024 | sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY) |
| 3991 | goto out; | 4025 | goto out; |
| 3992 | if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) | 4026 | if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) |
| 3993 | goto out; | 4027 | goto out; |
| @@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end) | |||
| 4033 | if (ret < 0) | 4067 | if (ret < 0) |
| 4034 | goto out; | 4068 | goto out; |
| 4035 | 4069 | ||
| 4036 | if (!S_ISLNK(sctx->cur_inode_mode)) { | 4070 | if (!sctx->parent_root || sctx->cur_inode_new) { |
| 4037 | if (!sctx->parent_root || sctx->cur_inode_new) { | 4071 | need_chown = 1; |
| 4072 | if (!S_ISLNK(sctx->cur_inode_mode)) | ||
| 4038 | need_chmod = 1; | 4073 | need_chmod = 1; |
| 4039 | need_chown = 1; | 4074 | } else { |
| 4040 | } else { | 4075 | ret = get_inode_info(sctx->parent_root, sctx->cur_ino, |
| 4041 | ret = get_inode_info(sctx->parent_root, sctx->cur_ino, | 4076 | NULL, NULL, &right_mode, &right_uid, |
| 4042 | NULL, NULL, &right_mode, &right_uid, | 4077 | &right_gid, NULL); |
| 4043 | &right_gid, NULL); | 4078 | if (ret < 0) |
| 4044 | if (ret < 0) | 4079 | goto out; |
| 4045 | goto out; | ||
| 4046 | 4080 | ||
| 4047 | if (left_uid != right_uid || left_gid != right_gid) | 4081 | if (left_uid != right_uid || left_gid != right_gid) |
| 4048 | need_chown = 1; | 4082 | need_chown = 1; |
| 4049 | if (left_mode != right_mode) | 4083 | if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode) |
| 4050 | need_chmod = 1; | 4084 | need_chmod = 1; |
| 4051 | } | ||
| 4052 | } | 4085 | } |
| 4053 | 4086 | ||
| 4054 | if (S_ISREG(sctx->cur_inode_mode)) { | 4087 | if (S_ISREG(sctx->cur_inode_mode)) { |
| @@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root, | |||
| 4335 | 4368 | ||
| 4336 | if (key->type == BTRFS_INODE_ITEM_KEY) | 4369 | if (key->type == BTRFS_INODE_ITEM_KEY) |
| 4337 | ret = changed_inode(sctx, result); | 4370 | ret = changed_inode(sctx, result); |
| 4338 | else if (key->type == BTRFS_INODE_REF_KEY) | 4371 | else if (key->type == BTRFS_INODE_REF_KEY || |
| 4372 | key->type == BTRFS_INODE_EXTREF_KEY) | ||
| 4339 | ret = changed_ref(sctx, result); | 4373 | ret = changed_ref(sctx, result); |
| 4340 | else if (key->type == BTRFS_XATTR_ITEM_KEY) | 4374 | else if (key->type == BTRFS_XATTR_ITEM_KEY) |
| 4341 | ret = changed_xattr(sctx, result); | 4375 | ret = changed_xattr(sctx, result); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 77db875b5116..04bbfb1052eb 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 1200 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 1200 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
| 1201 | dentry->d_name.len * 2); | 1201 | dentry->d_name.len * 2); |
| 1202 | parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; | 1202 | parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; |
| 1203 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | 1203 | ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode); |
| 1204 | if (ret) | 1204 | if (ret) |
| 1205 | btrfs_abort_transaction(trans, root, ret); | 1205 | btrfs_abort_transaction(trans, root, ret); |
| 1206 | fail: | 1206 | fail: |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 029b903a4ae3..0f5ebb72a5ea 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1819 | "Failed to relocate sys chunks after " | 1819 | "Failed to relocate sys chunks after " |
| 1820 | "device initialization. This can be fixed " | 1820 | "device initialization. This can be fixed " |
| 1821 | "using the \"btrfs balance\" command."); | 1821 | "using the \"btrfs balance\" command."); |
| 1822 | trans = btrfs_attach_transaction(root); | ||
| 1823 | if (IS_ERR(trans)) { | ||
| 1824 | if (PTR_ERR(trans) == -ENOENT) | ||
| 1825 | return 0; | ||
| 1826 | return PTR_ERR(trans); | ||
| 1827 | } | ||
| 1828 | ret = btrfs_commit_transaction(trans, root); | ||
| 1822 | } | 1829 | } |
| 1823 | 1830 | ||
| 1824 | return ret; | 1831 | return ret; |
