Commit 713db356 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-5.6-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:
 "Two races fixed, memory leak fix, sysfs directory fixup and two new
  log messages:

   - two fixed race conditions: extent map merging and truncate vs
     fiemap

   - create the right sysfs directory with device information and move
     the individual device dirs under it

   - print messages when the tree-log is replayed at mount time or
     cannot be replayed on remount"

* tag 'for-5.6-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: sysfs, move device id directories to UUID/devinfo
  btrfs: sysfs, add UUID/devinfo kobject
  Btrfs: fix race between shrinking truncate and fiemap
  btrfs: log message when rw remount is attempted with unclean tree-log
  btrfs: print message when tree-log replay starts
  Btrfs: fix race between using extent maps and merging them
  btrfs: ref-verify: fix memory leaks
parents 288b27a0 1b9867eb
...@@ -3164,6 +3164,7 @@ int __cold open_ctree(struct super_block *sb, ...@@ -3164,6 +3164,7 @@ int __cold open_ctree(struct super_block *sb,
/* do not make disk changes in broken FS or nologreplay is given */ /* do not make disk changes in broken FS or nologreplay is given */
if (btrfs_super_log_root(disk_super) != 0 && if (btrfs_super_log_root(disk_super) != 0 &&
!btrfs_test_opt(fs_info, NOLOGREPLAY)) { !btrfs_test_opt(fs_info, NOLOGREPLAY)) {
btrfs_info(fs_info, "start tree-log replay");
ret = btrfs_replay_log(fs_info, fs_devices); ret = btrfs_replay_log(fs_info, fs_devices);
if (ret) { if (ret) {
err = ret; err = ret;
......
...@@ -237,6 +237,17 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em) ...@@ -237,6 +237,17 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
struct extent_map *merge = NULL; struct extent_map *merge = NULL;
struct rb_node *rb; struct rb_node *rb;
/*
* We can't modify an extent map that is in the tree and that is being
* used by another task, as it can cause that other task to see it in
* inconsistent state during the merging. We always have 1 reference for
* the tree and 1 for this task (which is unpinning the extent map or
* clearing the logging flag), so anything > 2 means it's being used by
* other tasks too.
*/
if (refcount_read(&em->refs) > 2)
return;
if (em->start != 0) { if (em->start != 0) {
rb = rb_prev(&em->rb_node); rb = rb_prev(&em->rb_node);
if (rb) if (rb)
......
...@@ -4085,6 +4085,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -4085,6 +4085,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
u64 bytes_deleted = 0; u64 bytes_deleted = 0;
bool be_nice = false; bool be_nice = false;
bool should_throttle = false; bool should_throttle = false;
const u64 lock_start = ALIGN_DOWN(new_size, fs_info->sectorsize);
struct extent_state *cached_state = NULL;
BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY); BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
...@@ -4101,6 +4103,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -4101,6 +4103,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
return -ENOMEM; return -ENOMEM;
path->reada = READA_BACK; path->reada = READA_BACK;
lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
&cached_state);
/* /*
* We want to drop from the next block forward in case this new size is * We want to drop from the next block forward in case this new size is
* not block aligned since we will be keeping the last block of the * not block aligned since we will be keeping the last block of the
...@@ -4367,6 +4372,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -4367,6 +4372,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
btrfs_ordered_update_i_size(inode, last_size, NULL); btrfs_ordered_update_i_size(inode, last_size, NULL);
} }
unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
&cached_state);
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
} }
......
...@@ -744,6 +744,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, ...@@ -744,6 +744,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
*/ */
be = add_block_entry(fs_info, bytenr, num_bytes, ref_root); be = add_block_entry(fs_info, bytenr, num_bytes, ref_root);
if (IS_ERR(be)) { if (IS_ERR(be)) {
kfree(ref);
kfree(ra); kfree(ra);
ret = PTR_ERR(be); ret = PTR_ERR(be);
goto out; goto out;
...@@ -757,6 +758,8 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, ...@@ -757,6 +758,8 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
"re-allocated a block that still has references to it!"); "re-allocated a block that still has references to it!");
dump_block_entry(fs_info, be); dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra); dump_ref_action(fs_info, ra);
kfree(ref);
kfree(ra);
goto out_unlock; goto out_unlock;
} }
...@@ -819,6 +822,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, ...@@ -819,6 +822,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
"dropping a ref for a existing root that doesn't have a ref on the block"); "dropping a ref for a existing root that doesn't have a ref on the block");
dump_block_entry(fs_info, be); dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra); dump_ref_action(fs_info, ra);
kfree(ref);
kfree(ra); kfree(ra);
goto out_unlock; goto out_unlock;
} }
...@@ -834,6 +838,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, ...@@ -834,6 +838,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
"attempting to add another ref for an existing ref on a tree block"); "attempting to add another ref for an existing ref on a tree block");
dump_block_entry(fs_info, be); dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra); dump_ref_action(fs_info, ra);
kfree(ref);
kfree(ra); kfree(ra);
goto out_unlock; goto out_unlock;
} }
......
...@@ -1834,6 +1834,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1834,6 +1834,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
} }
if (btrfs_super_log_root(fs_info->super_copy) != 0) { if (btrfs_super_log_root(fs_info->super_copy) != 0) {
btrfs_warn(fs_info,
"mount required to replay tree-log, cannot remount read-write");
ret = -EINVAL; ret = -EINVAL;
goto restore; goto restore;
} }
......
...@@ -901,6 +901,12 @@ static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) ...@@ -901,6 +901,12 @@ static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add)
static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
{ {
if (fs_devs->devinfo_kobj) {
kobject_del(fs_devs->devinfo_kobj);
kobject_put(fs_devs->devinfo_kobj);
fs_devs->devinfo_kobj = NULL;
}
if (fs_devs->devices_kobj) { if (fs_devs->devices_kobj) {
kobject_del(fs_devs->devices_kobj); kobject_del(fs_devs->devices_kobj);
kobject_put(fs_devs->devices_kobj); kobject_put(fs_devs->devices_kobj);
...@@ -1289,7 +1295,7 @@ int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices, ...@@ -1289,7 +1295,7 @@ int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
init_completion(&dev->kobj_unregister); init_completion(&dev->kobj_unregister);
error = kobject_init_and_add(&dev->devid_kobj, &devid_ktype, error = kobject_init_and_add(&dev->devid_kobj, &devid_ktype,
fs_devices->devices_kobj, "%llu", fs_devices->devinfo_kobj, "%llu",
dev->devid); dev->devid);
if (error) { if (error) {
kobject_put(&dev->devid_kobj); kobject_put(&dev->devid_kobj);
...@@ -1369,6 +1375,15 @@ int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) ...@@ -1369,6 +1375,15 @@ int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs)
return -ENOMEM; return -ENOMEM;
} }
fs_devs->devinfo_kobj = kobject_create_and_add("devinfo",
&fs_devs->fsid_kobj);
if (!fs_devs->devinfo_kobj) {
btrfs_err(fs_devs->fs_info,
"failed to init sysfs devinfo kobject");
btrfs_sysfs_remove_fsid(fs_devs);
return -ENOMEM;
}
return 0; return 0;
} }
......
...@@ -258,6 +258,7 @@ struct btrfs_fs_devices { ...@@ -258,6 +258,7 @@ struct btrfs_fs_devices {
/* sysfs kobjects */ /* sysfs kobjects */
struct kobject fsid_kobj; struct kobject fsid_kobj;
struct kobject *devices_kobj; struct kobject *devices_kobj;
struct kobject *devinfo_kobj;
struct completion kobj_unregister; struct completion kobj_unregister;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment