Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "We've queued up a few fixes in my for-linus branch" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: fix crash when starting transaction Btrfs: fix btrfs_print_leaf for skinny metadata Btrfs: fix race of using total_bytes_pinned btrfs: use E2BIG instead of EIO if compression does not help btrfs: remove stale comment from btrfs_flush_all_pending_stuffs Btrfs: fix use-after-free when cloning a trailing file hole btrfs: fix null pointer dereference in btrfs_show_devname when name is null btrfs: fix null pointer dereference in clone_fs_devices when name is null btrfs: fix nossd and ssd_spread mount option regression Btrfs: fix race between balance recovery and root deletion Btrfs: atomically set inode->i_flags in btrfs_update_iflags btrfs: only unlock block in verify_parent_transid if we locked it Btrfs: assert send doesn't attempt to start transactions btrfs compression: reuse recently used workspace Btrfs: fix crash when mounting raid5 btrfs with missing disks btrfs: create sprout should rename fsid on the sysfs as well btrfs: dev replace should replace the sysfs entry btrfs: dev add should add its sysfs entry btrfs: dev delete should remove sysfs entry btrfs: rename add_device_membership to btrfs_kobj_add_device
This commit is contained in:
Коммит
b82207b8e8
|
@ -821,7 +821,7 @@ static void free_workspace(int type, struct list_head *workspace)
|
|||
|
||||
spin_lock(workspace_lock);
|
||||
if (*num_workspace < num_online_cpus()) {
|
||||
list_add_tail(workspace, idle_workspace);
|
||||
list_add(workspace, idle_workspace);
|
||||
(*num_workspace)++;
|
||||
spin_unlock(workspace_lock);
|
||||
goto wake;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "check-integrity.h"
|
||||
#include "rcu-string.h"
|
||||
#include "dev-replace.h"
|
||||
#include "sysfs.h"
|
||||
|
||||
static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
int scrub_ret);
|
||||
|
@ -562,6 +563,10 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
|||
fs_info->fs_devices->latest_bdev = tgt_device->bdev;
|
||||
list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);
|
||||
|
||||
/* replace the sysfs entry */
|
||||
btrfs_kobj_rm_device(fs_info, src_device);
|
||||
btrfs_kobj_add_device(fs_info, tgt_device);
|
||||
|
||||
btrfs_rm_dev_replace_blocked(fs_info);
|
||||
|
||||
btrfs_rm_dev_replace_srcdev(fs_info, src_device);
|
||||
|
|
|
@ -369,7 +369,8 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
|
|||
out:
|
||||
unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1,
|
||||
&cached_state, GFP_NOFS);
|
||||
btrfs_tree_read_unlock_blocking(eb);
|
||||
if (need_lock)
|
||||
btrfs_tree_read_unlock_blocking(eb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2904,7 +2905,9 @@ retry_root_backup:
|
|||
if (ret)
|
||||
goto fail_qgroup;
|
||||
|
||||
mutex_lock(&fs_info->cleaner_mutex);
|
||||
ret = btrfs_recover_relocation(tree_root);
|
||||
mutex_unlock(&fs_info->cleaner_mutex);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING
|
||||
"BTRFS: failed to recover relocation\n");
|
||||
|
|
|
@ -5678,7 +5678,6 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
|
|||
struct btrfs_caching_control *next;
|
||||
struct btrfs_caching_control *caching_ctl;
|
||||
struct btrfs_block_group_cache *cache;
|
||||
struct btrfs_space_info *space_info;
|
||||
|
||||
down_write(&fs_info->commit_root_sem);
|
||||
|
||||
|
@ -5701,9 +5700,6 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
|
|||
|
||||
up_write(&fs_info->commit_root_sem);
|
||||
|
||||
list_for_each_entry_rcu(space_info, &fs_info->space_info, list)
|
||||
percpu_counter_set(&space_info->total_bytes_pinned, 0);
|
||||
|
||||
update_global_block_rsv(fs_info);
|
||||
}
|
||||
|
||||
|
@ -5741,6 +5737,7 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
|
|||
spin_lock(&cache->lock);
|
||||
cache->pinned -= len;
|
||||
space_info->bytes_pinned -= len;
|
||||
percpu_counter_add(&space_info->total_bytes_pinned, -len);
|
||||
if (cache->ro) {
|
||||
space_info->bytes_readonly += len;
|
||||
readonly = true;
|
||||
|
|
|
@ -136,19 +136,22 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
|
|||
void btrfs_update_iflags(struct inode *inode)
|
||||
{
|
||||
struct btrfs_inode *ip = BTRFS_I(inode);
|
||||
|
||||
inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
|
||||
unsigned int new_fl = 0;
|
||||
|
||||
if (ip->flags & BTRFS_INODE_SYNC)
|
||||
inode->i_flags |= S_SYNC;
|
||||
new_fl |= S_SYNC;
|
||||
if (ip->flags & BTRFS_INODE_IMMUTABLE)
|
||||
inode->i_flags |= S_IMMUTABLE;
|
||||
new_fl |= S_IMMUTABLE;
|
||||
if (ip->flags & BTRFS_INODE_APPEND)
|
||||
inode->i_flags |= S_APPEND;
|
||||
new_fl |= S_APPEND;
|
||||
if (ip->flags & BTRFS_INODE_NOATIME)
|
||||
inode->i_flags |= S_NOATIME;
|
||||
new_fl |= S_NOATIME;
|
||||
if (ip->flags & BTRFS_INODE_DIRSYNC)
|
||||
inode->i_flags |= S_DIRSYNC;
|
||||
new_fl |= S_DIRSYNC;
|
||||
|
||||
set_mask_bits(&inode->i_flags,
|
||||
S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | S_DIRSYNC,
|
||||
new_fl);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3139,7 +3142,6 @@ out:
|
|||
static void clone_update_extent_map(struct inode *inode,
|
||||
const struct btrfs_trans_handle *trans,
|
||||
const struct btrfs_path *path,
|
||||
struct btrfs_file_extent_item *fi,
|
||||
const u64 hole_offset,
|
||||
const u64 hole_len)
|
||||
{
|
||||
|
@ -3154,7 +3156,11 @@ static void clone_update_extent_map(struct inode *inode,
|
|||
return;
|
||||
}
|
||||
|
||||
if (fi) {
|
||||
if (path) {
|
||||
struct btrfs_file_extent_item *fi;
|
||||
|
||||
fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_extent_item_to_extent_map(inode, path, fi, false, em);
|
||||
em->generation = -1;
|
||||
if (btrfs_file_extent_type(path->nodes[0], fi) ==
|
||||
|
@ -3508,18 +3514,15 @@ process_slot:
|
|||
btrfs_item_ptr_offset(leaf, slot),
|
||||
size);
|
||||
inode_add_bytes(inode, datal);
|
||||
extent = btrfs_item_ptr(leaf, slot,
|
||||
struct btrfs_file_extent_item);
|
||||
}
|
||||
|
||||
/* If we have an implicit hole (NO_HOLES feature). */
|
||||
if (drop_start < new_key.offset)
|
||||
clone_update_extent_map(inode, trans,
|
||||
path, NULL, drop_start,
|
||||
NULL, drop_start,
|
||||
new_key.offset - drop_start);
|
||||
|
||||
clone_update_extent_map(inode, trans, path,
|
||||
extent, 0, 0);
|
||||
clone_update_extent_map(inode, trans, path, 0, 0);
|
||||
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
btrfs_release_path(path);
|
||||
|
@ -3562,12 +3565,10 @@ process_slot:
|
|||
btrfs_end_transaction(trans, root);
|
||||
goto out;
|
||||
}
|
||||
clone_update_extent_map(inode, trans, NULL, last_dest_end,
|
||||
destoff + len - last_dest_end);
|
||||
ret = clone_finish_inode_update(trans, inode, destoff + len,
|
||||
destoff, olen);
|
||||
if (ret)
|
||||
goto out;
|
||||
clone_update_extent_map(inode, trans, path, NULL, last_dest_end,
|
||||
destoff + len - last_dest_end);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -54,7 +54,7 @@ static void print_extent_data_ref(struct extent_buffer *eb,
|
|||
btrfs_extent_data_ref_count(eb, ref));
|
||||
}
|
||||
|
||||
static void print_extent_item(struct extent_buffer *eb, int slot)
|
||||
static void print_extent_item(struct extent_buffer *eb, int slot, int type)
|
||||
{
|
||||
struct btrfs_extent_item *ei;
|
||||
struct btrfs_extent_inline_ref *iref;
|
||||
|
@ -63,7 +63,6 @@ static void print_extent_item(struct extent_buffer *eb, int slot)
|
|||
struct btrfs_disk_key key;
|
||||
unsigned long end;
|
||||
unsigned long ptr;
|
||||
int type;
|
||||
u32 item_size = btrfs_item_size_nr(eb, slot);
|
||||
u64 flags;
|
||||
u64 offset;
|
||||
|
@ -88,7 +87,8 @@ static void print_extent_item(struct extent_buffer *eb, int slot)
|
|||
btrfs_extent_refs(eb, ei), btrfs_extent_generation(eb, ei),
|
||||
flags);
|
||||
|
||||
if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
|
||||
if ((type == BTRFS_EXTENT_ITEM_KEY) &&
|
||||
flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
|
||||
struct btrfs_tree_block_info *info;
|
||||
info = (struct btrfs_tree_block_info *)(ei + 1);
|
||||
btrfs_tree_block_key(eb, info, &key);
|
||||
|
@ -223,7 +223,8 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
|
|||
btrfs_disk_root_refs(l, ri));
|
||||
break;
|
||||
case BTRFS_EXTENT_ITEM_KEY:
|
||||
print_extent_item(l, i);
|
||||
case BTRFS_METADATA_ITEM_KEY:
|
||||
print_extent_item(l, i, type);
|
||||
break;
|
||||
case BTRFS_TREE_BLOCK_REF_KEY:
|
||||
printk(KERN_INFO "\t\ttree block backref\n");
|
||||
|
|
|
@ -1956,9 +1956,10 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
|
|||
* pages are going to be uptodate.
|
||||
*/
|
||||
for (stripe = 0; stripe < bbio->num_stripes; stripe++) {
|
||||
if (rbio->faila == stripe ||
|
||||
rbio->failb == stripe)
|
||||
if (rbio->faila == stripe || rbio->failb == stripe) {
|
||||
atomic_inc(&rbio->bbio->error);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (pagenr = 0; pagenr < nr_pages; pagenr++) {
|
||||
struct page *p;
|
||||
|
|
|
@ -522,9 +522,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
case Opt_ssd_spread:
|
||||
btrfs_set_and_info(root, SSD_SPREAD,
|
||||
"use spread ssd allocation scheme");
|
||||
btrfs_set_opt(info->mount_opt, SSD);
|
||||
break;
|
||||
case Opt_nossd:
|
||||
btrfs_clear_and_info(root, NOSSD,
|
||||
btrfs_set_and_info(root, NOSSD,
|
||||
"not using ssd allocation scheme");
|
||||
btrfs_clear_opt(info->mount_opt, SSD);
|
||||
break;
|
||||
|
@ -1467,7 +1468,9 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
|
|||
goto restore;
|
||||
|
||||
/* recover relocation */
|
||||
mutex_lock(&fs_info->cleaner_mutex);
|
||||
ret = btrfs_recover_relocation(root);
|
||||
mutex_unlock(&fs_info->cleaner_mutex);
|
||||
if (ret)
|
||||
goto restore;
|
||||
|
||||
|
@ -1808,6 +1811,8 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
|
|||
list_for_each_entry(dev, head, dev_list) {
|
||||
if (dev->missing)
|
||||
continue;
|
||||
if (!dev->name)
|
||||
continue;
|
||||
if (!first_dev || dev->devid < first_dev->devid)
|
||||
first_dev = dev;
|
||||
}
|
||||
|
|
|
@ -605,14 +605,37 @@ static void init_feature_attrs(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int add_device_membership(struct btrfs_fs_info *fs_info)
|
||||
int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_device *one_device)
|
||||
{
|
||||
struct hd_struct *disk;
|
||||
struct kobject *disk_kobj;
|
||||
|
||||
if (!fs_info->device_dir_kobj)
|
||||
return -EINVAL;
|
||||
|
||||
if (one_device) {
|
||||
disk = one_device->bdev->bd_part;
|
||||
disk_kobj = &part_to_dev(disk)->kobj;
|
||||
|
||||
sysfs_remove_link(fs_info->device_dir_kobj,
|
||||
disk_kobj->name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_device *one_device)
|
||||
{
|
||||
int error = 0;
|
||||
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
|
||||
struct btrfs_device *dev;
|
||||
|
||||
fs_info->device_dir_kobj = kobject_create_and_add("devices",
|
||||
if (!fs_info->device_dir_kobj)
|
||||
fs_info->device_dir_kobj = kobject_create_and_add("devices",
|
||||
&fs_info->super_kobj);
|
||||
|
||||
if (!fs_info->device_dir_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -623,6 +646,9 @@ static int add_device_membership(struct btrfs_fs_info *fs_info)
|
|||
if (!dev->bdev)
|
||||
continue;
|
||||
|
||||
if (one_device && one_device != dev)
|
||||
continue;
|
||||
|
||||
disk = dev->bdev->bd_part;
|
||||
disk_kobj = &part_to_dev(disk)->kobj;
|
||||
|
||||
|
@ -666,7 +692,7 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
|
|||
if (error)
|
||||
goto failure;
|
||||
|
||||
error = add_device_membership(fs_info);
|
||||
error = btrfs_kobj_add_device(fs_info, NULL);
|
||||
if (error)
|
||||
goto failure;
|
||||
|
||||
|
|
|
@ -66,4 +66,8 @@ char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
|
|||
extern const char * const btrfs_feature_set_names[3];
|
||||
extern struct kobj_type space_info_ktype;
|
||||
extern struct kobj_type btrfs_raid_ktype;
|
||||
int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_device *one_device);
|
||||
int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_device *one_device);
|
||||
#endif /* _BTRFS_SYSFS_H_ */
|
||||
|
|
|
@ -386,11 +386,13 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type,
|
|||
bool reloc_reserved = false;
|
||||
int ret;
|
||||
|
||||
/* Send isn't supposed to start transactions. */
|
||||
ASSERT(current->journal_info != (void *)BTRFS_SEND_TRANS_STUB);
|
||||
|
||||
if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
|
||||
return ERR_PTR(-EROFS);
|
||||
|
||||
if (current->journal_info &&
|
||||
current->journal_info != (void *)BTRFS_SEND_TRANS_STUB) {
|
||||
if (current->journal_info) {
|
||||
WARN_ON(type & TRANS_EXTWRITERS);
|
||||
h = current->journal_info;
|
||||
h->use_count++;
|
||||
|
@ -491,6 +493,7 @@ again:
|
|||
smp_mb();
|
||||
if (cur_trans->state >= TRANS_STATE_BLOCKED &&
|
||||
may_wait_transaction(root, type)) {
|
||||
current->journal_info = h;
|
||||
btrfs_commit_transaction(h, root);
|
||||
goto again;
|
||||
}
|
||||
|
@ -1615,11 +1618,6 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans,
|
|||
int ret;
|
||||
|
||||
ret = btrfs_run_delayed_items(trans, root);
|
||||
/*
|
||||
* running the delayed items may have added new refs. account
|
||||
* them now so that they hinder processing of more delayed refs
|
||||
* as little as possible.
|
||||
*/
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "rcu-string.h"
|
||||
#include "math.h"
|
||||
#include "dev-replace.h"
|
||||
#include "sysfs.h"
|
||||
|
||||
static int init_first_rw_device(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
|
@ -554,12 +555,14 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
|
|||
* This is ok to do without rcu read locked because we hold the
|
||||
* uuid mutex so nothing we touch in here is going to disappear.
|
||||
*/
|
||||
name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS);
|
||||
if (!name) {
|
||||
kfree(device);
|
||||
goto error;
|
||||
if (orig_dev->name) {
|
||||
name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS);
|
||||
if (!name) {
|
||||
kfree(device);
|
||||
goto error;
|
||||
}
|
||||
rcu_assign_pointer(device->name, name);
|
||||
}
|
||||
rcu_assign_pointer(device->name, name);
|
||||
|
||||
list_add(&device->dev_list, &fs_devices->devices);
|
||||
device->fs_devices = fs_devices;
|
||||
|
@ -1680,6 +1683,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
|
|||
if (device->bdev)
|
||||
device->fs_devices->open_devices--;
|
||||
|
||||
/* remove sysfs entry */
|
||||
btrfs_kobj_rm_device(root->fs_info, device);
|
||||
|
||||
call_rcu(&device->rcu, free_device);
|
||||
|
||||
num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1;
|
||||
|
@ -2143,9 +2149,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
|||
total_bytes = btrfs_super_num_devices(root->fs_info->super_copy);
|
||||
btrfs_set_super_num_devices(root->fs_info->super_copy,
|
||||
total_bytes + 1);
|
||||
|
||||
/* add sysfs device entry */
|
||||
btrfs_kobj_add_device(root->fs_info, device);
|
||||
|
||||
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
|
||||
|
||||
if (seeding_dev) {
|
||||
char fsid_buf[BTRFS_UUID_UNPARSED_SIZE];
|
||||
ret = init_first_rw_device(trans, root, device);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
|
@ -2156,6 +2167,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
|||
btrfs_abort_transaction(trans, root, ret);
|
||||
goto error_trans;
|
||||
}
|
||||
|
||||
/* Sprouting would change fsid of the mounted root,
|
||||
* so rename the fsid on the sysfs
|
||||
*/
|
||||
snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU",
|
||||
root->fs_info->fsid);
|
||||
if (kobject_rename(&root->fs_info->super_kobj, fsid_buf))
|
||||
goto error_trans;
|
||||
} else {
|
||||
ret = btrfs_add_device(trans, root, device);
|
||||
if (ret) {
|
||||
|
@ -2205,6 +2224,7 @@ error_trans:
|
|||
unlock_chunks(root);
|
||||
btrfs_end_transaction(trans, root);
|
||||
rcu_string_free(device->name);
|
||||
btrfs_kobj_rm_device(root->fs_info, device);
|
||||
kfree(device);
|
||||
error:
|
||||
blkdev_put(bdev, FMODE_EXCL);
|
||||
|
|
|
@ -136,7 +136,7 @@ static int zlib_compress_pages(struct list_head *ws,
|
|||
if (workspace->def_strm.total_in > 8192 &&
|
||||
workspace->def_strm.total_in <
|
||||
workspace->def_strm.total_out) {
|
||||
ret = -EIO;
|
||||
ret = -E2BIG;
|
||||
goto out;
|
||||
}
|
||||
/* we need another page for writing out. Test this
|
||||
|
|
|
@ -38,6 +38,7 @@ struct btrfs_ioctl_vol_args {
|
|||
#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2)
|
||||
#define BTRFS_FSID_SIZE 16
|
||||
#define BTRFS_UUID_SIZE 16
|
||||
#define BTRFS_UUID_UNPARSED_SIZE 37
|
||||
|
||||
#define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче