diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-27 16:26:28 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-27 16:26:28 -0400 |
| commit | 33c0022f0e687b0161a9bb84a5671df932551e3a (patch) | |
| tree | af5a871d8685c0baca9c4b8fcf31cb9f5454374a | |
| parent | 2b9d1c050d291693f257c98605028325f8146c84 (diff) | |
| parent | cfd4a535b68faf651b238586011f5bae128391c4 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
Btrfs: limit the path size in send to PATH_MAX
Btrfs: correctly set profile flags on seqlock retry
Btrfs: use correct key when repeating search for extent item
Btrfs: fix inode caching vs tree log
Btrfs: fix possible memory leaks in open_ctree()
Btrfs: avoid triggering bug_on() when we fail to start inode caching task
Btrfs: move btrfs_{set,clear}_and_info() to ctree.h
btrfs: replace error code from btrfs_drop_extents
btrfs: Change the hole range to a more accurate value.
btrfs: fix use-after-free in mount_subvol()
| -rw-r--r-- | fs/btrfs/ctree.h | 14 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 10 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 8 | ||||
| -rw-r--r-- | fs/btrfs/inode-map.c | 24 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/send.c | 5 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 22 |
8 files changed, 48 insertions, 45 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 4c48df572bd6..ba6b88528dc7 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -2058,6 +2058,20 @@ struct btrfs_ioctl_defrag_range_args { | |||
| 2058 | #define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt) | 2058 | #define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt) |
| 2059 | #define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \ | 2059 | #define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \ |
| 2060 | BTRFS_MOUNT_##opt) | 2060 | BTRFS_MOUNT_##opt) |
| 2061 | #define btrfs_set_and_info(root, opt, fmt, args...) \ | ||
| 2062 | { \ | ||
| 2063 | if (!btrfs_test_opt(root, opt)) \ | ||
| 2064 | btrfs_info(root->fs_info, fmt, ##args); \ | ||
| 2065 | btrfs_set_opt(root->fs_info->mount_opt, opt); \ | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | #define btrfs_clear_and_info(root, opt, fmt, args...) \ | ||
| 2069 | { \ | ||
| 2070 | if (btrfs_test_opt(root, opt)) \ | ||
| 2071 | btrfs_info(root->fs_info, fmt, ##args); \ | ||
| 2072 | btrfs_clear_opt(root->fs_info->mount_opt, opt); \ | ||
| 2073 | } | ||
| 2074 | |||
| 2061 | /* | 2075 | /* |
| 2062 | * Inode flags | 2076 | * Inode flags |
| 2063 | */ | 2077 | */ |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 029d46c2e170..983314932af3 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -2861,7 +2861,7 @@ retry_root_backup: | |||
| 2861 | printk(KERN_ERR "BTRFS: failed to read log tree\n"); | 2861 | printk(KERN_ERR "BTRFS: failed to read log tree\n"); |
| 2862 | free_extent_buffer(log_tree_root->node); | 2862 | free_extent_buffer(log_tree_root->node); |
| 2863 | kfree(log_tree_root); | 2863 | kfree(log_tree_root); |
| 2864 | goto fail_trans_kthread; | 2864 | goto fail_qgroup; |
| 2865 | } | 2865 | } |
| 2866 | /* returns with log_tree_root freed on success */ | 2866 | /* returns with log_tree_root freed on success */ |
| 2867 | ret = btrfs_recover_log_trees(log_tree_root); | 2867 | ret = btrfs_recover_log_trees(log_tree_root); |
| @@ -2870,24 +2870,24 @@ retry_root_backup: | |||
| 2870 | "Failed to recover log tree"); | 2870 | "Failed to recover log tree"); |
| 2871 | free_extent_buffer(log_tree_root->node); | 2871 | free_extent_buffer(log_tree_root->node); |
| 2872 | kfree(log_tree_root); | 2872 | kfree(log_tree_root); |
| 2873 | goto fail_trans_kthread; | 2873 | goto fail_qgroup; |
| 2874 | } | 2874 | } |
| 2875 | 2875 | ||
| 2876 | if (sb->s_flags & MS_RDONLY) { | 2876 | if (sb->s_flags & MS_RDONLY) { |
| 2877 | ret = btrfs_commit_super(tree_root); | 2877 | ret = btrfs_commit_super(tree_root); |
| 2878 | if (ret) | 2878 | if (ret) |
| 2879 | goto fail_trans_kthread; | 2879 | goto fail_qgroup; |
| 2880 | } | 2880 | } |
| 2881 | } | 2881 | } |
| 2882 | 2882 | ||
| 2883 | ret = btrfs_find_orphan_roots(tree_root); | 2883 | ret = btrfs_find_orphan_roots(tree_root); |
| 2884 | if (ret) | 2884 | if (ret) |
| 2885 | goto fail_trans_kthread; | 2885 | goto fail_qgroup; |
| 2886 | 2886 | ||
| 2887 | if (!(sb->s_flags & MS_RDONLY)) { | 2887 | if (!(sb->s_flags & MS_RDONLY)) { |
| 2888 | ret = btrfs_cleanup_fs_roots(fs_info); | 2888 | ret = btrfs_cleanup_fs_roots(fs_info); |
| 2889 | if (ret) | 2889 | if (ret) |
| 2890 | goto fail_trans_kthread; | 2890 | goto fail_qgroup; |
| 2891 | 2891 | ||
| 2892 | ret = btrfs_recover_relocation(tree_root); | 2892 | ret = btrfs_recover_relocation(tree_root); |
| 2893 | if (ret < 0) { | 2893 | if (ret < 0) { |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1306487c82cf..5590af92094b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -1542,6 +1542,7 @@ again: | |||
| 1542 | ret = 0; | 1542 | ret = 0; |
| 1543 | } | 1543 | } |
| 1544 | if (ret) { | 1544 | if (ret) { |
| 1545 | key.objectid = bytenr; | ||
| 1545 | key.type = BTRFS_EXTENT_ITEM_KEY; | 1546 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 1546 | key.offset = num_bytes; | 1547 | key.offset = num_bytes; |
| 1547 | btrfs_release_path(path); | 1548 | btrfs_release_path(path); |
| @@ -3542,11 +3543,13 @@ static u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | |||
| 3542 | return extended_to_chunk(flags | tmp); | 3543 | return extended_to_chunk(flags | tmp); |
| 3543 | } | 3544 | } |
| 3544 | 3545 | ||
| 3545 | static u64 get_alloc_profile(struct btrfs_root *root, u64 flags) | 3546 | static u64 get_alloc_profile(struct btrfs_root *root, u64 orig_flags) |
| 3546 | { | 3547 | { |
| 3547 | unsigned seq; | 3548 | unsigned seq; |
| 3549 | u64 flags; | ||
| 3548 | 3550 | ||
| 3549 | do { | 3551 | do { |
| 3552 | flags = orig_flags; | ||
| 3550 | seq = read_seqbegin(&root->fs_info->profiles_lock); | 3553 | seq = read_seqbegin(&root->fs_info->profiles_lock); |
| 3551 | 3554 | ||
| 3552 | if (flags & BTRFS_BLOCK_GROUP_DATA) | 3555 | if (flags & BTRFS_BLOCK_GROUP_DATA) |
| @@ -5719,6 +5722,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5719 | 5722 | ||
| 5720 | if (ret > 0 && skinny_metadata) { | 5723 | if (ret > 0 && skinny_metadata) { |
| 5721 | skinny_metadata = false; | 5724 | skinny_metadata = false; |
| 5725 | key.objectid = bytenr; | ||
| 5722 | key.type = BTRFS_EXTENT_ITEM_KEY; | 5726 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 5723 | key.offset = num_bytes; | 5727 | key.offset = num_bytes; |
| 5724 | btrfs_release_path(path); | 5728 | btrfs_release_path(path); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index eb742c07e7a4..ae6af072b635 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -800,7 +800,7 @@ next_slot: | |||
| 800 | if (start > key.offset && end < extent_end) { | 800 | if (start > key.offset && end < extent_end) { |
| 801 | BUG_ON(del_nr > 0); | 801 | BUG_ON(del_nr > 0); |
| 802 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 802 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
| 803 | ret = -EINVAL; | 803 | ret = -EOPNOTSUPP; |
| 804 | break; | 804 | break; |
| 805 | } | 805 | } |
| 806 | 806 | ||
| @@ -846,7 +846,7 @@ next_slot: | |||
| 846 | */ | 846 | */ |
| 847 | if (start <= key.offset && end < extent_end) { | 847 | if (start <= key.offset && end < extent_end) { |
| 848 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 848 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
| 849 | ret = -EINVAL; | 849 | ret = -EOPNOTSUPP; |
| 850 | break; | 850 | break; |
| 851 | } | 851 | } |
| 852 | 852 | ||
| @@ -872,7 +872,7 @@ next_slot: | |||
| 872 | if (start > key.offset && end >= extent_end) { | 872 | if (start > key.offset && end >= extent_end) { |
| 873 | BUG_ON(del_nr > 0); | 873 | BUG_ON(del_nr > 0); |
| 874 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 874 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
| 875 | ret = -EINVAL; | 875 | ret = -EOPNOTSUPP; |
| 876 | break; | 876 | break; |
| 877 | } | 877 | } |
| 878 | 878 | ||
| @@ -1777,7 +1777,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1777 | start_pos = round_down(pos, root->sectorsize); | 1777 | start_pos = round_down(pos, root->sectorsize); |
| 1778 | if (start_pos > i_size_read(inode)) { | 1778 | if (start_pos > i_size_read(inode)) { |
| 1779 | /* Expand hole size to cover write data, preventing empty gap */ | 1779 | /* Expand hole size to cover write data, preventing empty gap */ |
| 1780 | end_pos = round_up(pos + iov->iov_len, root->sectorsize); | 1780 | end_pos = round_up(pos + count, root->sectorsize); |
| 1781 | err = btrfs_cont_expand(inode, i_size_read(inode), end_pos); | 1781 | err = btrfs_cont_expand(inode, i_size_read(inode), end_pos); |
| 1782 | if (err) { | 1782 | if (err) { |
| 1783 | mutex_unlock(&inode->i_mutex); | 1783 | mutex_unlock(&inode->i_mutex); |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index cc8ca193d830..86935f5ae291 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
| @@ -176,7 +176,11 @@ static void start_caching(struct btrfs_root *root) | |||
| 176 | 176 | ||
| 177 | tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n", | 177 | tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n", |
| 178 | root->root_key.objectid); | 178 | root->root_key.objectid); |
| 179 | BUG_ON(IS_ERR(tsk)); /* -ENOMEM */ | 179 | if (IS_ERR(tsk)) { |
| 180 | btrfs_warn(root->fs_info, "failed to start inode caching task"); | ||
| 181 | btrfs_clear_and_info(root, CHANGE_INODE_CACHE, | ||
| 182 | "disabling inode map caching"); | ||
| 183 | } | ||
| 180 | } | 184 | } |
| 181 | 185 | ||
| 182 | int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid) | 186 | int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid) |
| @@ -205,24 +209,14 @@ again: | |||
| 205 | 209 | ||
| 206 | void btrfs_return_ino(struct btrfs_root *root, u64 objectid) | 210 | void btrfs_return_ino(struct btrfs_root *root, u64 objectid) |
| 207 | { | 211 | { |
| 208 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; | ||
| 209 | struct btrfs_free_space_ctl *pinned = root->free_ino_pinned; | 212 | struct btrfs_free_space_ctl *pinned = root->free_ino_pinned; |
| 210 | 213 | ||
| 211 | if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | 214 | if (!btrfs_test_opt(root, INODE_MAP_CACHE)) |
| 212 | return; | 215 | return; |
| 213 | |||
| 214 | again: | 216 | again: |
| 215 | if (root->cached == BTRFS_CACHE_FINISHED) { | 217 | if (root->cached == BTRFS_CACHE_FINISHED) { |
| 216 | __btrfs_add_free_space(ctl, objectid, 1); | 218 | __btrfs_add_free_space(pinned, objectid, 1); |
| 217 | } else { | 219 | } else { |
| 218 | /* | ||
| 219 | * If we are in the process of caching free ino chunks, | ||
| 220 | * to avoid adding the same inode number to the free_ino | ||
| 221 | * tree twice due to cross transaction, we'll leave it | ||
| 222 | * in the pinned tree until a transaction is committed | ||
| 223 | * or the caching work is done. | ||
| 224 | */ | ||
| 225 | |||
| 226 | down_write(&root->fs_info->commit_root_sem); | 220 | down_write(&root->fs_info->commit_root_sem); |
| 227 | spin_lock(&root->cache_lock); | 221 | spin_lock(&root->cache_lock); |
| 228 | if (root->cached == BTRFS_CACHE_FINISHED) { | 222 | if (root->cached == BTRFS_CACHE_FINISHED) { |
| @@ -234,11 +228,7 @@ again: | |||
| 234 | 228 | ||
| 235 | start_caching(root); | 229 | start_caching(root); |
| 236 | 230 | ||
| 237 | if (objectid <= root->cache_progress || | 231 | __btrfs_add_free_space(pinned, objectid, 1); |
| 238 | objectid >= root->highest_objectid) | ||
| 239 | __btrfs_add_free_space(ctl, objectid, 1); | ||
| 240 | else | ||
| 241 | __btrfs_add_free_space(pinned, objectid, 1); | ||
| 242 | 232 | ||
| 243 | up_write(&root->fs_info->commit_root_sem); | 233 | up_write(&root->fs_info->commit_root_sem); |
| 244 | } | 234 | } |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index e79ff6b90cb7..2ad7de94efef 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -3066,7 +3066,7 @@ process_slot: | |||
| 3066 | new_key.offset + datal, | 3066 | new_key.offset + datal, |
| 3067 | 1); | 3067 | 1); |
| 3068 | if (ret) { | 3068 | if (ret) { |
| 3069 | if (ret != -EINVAL) | 3069 | if (ret != -EOPNOTSUPP) |
| 3070 | btrfs_abort_transaction(trans, | 3070 | btrfs_abort_transaction(trans, |
| 3071 | root, ret); | 3071 | root, ret); |
| 3072 | btrfs_end_transaction(trans, root); | 3072 | btrfs_end_transaction(trans, root); |
| @@ -3141,7 +3141,7 @@ process_slot: | |||
| 3141 | new_key.offset + datal, | 3141 | new_key.offset + datal, |
| 3142 | 1); | 3142 | 1); |
| 3143 | if (ret) { | 3143 | if (ret) { |
| 3144 | if (ret != -EINVAL) | 3144 | if (ret != -EOPNOTSUPP) |
| 3145 | btrfs_abort_transaction(trans, | 3145 | btrfs_abort_transaction(trans, |
| 3146 | root, ret); | 3146 | root, ret); |
| 3147 | btrfs_end_transaction(trans, root); | 3147 | btrfs_end_transaction(trans, root); |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 1ac3ca98c429..eb6537a08c1b 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
| @@ -349,6 +349,11 @@ static int fs_path_ensure_buf(struct fs_path *p, int len) | |||
| 349 | if (p->buf_len >= len) | 349 | if (p->buf_len >= len) |
| 350 | return 0; | 350 | return 0; |
| 351 | 351 | ||
| 352 | if (len > PATH_MAX) { | ||
| 353 | WARN_ON(1); | ||
| 354 | return -ENOMEM; | ||
| 355 | } | ||
| 356 | |||
| 352 | path_len = p->end - p->start; | 357 | path_len = p->end - p->start; |
| 353 | old_buf_len = p->buf_len; | 358 | old_buf_len = p->buf_len; |
| 354 | 359 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 5011aadacab8..9601d25a4607 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -385,20 +385,6 @@ static match_table_t tokens = { | |||
| 385 | {Opt_err, NULL}, | 385 | {Opt_err, NULL}, |
| 386 | }; | 386 | }; |
| 387 | 387 | ||
| 388 | #define btrfs_set_and_info(root, opt, fmt, args...) \ | ||
| 389 | { \ | ||
| 390 | if (!btrfs_test_opt(root, opt)) \ | ||
| 391 | btrfs_info(root->fs_info, fmt, ##args); \ | ||
| 392 | btrfs_set_opt(root->fs_info->mount_opt, opt); \ | ||
| 393 | } | ||
| 394 | |||
| 395 | #define btrfs_clear_and_info(root, opt, fmt, args...) \ | ||
| 396 | { \ | ||
| 397 | if (btrfs_test_opt(root, opt)) \ | ||
| 398 | btrfs_info(root->fs_info, fmt, ##args); \ | ||
| 399 | btrfs_clear_opt(root->fs_info->mount_opt, opt); \ | ||
| 400 | } | ||
| 401 | |||
| 402 | /* | 388 | /* |
| 403 | * Regular mount options parser. Everything that is needed only when | 389 | * Regular mount options parser. Everything that is needed only when |
| 404 | * reading in a new superblock is parsed here. | 390 | * reading in a new superblock is parsed here. |
| @@ -1186,7 +1172,6 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, | |||
| 1186 | return ERR_PTR(-ENOMEM); | 1172 | return ERR_PTR(-ENOMEM); |
| 1187 | mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, | 1173 | mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, |
| 1188 | newargs); | 1174 | newargs); |
| 1189 | kfree(newargs); | ||
| 1190 | 1175 | ||
| 1191 | if (PTR_RET(mnt) == -EBUSY) { | 1176 | if (PTR_RET(mnt) == -EBUSY) { |
| 1192 | if (flags & MS_RDONLY) { | 1177 | if (flags & MS_RDONLY) { |
| @@ -1196,17 +1181,22 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, | |||
| 1196 | int r; | 1181 | int r; |
| 1197 | mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name, | 1182 | mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name, |
| 1198 | newargs); | 1183 | newargs); |
| 1199 | if (IS_ERR(mnt)) | 1184 | if (IS_ERR(mnt)) { |
| 1185 | kfree(newargs); | ||
| 1200 | return ERR_CAST(mnt); | 1186 | return ERR_CAST(mnt); |
| 1187 | } | ||
| 1201 | 1188 | ||
| 1202 | r = btrfs_remount(mnt->mnt_sb, &flags, NULL); | 1189 | r = btrfs_remount(mnt->mnt_sb, &flags, NULL); |
| 1203 | if (r < 0) { | 1190 | if (r < 0) { |
| 1204 | /* FIXME: release vfsmount mnt ??*/ | 1191 | /* FIXME: release vfsmount mnt ??*/ |
| 1192 | kfree(newargs); | ||
| 1205 | return ERR_PTR(r); | 1193 | return ERR_PTR(r); |
| 1206 | } | 1194 | } |
| 1207 | } | 1195 | } |
| 1208 | } | 1196 | } |
| 1209 | 1197 | ||
| 1198 | kfree(newargs); | ||
| 1199 | |||
| 1210 | if (IS_ERR(mnt)) | 1200 | if (IS_ERR(mnt)) |
| 1211 | return ERR_CAST(mnt); | 1201 | return ERR_CAST(mnt); |
| 1212 | 1202 | ||
