Skip to content

Commit

Permalink
Merge tag 'for-5.6-rc1-tag' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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
  • Loading branch information
torvalds committed Feb 16, 2020
2 parents 288b27a + 1b9867e commit 713db35
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -3164,6 +3164,7 @@ int __cold open_ctree(struct super_block *sb,
/* do not make disk changes in broken FS or nologreplay is given */
if (btrfs_super_log_root(disk_super) != 0 &&
!btrfs_test_opt(fs_info, NOLOGREPLAY)) {
btrfs_info(fs_info, "start tree-log replay");
ret = btrfs_replay_log(fs_info, fs_devices);
if (ret) {
err = ret;
Expand Down
11 changes: 11 additions & 0 deletions fs/btrfs/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,17 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
struct extent_map *merge = NULL;
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) {
rb = rb_prev(&em->rb_node);
if (rb)
Expand Down
8 changes: 8 additions & 0 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -4085,6 +4085,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
u64 bytes_deleted = 0;
bool be_nice = 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);

Expand All @@ -4101,6 +4103,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
return -ENOMEM;
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
* not block aligned since we will be keeping the last block of the
Expand Down Expand Up @@ -4367,6 +4372,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
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);
return ret;
}
Expand Down
5 changes: 5 additions & 0 deletions fs/btrfs/ref-verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (IS_ERR(be)) {
kfree(ref);
kfree(ra);
ret = PTR_ERR(be);
goto out;
Expand All @@ -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!");
dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra);
kfree(ref);
kfree(ra);
goto out_unlock;
}

Expand Down Expand Up @@ -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");
dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra);
kfree(ref);
kfree(ra);
goto out_unlock;
}
Expand All @@ -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");
dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra);
kfree(ref);
kfree(ra);
goto out_unlock;
}
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
btrfs_warn(fs_info,
"mount required to replay tree-log, cannot remount read-write");
ret = -EINVAL;
goto restore;
}
Expand Down
17 changes: 16 additions & 1 deletion fs/btrfs/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
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) {
kobject_del(fs_devs->devices_kobj);
kobject_put(fs_devs->devices_kobj);
Expand Down Expand Up @@ -1289,7 +1295,7 @@ int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,

init_completion(&dev->kobj_unregister);
error = kobject_init_and_add(&dev->devid_kobj, &devid_ktype,
fs_devices->devices_kobj, "%llu",
fs_devices->devinfo_kobj, "%llu",
dev->devid);
if (error) {
kobject_put(&dev->devid_kobj);
Expand Down Expand Up @@ -1369,6 +1375,15 @@ int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs)
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;
}

Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/volumes.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ struct btrfs_fs_devices {
/* sysfs kobjects */
struct kobject fsid_kobj;
struct kobject *devices_kobj;
struct kobject *devinfo_kobj;
struct completion kobj_unregister;
};

Expand Down

0 comments on commit 713db35

Please sign in to comment.