mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
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()
This commit is contained in:
commit
33c0022f0e
@ -2058,6 +2058,20 @@ struct btrfs_ioctl_defrag_range_args {
|
||||
#define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt)
|
||||
#define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
|
||||
BTRFS_MOUNT_##opt)
|
||||
#define btrfs_set_and_info(root, opt, fmt, args...) \
|
||||
{ \
|
||||
if (!btrfs_test_opt(root, opt)) \
|
||||
btrfs_info(root->fs_info, fmt, ##args); \
|
||||
btrfs_set_opt(root->fs_info->mount_opt, opt); \
|
||||
}
|
||||
|
||||
#define btrfs_clear_and_info(root, opt, fmt, args...) \
|
||||
{ \
|
||||
if (btrfs_test_opt(root, opt)) \
|
||||
btrfs_info(root->fs_info, fmt, ##args); \
|
||||
btrfs_clear_opt(root->fs_info->mount_opt, opt); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Inode flags
|
||||
*/
|
||||
|
@ -2861,7 +2861,7 @@ retry_root_backup:
|
||||
printk(KERN_ERR "BTRFS: failed to read log tree\n");
|
||||
free_extent_buffer(log_tree_root->node);
|
||||
kfree(log_tree_root);
|
||||
goto fail_trans_kthread;
|
||||
goto fail_qgroup;
|
||||
}
|
||||
/* returns with log_tree_root freed on success */
|
||||
ret = btrfs_recover_log_trees(log_tree_root);
|
||||
@ -2870,24 +2870,24 @@ retry_root_backup:
|
||||
"Failed to recover log tree");
|
||||
free_extent_buffer(log_tree_root->node);
|
||||
kfree(log_tree_root);
|
||||
goto fail_trans_kthread;
|
||||
goto fail_qgroup;
|
||||
}
|
||||
|
||||
if (sb->s_flags & MS_RDONLY) {
|
||||
ret = btrfs_commit_super(tree_root);
|
||||
if (ret)
|
||||
goto fail_trans_kthread;
|
||||
goto fail_qgroup;
|
||||
}
|
||||
}
|
||||
|
||||
ret = btrfs_find_orphan_roots(tree_root);
|
||||
if (ret)
|
||||
goto fail_trans_kthread;
|
||||
goto fail_qgroup;
|
||||
|
||||
if (!(sb->s_flags & MS_RDONLY)) {
|
||||
ret = btrfs_cleanup_fs_roots(fs_info);
|
||||
if (ret)
|
||||
goto fail_trans_kthread;
|
||||
goto fail_qgroup;
|
||||
|
||||
ret = btrfs_recover_relocation(tree_root);
|
||||
if (ret < 0) {
|
||||
|
@ -1542,6 +1542,7 @@ again:
|
||||
ret = 0;
|
||||
}
|
||||
if (ret) {
|
||||
key.objectid = bytenr;
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
key.offset = num_bytes;
|
||||
btrfs_release_path(path);
|
||||
@ -3542,11 +3543,13 @@ static u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
|
||||
return extended_to_chunk(flags | tmp);
|
||||
}
|
||||
|
||||
static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
|
||||
static u64 get_alloc_profile(struct btrfs_root *root, u64 orig_flags)
|
||||
{
|
||||
unsigned seq;
|
||||
u64 flags;
|
||||
|
||||
do {
|
||||
flags = orig_flags;
|
||||
seq = read_seqbegin(&root->fs_info->profiles_lock);
|
||||
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
@ -5719,6 +5722,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
|
||||
if (ret > 0 && skinny_metadata) {
|
||||
skinny_metadata = false;
|
||||
key.objectid = bytenr;
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
key.offset = num_bytes;
|
||||
btrfs_release_path(path);
|
||||
|
@ -800,7 +800,7 @@ next_slot:
|
||||
if (start > key.offset && end < extent_end) {
|
||||
BUG_ON(del_nr > 0);
|
||||
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
ret = -EINVAL;
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -846,7 +846,7 @@ next_slot:
|
||||
*/
|
||||
if (start <= key.offset && end < extent_end) {
|
||||
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
ret = -EINVAL;
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -872,7 +872,7 @@ next_slot:
|
||||
if (start > key.offset && end >= extent_end) {
|
||||
BUG_ON(del_nr > 0);
|
||||
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
ret = -EINVAL;
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1777,7 +1777,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
|
||||
start_pos = round_down(pos, root->sectorsize);
|
||||
if (start_pos > i_size_read(inode)) {
|
||||
/* Expand hole size to cover write data, preventing empty gap */
|
||||
end_pos = round_up(pos + iov->iov_len, root->sectorsize);
|
||||
end_pos = round_up(pos + count, root->sectorsize);
|
||||
err = btrfs_cont_expand(inode, i_size_read(inode), end_pos);
|
||||
if (err) {
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
@ -176,7 +176,11 @@ static void start_caching(struct btrfs_root *root)
|
||||
|
||||
tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n",
|
||||
root->root_key.objectid);
|
||||
BUG_ON(IS_ERR(tsk)); /* -ENOMEM */
|
||||
if (IS_ERR(tsk)) {
|
||||
btrfs_warn(root->fs_info, "failed to start inode caching task");
|
||||
btrfs_clear_and_info(root, CHANGE_INODE_CACHE,
|
||||
"disabling inode map caching");
|
||||
}
|
||||
}
|
||||
|
||||
int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)
|
||||
@ -205,24 +209,14 @@ again:
|
||||
|
||||
void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
|
||||
{
|
||||
struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
|
||||
struct btrfs_free_space_ctl *pinned = root->free_ino_pinned;
|
||||
|
||||
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
|
||||
return;
|
||||
|
||||
again:
|
||||
if (root->cached == BTRFS_CACHE_FINISHED) {
|
||||
__btrfs_add_free_space(ctl, objectid, 1);
|
||||
__btrfs_add_free_space(pinned, objectid, 1);
|
||||
} else {
|
||||
/*
|
||||
* If we are in the process of caching free ino chunks,
|
||||
* to avoid adding the same inode number to the free_ino
|
||||
* tree twice due to cross transaction, we'll leave it
|
||||
* in the pinned tree until a transaction is committed
|
||||
* or the caching work is done.
|
||||
*/
|
||||
|
||||
down_write(&root->fs_info->commit_root_sem);
|
||||
spin_lock(&root->cache_lock);
|
||||
if (root->cached == BTRFS_CACHE_FINISHED) {
|
||||
@ -234,11 +228,7 @@ again:
|
||||
|
||||
start_caching(root);
|
||||
|
||||
if (objectid <= root->cache_progress ||
|
||||
objectid >= root->highest_objectid)
|
||||
__btrfs_add_free_space(ctl, objectid, 1);
|
||||
else
|
||||
__btrfs_add_free_space(pinned, objectid, 1);
|
||||
__btrfs_add_free_space(pinned, objectid, 1);
|
||||
|
||||
up_write(&root->fs_info->commit_root_sem);
|
||||
}
|
||||
|
@ -3066,7 +3066,7 @@ process_slot:
|
||||
new_key.offset + datal,
|
||||
1);
|
||||
if (ret) {
|
||||
if (ret != -EINVAL)
|
||||
if (ret != -EOPNOTSUPP)
|
||||
btrfs_abort_transaction(trans,
|
||||
root, ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
@ -3141,7 +3141,7 @@ process_slot:
|
||||
new_key.offset + datal,
|
||||
1);
|
||||
if (ret) {
|
||||
if (ret != -EINVAL)
|
||||
if (ret != -EOPNOTSUPP)
|
||||
btrfs_abort_transaction(trans,
|
||||
root, ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
|
@ -349,6 +349,11 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
|
||||
if (p->buf_len >= len)
|
||||
return 0;
|
||||
|
||||
if (len > PATH_MAX) {
|
||||
WARN_ON(1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
path_len = p->end - p->start;
|
||||
old_buf_len = p->buf_len;
|
||||
|
||||
|
@ -385,20 +385,6 @@ static match_table_t tokens = {
|
||||
{Opt_err, NULL},
|
||||
};
|
||||
|
||||
#define btrfs_set_and_info(root, opt, fmt, args...) \
|
||||
{ \
|
||||
if (!btrfs_test_opt(root, opt)) \
|
||||
btrfs_info(root->fs_info, fmt, ##args); \
|
||||
btrfs_set_opt(root->fs_info->mount_opt, opt); \
|
||||
}
|
||||
|
||||
#define btrfs_clear_and_info(root, opt, fmt, args...) \
|
||||
{ \
|
||||
if (btrfs_test_opt(root, opt)) \
|
||||
btrfs_info(root->fs_info, fmt, ##args); \
|
||||
btrfs_clear_opt(root->fs_info->mount_opt, opt); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Regular mount options parser. Everything that is needed only when
|
||||
* reading in a new superblock is parsed here.
|
||||
@ -1186,7 +1172,6 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name,
|
||||
newargs);
|
||||
kfree(newargs);
|
||||
|
||||
if (PTR_RET(mnt) == -EBUSY) {
|
||||
if (flags & MS_RDONLY) {
|
||||
@ -1196,17 +1181,22 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
|
||||
int r;
|
||||
mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name,
|
||||
newargs);
|
||||
if (IS_ERR(mnt))
|
||||
if (IS_ERR(mnt)) {
|
||||
kfree(newargs);
|
||||
return ERR_CAST(mnt);
|
||||
}
|
||||
|
||||
r = btrfs_remount(mnt->mnt_sb, &flags, NULL);
|
||||
if (r < 0) {
|
||||
/* FIXME: release vfsmount mnt ??*/
|
||||
kfree(newargs);
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kfree(newargs);
|
||||
|
||||
if (IS_ERR(mnt))
|
||||
return ERR_CAST(mnt);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user