Skip to content

Commit 713db35

Browse files
committed
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
2 parents 288b27a + 1b9867e commit 713db35

File tree

7 files changed

+44
-1
lines changed

7 files changed

+44
-1
lines changed

fs/btrfs/disk-io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3164,6 +3164,7 @@ int __cold open_ctree(struct super_block *sb,
31643164
/* do not make disk changes in broken FS or nologreplay is given */
31653165
if (btrfs_super_log_root(disk_super) != 0 &&
31663166
!btrfs_test_opt(fs_info, NOLOGREPLAY)) {
3167+
btrfs_info(fs_info, "start tree-log replay");
31673168
ret = btrfs_replay_log(fs_info, fs_devices);
31683169
if (ret) {
31693170
err = ret;

fs/btrfs/extent_map.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,17 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
237237
struct extent_map *merge = NULL;
238238
struct rb_node *rb;
239239

240+
/*
241+
* We can't modify an extent map that is in the tree and that is being
242+
* used by another task, as it can cause that other task to see it in
243+
* inconsistent state during the merging. We always have 1 reference for
244+
* the tree and 1 for this task (which is unpinning the extent map or
245+
* clearing the logging flag), so anything > 2 means it's being used by
246+
* other tasks too.
247+
*/
248+
if (refcount_read(&em->refs) > 2)
249+
return;
250+
240251
if (em->start != 0) {
241252
rb = rb_prev(&em->rb_node);
242253
if (rb)

fs/btrfs/inode.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4085,6 +4085,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
40854085
u64 bytes_deleted = 0;
40864086
bool be_nice = false;
40874087
bool should_throttle = false;
4088+
const u64 lock_start = ALIGN_DOWN(new_size, fs_info->sectorsize);
4089+
struct extent_state *cached_state = NULL;
40884090

40894091
BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
40904092

@@ -4101,6 +4103,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
41014103
return -ENOMEM;
41024104
path->reada = READA_BACK;
41034105

4106+
lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
4107+
&cached_state);
4108+
41044109
/*
41054110
* We want to drop from the next block forward in case this new size is
41064111
* 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,
43674372
btrfs_ordered_update_i_size(inode, last_size, NULL);
43684373
}
43694374

4375+
unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
4376+
&cached_state);
4377+
43704378
btrfs_free_path(path);
43714379
return ret;
43724380
}

fs/btrfs/ref-verify.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
744744
*/
745745
be = add_block_entry(fs_info, bytenr, num_bytes, ref_root);
746746
if (IS_ERR(be)) {
747+
kfree(ref);
747748
kfree(ra);
748749
ret = PTR_ERR(be);
749750
goto out;
@@ -757,6 +758,8 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
757758
"re-allocated a block that still has references to it!");
758759
dump_block_entry(fs_info, be);
759760
dump_ref_action(fs_info, ra);
761+
kfree(ref);
762+
kfree(ra);
760763
goto out_unlock;
761764
}
762765

@@ -819,6 +822,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
819822
"dropping a ref for a existing root that doesn't have a ref on the block");
820823
dump_block_entry(fs_info, be);
821824
dump_ref_action(fs_info, ra);
825+
kfree(ref);
822826
kfree(ra);
823827
goto out_unlock;
824828
}
@@ -834,6 +838,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
834838
"attempting to add another ref for an existing ref on a tree block");
835839
dump_block_entry(fs_info, be);
836840
dump_ref_action(fs_info, ra);
841+
kfree(ref);
837842
kfree(ra);
838843
goto out_unlock;
839844
}

fs/btrfs/super.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,6 +1834,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
18341834
}
18351835

18361836
if (btrfs_super_log_root(fs_info->super_copy) != 0) {
1837+
btrfs_warn(fs_info,
1838+
"mount required to replay tree-log, cannot remount read-write");
18371839
ret = -EINVAL;
18381840
goto restore;
18391841
}

fs/btrfs/sysfs.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,12 @@ static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add)
901901

902902
static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
903903
{
904+
if (fs_devs->devinfo_kobj) {
905+
kobject_del(fs_devs->devinfo_kobj);
906+
kobject_put(fs_devs->devinfo_kobj);
907+
fs_devs->devinfo_kobj = NULL;
908+
}
909+
904910
if (fs_devs->devices_kobj) {
905911
kobject_del(fs_devs->devices_kobj);
906912
kobject_put(fs_devs->devices_kobj);
@@ -1289,7 +1295,7 @@ int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
12891295

12901296
init_completion(&dev->kobj_unregister);
12911297
error = kobject_init_and_add(&dev->devid_kobj, &devid_ktype,
1292-
fs_devices->devices_kobj, "%llu",
1298+
fs_devices->devinfo_kobj, "%llu",
12931299
dev->devid);
12941300
if (error) {
12951301
kobject_put(&dev->devid_kobj);
@@ -1369,6 +1375,15 @@ int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs)
13691375
return -ENOMEM;
13701376
}
13711377

1378+
fs_devs->devinfo_kobj = kobject_create_and_add("devinfo",
1379+
&fs_devs->fsid_kobj);
1380+
if (!fs_devs->devinfo_kobj) {
1381+
btrfs_err(fs_devs->fs_info,
1382+
"failed to init sysfs devinfo kobject");
1383+
btrfs_sysfs_remove_fsid(fs_devs);
1384+
return -ENOMEM;
1385+
}
1386+
13721387
return 0;
13731388
}
13741389

fs/btrfs/volumes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ struct btrfs_fs_devices {
258258
/* sysfs kobjects */
259259
struct kobject fsid_kobj;
260260
struct kobject *devices_kobj;
261+
struct kobject *devinfo_kobj;
261262
struct completion kobj_unregister;
262263
};
263264

0 commit comments

Comments
 (0)