From 87fa3bb0786f37dff0b92f2c38421dd56d8902a9 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Tue, 29 Jul 2014 19:09:39 +0800 Subject: Btrfs: fix regression of btrfs device replace Commit 49c6f736f34f901117c20960ebd7d5e60f12fcac( btrfs: dev replace should replace the sysfs entry) added the missing sysfs entry in the process of device replace, but didn't take missing devices into account, so now we have BUG: unable to handle kernel NULL pointer dereference at 0000000000000088 IP: [] btrfs_kobj_rm_device+0x21/0x40 [btrfs] ... To reproduce it, 1. mkfs.btrfs -f disk1 disk2 2. mkfs.ext4 disk1 3. mount disk2 /mnt -odegraded 4. btrfs replace start -B 1 disk3 /mnt -------------------------- This fixes the problem. Reported-by: Chris Murphy Signed-off-by: Liu Bo Reviewed-by: Satoru Takeuchi Tested-by: Satoru Takeuchi Signed-off-by: Chris Mason --- fs/btrfs/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/btrfs/sysfs.c') diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 78699364f53..12e53556e21 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -614,7 +614,7 @@ int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info, if (!fs_info->device_dir_kobj) return -EINVAL; - if (one_device) { + if (one_device && one_device->bdev) { disk = one_device->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; -- cgit v1.2.3-70-g09d2 From 48fcc3ff7dce0138c053833adf81670494f177f3 Mon Sep 17 00:00:00 2001 From: Satoru Takeuchi Date: Tue, 1 Jul 2014 17:00:07 +0900 Subject: btrfs: label should not contain return char Rediffed remaining parts of original patch from Anand Jain. This makes sure to avoid trailing newlines in the btrfs label output reproducer.sh: =============================================================================== TEST_DEV=/dev/vdb TEST_DIR=/home/sat/mnt umount /home/sat/mnt mkfs.btrfs -f $TEST_DEV UUID=$(btrfs fi show $TEST_DEV | head -1 | sed -e 's/.*uuid: \([-0-9a-z]*\)$/\1/') mount $TEST_DEV $TEST_DIR LABELFILE=/sys/fs/btrfs/$UUID/label echo "Test for empty label..." >&2 LINES="$(cat $LABELFILE | wc -l | awk '{print $1}')" RET=0 if [ $LINES -eq 0 ] ; then echo '[PASS] Trailing \n is removed correctly.' >&2 else echo '[FAIL] Trailing \n still exists.' >&2 RET=1 fi echo "Test for non-empty label..." >&2 echo testlabel >$LABELFILE LINES="$(cat $LABELFILE | wc -l | awk '{print $1}')" if [ $LINES -eq 1 ] ; then echo '[PASS] Trailing \n is removed correctly.' >&2 else echo '[FAIL] Trailing \n still exists.' >&2 RET=1 fi exit $RET =============================================================================== Signed-off-by: Satoru Takeuchi Signed-off-by: Chris Mason --- fs/btrfs/sysfs.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'fs/btrfs/sysfs.c') diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 12e53556e21..82a968fdfd8 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -363,7 +363,8 @@ static ssize_t btrfs_label_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); - return snprintf(buf, PAGE_SIZE, "%s\n", fs_info->super_copy->label); + char *label = fs_info->super_copy->label; + return snprintf(buf, PAGE_SIZE, label[0] ? "%s\n" : "%s", label); } static ssize_t btrfs_label_store(struct kobject *kobj, @@ -374,8 +375,15 @@ static ssize_t btrfs_label_store(struct kobject *kobj, struct btrfs_trans_handle *trans; struct btrfs_root *root = fs_info->fs_root; int ret; + size_t p_len; - if (len >= BTRFS_LABEL_SIZE) + /* + * p_len is the len until the first occurrence of either + * '\n' or '\0' + */ + p_len = strcspn(buf, "\n"); + + if (p_len >= BTRFS_LABEL_SIZE) return -EINVAL; trans = btrfs_start_transaction(root, 0); @@ -383,7 +391,8 @@ static ssize_t btrfs_label_store(struct kobject *kobj, return PTR_ERR(trans); spin_lock(&root->fs_info->super_lock); - strcpy(fs_info->super_copy->label, buf); + memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); + memcpy(fs_info->super_copy->label, buf, p_len); spin_unlock(&root->fs_info->super_lock); ret = btrfs_commit_transaction(trans, root); -- cgit v1.2.3-70-g09d2 From 3f4b57e09d6cbd97f92311a801e1b83992506dcd Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 30 Jul 2014 20:04:07 +0800 Subject: btrfs: use BTRFS_ATTR instead of btrfs_no_store() we have BTRFS_ATTR define to create sysfs RO file, use that. Signed-off-by: Anand Jain Signed-off-by: Chris Mason --- fs/btrfs/sysfs.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'fs/btrfs/sysfs.c') diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 82a968fdfd8..e6a851b9ae3 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -403,13 +403,6 @@ static ssize_t btrfs_label_store(struct kobject *kobj, } BTRFS_ATTR_RW(label, 0644, btrfs_label_show, btrfs_label_store); -static ssize_t btrfs_no_store(struct kobject *kobj, - struct kobj_attribute *a, - const char *buf, size_t len) -{ - return -EPERM; -} - static ssize_t btrfs_nodesize_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { @@ -418,7 +411,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize); } -BTRFS_ATTR_RW(nodesize, 0444, btrfs_nodesize_show, btrfs_no_store); +BTRFS_ATTR(nodesize, 0444, btrfs_nodesize_show); static ssize_t btrfs_sectorsize_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) @@ -428,7 +421,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize); } -BTRFS_ATTR_RW(sectorsize, 0444, btrfs_sectorsize_show, btrfs_no_store); +BTRFS_ATTR(sectorsize, 0444, btrfs_sectorsize_show); static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) @@ -438,7 +431,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize); } -BTRFS_ATTR_RW(clone_alignment, 0444, btrfs_clone_alignment_show, btrfs_no_store); +BTRFS_ATTR(clone_alignment, 0444, btrfs_clone_alignment_show); static struct attribute *btrfs_attrs[] = { BTRFS_ATTR_PTR(label), -- cgit v1.2.3-70-g09d2 From 98b3d389eb473f28ef69547c0a9f72041c4c40e6 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 30 Jul 2014 20:04:08 +0800 Subject: btrfs: code optimize: BTRFS_ATTR could handle the mode All that uses BTRFS_ATTR want mode to be set at 0444 so just do it at the define. And few spacing alignments. Signed-off-by: Anand Jain Signed-off-by: Chris Mason --- fs/btrfs/sysfs.c | 14 +++++++------- fs/btrfs/sysfs.h | 11 +++++++---- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'fs/btrfs/sysfs.c') diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index e6a851b9ae3..a1c10886d9f 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -242,7 +242,7 @@ static ssize_t global_rsv_size_show(struct kobject *kobj, struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); } -BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show); +BTRFS_ATTR(global_rsv_size, global_rsv_size_show); static ssize_t global_rsv_reserved_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) @@ -251,7 +251,7 @@ static ssize_t global_rsv_reserved_show(struct kobject *kobj, struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); } -BTRFS_ATTR(global_rsv_reserved, 0444, global_rsv_reserved_show); +BTRFS_ATTR(global_rsv_reserved, global_rsv_reserved_show); #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) @@ -306,7 +306,7 @@ static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ struct btrfs_space_info *sinfo = to_space_info(kobj); \ return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ } \ -BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field) +BTRFS_ATTR(field, btrfs_space_info_show_##field) static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj, struct kobj_attribute *a, @@ -325,7 +325,7 @@ SPACE_INFO_ATTR(bytes_reserved); SPACE_INFO_ATTR(bytes_may_use); SPACE_INFO_ATTR(disk_used); SPACE_INFO_ATTR(disk_total); -BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned); +BTRFS_ATTR(total_bytes_pinned, btrfs_space_info_show_total_bytes_pinned); static struct attribute *space_info_attrs[] = { BTRFS_ATTR_PTR(flags), @@ -411,7 +411,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize); } -BTRFS_ATTR(nodesize, 0444, btrfs_nodesize_show); +BTRFS_ATTR(nodesize, btrfs_nodesize_show); static ssize_t btrfs_sectorsize_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) @@ -421,7 +421,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize); } -BTRFS_ATTR(sectorsize, 0444, btrfs_sectorsize_show); +BTRFS_ATTR(sectorsize, btrfs_sectorsize_show); static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) @@ -431,7 +431,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize); } -BTRFS_ATTR(clone_alignment, 0444, btrfs_clone_alignment_show); +BTRFS_ATTR(clone_alignment, btrfs_clone_alignment_show); static struct attribute *btrfs_attrs[] = { BTRFS_ATTR_PTR(label), diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h index ac46df37504..531b11ee912 100644 --- a/fs/btrfs/sysfs.h +++ b/fs/btrfs/sysfs.h @@ -21,15 +21,18 @@ enum btrfs_feature_set { } #define BTRFS_ATTR_RW(_name, _mode, _show, _store) \ -static struct kobj_attribute btrfs_attr_##_name = \ + static struct kobj_attribute btrfs_attr_##_name = \ __INIT_KOBJ_ATTR(_name, _mode, _show, _store) -#define BTRFS_ATTR(_name, _mode, _show) \ - BTRFS_ATTR_RW(_name, _mode, _show, NULL) + +#define BTRFS_ATTR(_name, _show) \ + BTRFS_ATTR_RW(_name, 0444, _show, NULL) + #define BTRFS_ATTR_PTR(_name) (&btrfs_attr_##_name.attr) #define BTRFS_RAID_ATTR(_name, _show) \ -static struct kobj_attribute btrfs_raid_attr_##_name = \ + static struct kobj_attribute btrfs_raid_attr_##_name = \ __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) + #define BTRFS_RAID_ATTR_PTR(_name) (&btrfs_raid_attr_##_name.attr) -- cgit v1.2.3-70-g09d2 From 20ee0825ecec889afdf12f7c13b9dc3af0bb9f14 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 30 Jul 2014 20:04:09 +0800 Subject: btrfs: code optimize: BTRFS_ATTR_RW could set the mode BTRFS_ATTR_RW could set the mode and be inline with BTRFS_ATTR Signed-off-by: Anand Jain Signed-off-by: Chris Mason --- fs/btrfs/sysfs.c | 2 +- fs/btrfs/sysfs.h | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'fs/btrfs/sysfs.c') diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index a1c10886d9f..e6a5e7d82f4 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -401,7 +401,7 @@ static ssize_t btrfs_label_store(struct kobject *kobj, return ret; } -BTRFS_ATTR_RW(label, 0644, btrfs_label_show, btrfs_label_store); +BTRFS_ATTR_RW(label, btrfs_label_show, btrfs_label_store); static ssize_t btrfs_nodesize_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h index 531b11ee912..f7dd298b3cf 100644 --- a/fs/btrfs/sysfs.h +++ b/fs/btrfs/sysfs.h @@ -20,12 +20,13 @@ enum btrfs_feature_set { .store = _store, \ } -#define BTRFS_ATTR_RW(_name, _mode, _show, _store) \ +#define BTRFS_ATTR_RW(_name, _show, _store) \ static struct kobj_attribute btrfs_attr_##_name = \ - __INIT_KOBJ_ATTR(_name, _mode, _show, _store) + __INIT_KOBJ_ATTR(_name, 0644, _show, _store) #define BTRFS_ATTR(_name, _show) \ - BTRFS_ATTR_RW(_name, 0444, _show, NULL) + static struct kobj_attribute btrfs_attr_##_name = \ + __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) #define BTRFS_ATTR_PTR(_name) (&btrfs_attr_##_name.attr) -- cgit v1.2.3-70-g09d2 From 79aec2b80db1089f983d60e4a22cb95d8b939844 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 30 Jul 2014 20:04:10 +0800 Subject: btrfs: sysfs label interface should check for read only FS Not sure how this escaped many eyes so far Signed-off-by: Anand Jain Signed-off-by: Chris Mason --- fs/btrfs/sysfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/btrfs/sysfs.c') diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index e6a5e7d82f4..b2e7bb4393f 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -377,6 +377,9 @@ static ssize_t btrfs_label_store(struct kobject *kobj, int ret; size_t p_len; + if (fs_info->sb->s_flags & MS_RDONLY) + return -EROFS; + /* * p_len is the len until the first occurrence of either * '\n' or '\0' -- cgit v1.2.3-70-g09d2