All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning
@ 2020-11-03  5:49 Anand Jain
  2020-11-03  5:49 ` [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0 Anand Jain
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Anand Jain @ 2020-11-03  5:49 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Patch 1 and 2 are cleanups. They were sent before with the cover-letter
as below.
 [PATCH RESEND 0/2] fix verify_one_dev_extent and btrfs_find_device

Patch 3 is a fix for the Warning reported by sysbot. This also was sent
before with the cover-letter titled as below.
  [PATCH 0/1] handle attacking device with devid=0

To avoid conflict fixes, please apply these patches in the order it is
sent here. But the sets are not related.

Both of these patchsets are at v2 at the latest. So I am marking all of
them as v2. The individual changes are in the patches.

Also earlier resend patches were threaded under its previous cover-letter
(though --in-reply-to was not used to generate/send those patches). So I am
trying to resend these patches again, hopefully, they are not threaded to
the older series again.

Anand Jain (3):
  btrfs: drop never met condition of disk_total_bytes == 0
  btrfs: fix btrfs_find_device unused arg seed
  btrfs: fix devid 0 without a replace item by failing the mount

 fs/btrfs/dev-replace.c | 30 ++++++++++++++---
 fs/btrfs/ioctl.c       |  4 +--
 fs/btrfs/scrub.c       |  4 +--
 fs/btrfs/volumes.c     | 73 ++++++++++++++++--------------------------
 fs/btrfs/volumes.h     |  2 +-
 5 files changed, 58 insertions(+), 55 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0
  2020-11-03  5:49 [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning Anand Jain
@ 2020-11-03  5:49 ` Anand Jain
  2020-11-05 22:36   ` David Sterba
  2020-11-03  5:49 ` [PATCH RESEND v2 2/3] btrfs: fix btrfs_find_device unused arg seed Anand Jain
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Anand Jain @ 2020-11-03  5:49 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba, Nikolay Borisov

btrfs_device::disk_total_bytes is set even for a seed device (the
comment is wrong).

The function fill_device_from_item() does the job of reading it from the
item and updating btrfs_device::disk_total_bytes. So both the missing
device and the seed devices do have their disk_total_bytes updated.

Furthermore, while removing the device if there is a power loss, we could
have a device with its total_bytes = 0, that's still valid.

So this patch removes the check dev->disk_total_bytes == 0 in the
function verify_one_dev_extent(), which it does nothing in it.

And take this opportunity to introduce a check if the device::total_bytes
is more than the max device size in read_one_dev().

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
---
v2: add check if the total_bytes is more than the actual device size in
    read_one_dev().
    update change log.

 fs/btrfs/volumes.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index eb9ee7c2998f..e615ca393aab 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6875,6 +6875,16 @@ static int read_one_dev(struct extent_buffer *leaf,
 	}
 
 	fill_device_from_item(leaf, dev_item, device);
+	if (device->bdev) {
+		u64 max_total_bytes = i_size_read(device->bdev->bd_inode);
+
+		if (device->total_bytes > max_total_bytes) {
+			btrfs_err(fs_info,
+			"device total_bytes should be below %llu but found %llu",
+				  max_total_bytes, device->total_bytes);
+			return -EINVAL;
+		}
+	}
 	set_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
 	if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) &&
 	   !test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) {
@@ -7608,21 +7618,6 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
 		goto out;
 	}
 
-	/* It's possible this device is a dummy for seed device */
-	if (dev->disk_total_bytes == 0) {
-		struct btrfs_fs_devices *devs;
-
-		devs = list_first_entry(&fs_info->fs_devices->seed_list,
-					struct btrfs_fs_devices, seed_list);
-		dev = btrfs_find_device(devs, devid, NULL, NULL, false);
-		if (!dev) {
-			btrfs_err(fs_info, "failed to find seed devid %llu",
-				  devid);
-			ret = -EUCLEAN;
-			goto out;
-		}
-	}
-
 	if (physical_offset + physical_len > dev->disk_total_bytes) {
 		btrfs_err(fs_info,
 "dev extent devid %llu physical offset %llu len %llu is beyond device boundary %llu",
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH RESEND v2 2/3] btrfs: fix btrfs_find_device unused arg seed
  2020-11-03  5:49 [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning Anand Jain
  2020-11-03  5:49 ` [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0 Anand Jain
@ 2020-11-03  5:49 ` Anand Jain
  2020-11-03  5:49 ` [PATCH RESEND v2 3/3] btrfs: fix devid 0 without a replace item by failing the mount Anand Jain
  2020-11-11 15:51 ` [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning David Sterba
  3 siblings, 0 replies; 8+ messages in thread
From: Anand Jain @ 2020-11-03  5:49 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba, Josef Bacik

commit 343694eee8d8 (btrfs: switch seed device to list api), missed to
check if the last arg (seed) is true in the function btrfs_find_device().
This arg tells whether to traverse through the seed device list or not.

This means after the above commit the arg is always true, and the parent
function which set this arg to false aren't effective.

So we don't worry about the parent functions which set the last arg to
true, instead there is only one parent with calling btrfs_find_device
with the last arg false in device_list_add().

But in fact, even the device_list_add() has no purpose that it has to set
the last arg to false. Because the fs_devices always points to the
device's fs_devices. So with the devid+uuid matching, it shall find the
btrfs_device and returns. So naturally, it won't traverse through the
seed fs_devices (if) present.

So this patch makes it official that we don't need the last arg in the
function btrfs_find_device() and it shall always traverse through the
seed device list.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
v2: -
 fs/btrfs/dev-replace.c |  4 ++--
 fs/btrfs/ioctl.c       |  4 ++--
 fs/btrfs/scrub.c       |  4 ++--
 fs/btrfs/volumes.c     | 22 ++++++++++------------
 fs/btrfs/volumes.h     |  2 +-
 5 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 5b9e3f3ace22..ffab2758f991 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -149,10 +149,10 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
 		dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices,
-						src_devid, NULL, NULL, true);
+						src_devid, NULL, NULL);
 		dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices,
 							BTRFS_DEV_REPLACE_DEVID,
-							NULL, NULL, true);
+							NULL, NULL);
 		/*
 		 * allow 'btrfs dev replace_cancel' if src/tgt device is
 		 * missing
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 69a384145dc6..36e09a22068a 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1678,7 +1678,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
 		btrfs_info(fs_info, "resizing devid %llu", devid);
 	}
 
-	device = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL, true);
+	device = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
 	if (!device) {
 		btrfs_info(fs_info, "resizer unable to find device %llu",
 			   devid);
@@ -3321,7 +3321,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
 
 	rcu_read_lock();
 	dev = btrfs_find_device(fs_info->fs_devices, di_args->devid, s_uuid,
-				NULL, true);
+				NULL);
 
 	if (!dev) {
 		ret = -ENODEV;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 58cd3278fbfe..c85b493380da 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -3858,7 +3858,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
 		goto out_free_ctx;
 
 	mutex_lock(&fs_info->fs_devices->device_list_mutex);
-	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL, true);
+	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
 	if (!dev || (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) &&
 		     !is_dev_replace)) {
 		mutex_unlock(&fs_info->fs_devices->device_list_mutex);
@@ -4035,7 +4035,7 @@ int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
 	struct scrub_ctx *sctx = NULL;
 
 	mutex_lock(&fs_info->fs_devices->device_list_mutex);
-	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL, true);
+	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
 	if (dev)
 		sctx = dev->scrub_ctx;
 	if (sctx)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e615ca393aab..04ef251d885e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -822,7 +822,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,
 	} else {
 		mutex_lock(&fs_devices->device_list_mutex);
 		device = btrfs_find_device(fs_devices, devid,
-				disk_super->dev_item.uuid, NULL, false);
+				disk_super->dev_item.uuid, NULL);
 
 		/*
 		 * If this disk has been pulled into an fs devices created by
@@ -2300,10 +2300,10 @@ static struct btrfs_device *btrfs_find_device_by_path(
 	dev_uuid = disk_super->dev_item.uuid;
 	if (btrfs_fs_incompat(fs_info, METADATA_UUID))
 		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-					   disk_super->metadata_uuid, true);
+					   disk_super->metadata_uuid);
 	else
 		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-					   disk_super->fsid, true);
+					   disk_super->fsid);
 
 	btrfs_release_disk_super(disk_super);
 	if (!device)
@@ -2323,7 +2323,7 @@ struct btrfs_device *btrfs_find_device_by_devspec(
 
 	if (devid) {
 		device = btrfs_find_device(fs_info->fs_devices, devid, NULL,
-					   NULL, true);
+					   NULL);
 		if (!device)
 			return ERR_PTR(-ENOENT);
 		return device;
@@ -2472,7 +2472,7 @@ static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
 		read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
 				   BTRFS_FSID_SIZE);
 		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-					   fs_uuid, true);
+					   fs_uuid);
 		BUG_ON(!device); /* Logic error */
 
 		if (device->fs_devices->seeding) {
@@ -6465,8 +6465,7 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
  * If @seed is true, traverse through the seed devices.
  */
 struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
-				       u64 devid, u8 *uuid, u8 *fsid,
-				       bool seed)
+				       u64 devid, u8 *uuid, u8 *fsid)
 {
 	struct btrfs_device *device;
 	struct btrfs_fs_devices *seed_devs;
@@ -6673,7 +6672,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 				   btrfs_stripe_dev_uuid_nr(chunk, i),
 				   BTRFS_UUID_SIZE);
 		map->stripes[i].dev = btrfs_find_device(fs_info->fs_devices,
-							devid, uuid, NULL, true);
+							devid, uuid, NULL);
 		if (!map->stripes[i].dev &&
 		    !btrfs_test_opt(fs_info, DEGRADED)) {
 			free_extent_map(em);
@@ -6812,7 +6811,7 @@ static int read_one_dev(struct extent_buffer *leaf,
 	}
 
 	device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-				   fs_uuid, true);
+				   fs_uuid);
 	if (!device) {
 		if (!btrfs_test_opt(fs_info, DEGRADED)) {
 			btrfs_report_missing_device(fs_info, devid,
@@ -7479,8 +7478,7 @@ int btrfs_get_dev_stats(struct btrfs_fs_info *fs_info,
 	int i;
 
 	mutex_lock(&fs_devices->device_list_mutex);
-	dev = btrfs_find_device(fs_info->fs_devices, stats->devid, NULL, NULL,
-				true);
+	dev = btrfs_find_device(fs_info->fs_devices, stats->devid, NULL, NULL);
 	mutex_unlock(&fs_devices->device_list_mutex);
 
 	if (!dev) {
@@ -7611,7 +7609,7 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
 	}
 
 	/* Make sure no dev extent is beyond device bondary */
-	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL, true);
+	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
 	if (!dev) {
 		btrfs_err(fs_info, "failed to find devid %llu", devid);
 		ret = -EUCLEAN;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 34fd440fd30b..bd95cea85a65 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -466,7 +466,7 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len);
 int btrfs_grow_device(struct btrfs_trans_handle *trans,
 		      struct btrfs_device *device, u64 new_size);
 struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
-				       u64 devid, u8 *uuid, u8 *fsid, bool seed);
+				       u64 devid, u8 *uuid, u8 *fsid);
 int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
 int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *path);
 int btrfs_balance(struct btrfs_fs_info *fs_info,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH RESEND v2 3/3] btrfs: fix devid 0 without a replace item by failing the mount
  2020-11-03  5:49 [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning Anand Jain
  2020-11-03  5:49 ` [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0 Anand Jain
  2020-11-03  5:49 ` [PATCH RESEND v2 2/3] btrfs: fix btrfs_find_device unused arg seed Anand Jain
@ 2020-11-03  5:49 ` Anand Jain
  2020-11-11 15:51 ` [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning David Sterba
  3 siblings, 0 replies; 8+ messages in thread
From: Anand Jain @ 2020-11-03  5:49 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba, josef, syzbot+4cfe71a4da060be47502

If there is a BTRFS_DEV_REPLACE_DEVID without a replace item, then
it means some device is trying to attack or may be corrupted. Fail the
mount so that the user can remove the attacking or fix the corrupted
device.

As of now if BTRFS_DEV_REPLACE_DEVID is present without the replace
item, in __btrfs_free_extra_devids() we determine that there is an
extra device, and free those extra devices but continue to mount the
device.
However, we were wrong in keeping tack of the rw_devices so the syzbot
testcase failed as below [1].

[1]
WARNING: CPU: 1 PID: 3612 at fs/btrfs/volumes.c:1166 close_fs_devices.part.0+0x607/0x800 fs/btrfs/volumes.c:1166
Kernel panic - not syncing: panic_on_warn set ...
CPU: 1 PID: 3612 Comm: syz-executor.2 Not tainted 5.9.0-rc4-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x198/0x1fd lib/dump_stack.c:118
 panic+0x347/0x7c0 kernel/panic.c:231
 __warn.cold+0x20/0x46 kernel/panic.c:600
 report_bug+0x1bd/0x210 lib/bug.c:198
 handle_bug+0x38/0x90 arch/x86/kernel/traps.c:234
 exc_invalid_op+0x14/0x40 arch/x86/kernel/traps.c:254
 asm_exc_invalid_op+0x12/0x20 arch/x86/include/asm/idtentry.h:536
RIP: 0010:close_fs_devices.part.0+0x607/0x800 fs/btrfs/volumes.c:1166
Code: 0f b6 04 02 84 c0 74 02 7e 33 48 8b 44 24 18 c6 80 30 01 00 00 00 48 83 c4 30 5b 5d 41 5c 41 5d 41 5e 41 5f c3 e8 99 ce 6a fe <0f> 0b e9 71 ff ff ff e8 8d ce 6a fe 0f 0b e9 20 ff ff ff e8 d1 d5
RSP: 0018:ffffc900091777e0 EFLAGS: 00010246
RAX: 0000000000040000 RBX: ffffffffffffffff RCX: ffffc9000c8b7000
RDX: 0000000000040000 RSI: ffffffff83097f47 RDI: 0000000000000007
RBP: dffffc0000000000 R08: 0000000000000001 R09: ffff8880988a187f
R10: 0000000000000000 R11: 0000000000000001 R12: ffff88809593a130
R13: ffff88809593a1ec R14: ffff8880988a1908 R15: ffff88809593a050
 close_fs_devices fs/btrfs/volumes.c:1193 [inline]
 btrfs_close_devices+0x95/0x1f0 fs/btrfs/volumes.c:1179
 open_ctree+0x4984/0x4a2d fs/btrfs/disk-io.c:3434
 btrfs_fill_super fs/btrfs/super.c:1316 [inline]
 btrfs_mount_root.cold+0x14/0x165 fs/btrfs/super.c:1672

The fix here is, when we determine that there isn't a replace item
then fail the mount if there is a replace target device (devid 0).

The reproducer and the fix looks like this.

 mkfs.btrfs -fq /dev/sda
 dd if=/dev/sda of=/dev/sdb bs=1 seek=64K skip=64K count=4096
 btrfs-sb-mod /dev/sdb dev_item.devid =0
 mount -o device=/dev/sdb /dev/sda /btrfsS
mount: /btrfs: wrong fs type, bad option, bad superblock on /dev/sda, missing codepage or helper program, or other error.

[ 3526.708108] BTRFS error (device sdb): found replace target device without a replace item
[ 3526.709152] BTRFS error (device sdb): failed to init dev_replace: -5
[ 3526.715623] BTRFS error (device sdb): open_ctree failed

Cc: josef@toxicpanda.com
Reported-by: syzbot+4cfe71a4da060be47502@syzkaller.appspotmail.com
Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
(changle log reproducer updated).

Conflicts with the patches
 btrfs: drop never met condition of disk_total_bytes == 0
 btrfs: fix btrfs_find_device unused arg seed
If these patches aren't integrated yet, then please add the last arg in
the function btrfs_find_device(). Any value is fine as it doesn't care.

Dropped the idea of fstests for now as the test case requires btrfs-sb-mod.
And there aren't any fstests yet which shall carry 4k superblock in its script
not sure if it's a good idea.

Instead, we could rely on sysbot for now.

v2: changed title
    old: btrfs: fix rw_devices count in __btrfs_free_extra_devids

    In btrfs_init_dev_replace() try to match the presence of replace_item
    to the BTRFS_DEV_REPLACE_DEVID device. If fails then fail the
    mount. So drop the similar check in __btrfs_free_extra_devids().

 fs/btrfs/dev-replace.c | 26 ++++++++++++++++++++++++--
 fs/btrfs/volumes.c     | 26 +++++++-------------------
 2 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index ffab2758f991..8b3935757dc1 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -91,6 +91,17 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 	ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0);
 	if (ret) {
 no_valid_dev_replace_entry_found:
+		/*
+		 * We don't have a replace item or it's corrupted.
+		 * If there is a replace target, fail the mount.
+		 */
+		if (btrfs_find_device(fs_info->fs_devices,
+				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
+			btrfs_err(fs_info,
+			"found replace target device without a replace item");
+			ret = -EIO;
+			goto out;
+		}
 		ret = 0;
 		dev_replace->replace_state =
 			BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
@@ -143,8 +154,19 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
-		dev_replace->srcdev = NULL;
-		dev_replace->tgtdev = NULL;
+		/*
+		 * We don't have an active replace item but if there is a
+		 * replace target, fail the mount.
+		 */
+		if (btrfs_find_device(fs_info->fs_devices,
+				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
+			btrfs_err(fs_info,
+			"replace devid present without an active replace item");
+			ret = -EIO;
+		} else {
+			dev_replace->srcdev = NULL;
+			dev_replace->tgtdev = NULL;
+		}
 		break;
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 04ef251d885e..9dd55a6f38de 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1056,22 +1056,13 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
 			continue;
 		}
 
-		if (device->devid == BTRFS_DEV_REPLACE_DEVID) {
-			/*
-			 * In the first step, keep the device which has
-			 * the correct fsid and the devid that is used
-			 * for the dev_replace procedure.
-			 * In the second step, the dev_replace state is
-			 * read from the device tree and it is known
-			 * whether the procedure is really active or
-			 * not, which means whether this device is
-			 * used or whether it should be removed.
-			 */
-			if (step == 0 || test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
-						  &device->dev_state)) {
-				continue;
-			}
-		}
+		/*
+		 * We have already validated the presence of BTRFS_DEV_REPLACE_DEVID,
+		 * in btrfs_init_dev_replace() so just continue.
+		 */
+		if (device->devid == BTRFS_DEV_REPLACE_DEVID)
+			continue;
+
 		if (device->bdev) {
 			blkdev_put(device->bdev, device->mode);
 			device->bdev = NULL;
@@ -1080,9 +1071,6 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
 		if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
 			list_del_init(&device->dev_alloc_list);
 			clear_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
-			if (!test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
-				      &device->dev_state))
-				fs_devices->rw_devices--;
 		}
 		list_del_init(&device->dev_list);
 		fs_devices->num_devices--;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0
  2020-11-03  5:49 ` [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0 Anand Jain
@ 2020-11-05 22:36   ` David Sterba
  2020-11-06  0:20     ` Anand Jain
  0 siblings, 1 reply; 8+ messages in thread
From: David Sterba @ 2020-11-05 22:36 UTC (permalink / raw)
  To: Anand Jain; +Cc: linux-btrfs, dsterba, Nikolay Borisov, wqu

On Tue, Nov 03, 2020 at 01:49:42PM +0800, Anand Jain wrote:
> btrfs_device::disk_total_bytes is set even for a seed device (the
> comment is wrong).

That's where I'm a bit lost. It was added in 1b3922a8bc74 ("btrfs: Use
real device structure to verify dev extent").

> The function fill_device_from_item() does the job of reading it from the
> item and updating btrfs_device::disk_total_bytes. So both the missing
> device and the seed devices do have their disk_total_bytes updated.
> 
> Furthermore, while removing the device if there is a power loss, we could
> have a device with its total_bytes = 0, that's still valid.

Ok, that's the condition that the commit mentioned above used to detect
the device and to avoid doing the tree-checker verification.

> So this patch removes the check dev->disk_total_bytes == 0 in the
> function verify_one_dev_extent(), which it does nothing in it.

Removing a check that supposedly does notghing, but the referenced
commit says otherwise.

> And take this opportunity to introduce a check if the device::total_bytes
> is more than the max device size in read_one_dev().

If this is not related to the the check removal, then it should be an
independent patch explaing in full what is being fixed. As I read it
this should be independent as it's checking the upper bound.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0
  2020-11-05 22:36   ` David Sterba
@ 2020-11-06  0:20     ` Anand Jain
  2020-11-11 15:33       ` David Sterba
  0 siblings, 1 reply; 8+ messages in thread
From: Anand Jain @ 2020-11-06  0:20 UTC (permalink / raw)
  To: dsterba, linux-btrfs, dsterba, Nikolay Borisov, wqu



On 6/11/20 6:36 am, David Sterba wrote:
> On Tue, Nov 03, 2020 at 01:49:42PM +0800, Anand Jain wrote:
>> btrfs_device::disk_total_bytes is set even for a seed device (the
>> comment is wrong).
> 
> That's where I'm a bit lost. It was added in 1b3922a8bc74 ("btrfs: Use
> real device structure to verify dev extent").
> 

  The call chain where we update the btrfs_device::disk_total_bytes is as
  below..


    read_one_dev()
::

 From the section below we get the cloned copy of the seed device.
-----
         if (memcmp(fs_uuid, fs_devices->metadata_uuid, BTRFS_FSID_SIZE)) {
                 fs_devices = open_seed_devices(fs_info, fs_uuid);
                 if (IS_ERR(fs_devices))
                         return PTR_ERR(fs_devices);
         }

         device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
                                    fs_uuid);
------


  Further down in read_one_dev() at and in the 
fill_device_from_item(..., device) we update the 
btrfs_device::disk_total_bytes.

fill_device_from_item(..., device)
::
         device->disk_total_bytes = btrfs_device_total_bytes(leaf, 
dev_item);

Hope this clarifies.

V1 email discussion has more information.

>> The function fill_device_from_item() does the job of reading it from the
>> item and updating btrfs_device::disk_total_bytes. So both the missing
>> device and the seed devices do have their disk_total_bytes updated.
>>
>> Furthermore, while removing the device if there is a power loss, we could
>> have a device with its total_bytes = 0, that's still valid.


> 
> Ok, that's the condition that the commit mentioned above used to detect
> the device and to avoid doing the tree-checker verification.

Ok. Please look at what did the commit 1b3922a8bc74 do? It re-ran the 
btrfs_find_device(seed_devs,..., false), which anyway the 
btrfs_find_device(sprout_devs,..., true) has run just before. In both of 
these btrfs_find_device() runs, the dev returned will be the same. The 
fix makes no sense to the problem as in the commit.


> 
>> So this patch removes the check dev->disk_total_bytes == 0 in the
>> function verify_one_dev_extent(), which it does nothing in it.
> 
> Removing a check that supposedly does notghing, but the referenced
> commit says otherwise.
> 

IMO the reason for the problem found in that commit was wrong. Qu 
commit's email thread has some discussion. But nothing more on the problem.

Also Nikolay had the same question here was my reply.
https://www.spinics.net/lists/linux-btrfs/msg105645.html


>> And take this opportunity to introduce a check if the device::total_bytes
>> is more than the max device size in read_one_dev().
> 
> If this is not related to the the check removal, then it should be an
> independent patch explaing in full what is being fixed. As I read it
> this should be independent as it's checking the upper bound.
> 

  That came from the Josef comments, please refer to the v1 email 
discussion. Most of the above concerns are already discussed there. I am 
ok to move it to a new patch if required.

Thanks, Anand


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0
  2020-11-06  0:20     ` Anand Jain
@ 2020-11-11 15:33       ` David Sterba
  0 siblings, 0 replies; 8+ messages in thread
From: David Sterba @ 2020-11-11 15:33 UTC (permalink / raw)
  To: Anand Jain; +Cc: dsterba, linux-btrfs, dsterba, Nikolay Borisov, wqu

On Fri, Nov 06, 2020 at 08:20:12AM +0800, Anand Jain wrote:
> On 6/11/20 6:36 am, David Sterba wrote:
> > On Tue, Nov 03, 2020 at 01:49:42PM +0800, Anand Jain wrote:
> >> btrfs_device::disk_total_bytes is set even for a seed device (the
> >> comment is wrong).
> > 
> > That's where I'm a bit lost. It was added in 1b3922a8bc74 ("btrfs: Use
> > real device structure to verify dev extent").
> > 
> 
>   The call chain where we update the btrfs_device::disk_total_bytes is as
>   below..
> 
> 
>     read_one_dev()
> ::
> 
>  From the section below we get the cloned copy of the seed device.
> -----
>          if (memcmp(fs_uuid, fs_devices->metadata_uuid, BTRFS_FSID_SIZE)) {
>                  fs_devices = open_seed_devices(fs_info, fs_uuid);
>                  if (IS_ERR(fs_devices))
>                          return PTR_ERR(fs_devices);
>          }
> 
>          device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
>                                     fs_uuid);
> ------
> 
> 
>   Further down in read_one_dev() at and in the 
> fill_device_from_item(..., device) we update the 
> btrfs_device::disk_total_bytes.
> 
> fill_device_from_item(..., device)
> ::
>          device->disk_total_bytes = btrfs_device_total_bytes(leaf, 
> dev_item);
> 
> Hope this clarifies.
> 
> V1 email discussion has more information.

... that should have been turned into a changelog update in v2.

> >> The function fill_device_from_item() does the job of reading it from the
> >> item and updating btrfs_device::disk_total_bytes. So both the missing
> >> device and the seed devices do have their disk_total_bytes updated.
> >>
> >> Furthermore, while removing the device if there is a power loss, we could
> >> have a device with its total_bytes = 0, that's still valid.
> 
> 
> > 
> > Ok, that's the condition that the commit mentioned above used to detect
> > the device and to avoid doing the tree-checker verification.
> 
> Ok. Please look at what did the commit 1b3922a8bc74 do? It re-ran the 
> btrfs_find_device(seed_devs,..., false), which anyway the 
> btrfs_find_device(sprout_devs,..., true) has run just before. In both of 
> these btrfs_find_device() runs, the dev returned will be the same. The 
> fix makes no sense to the problem as in the commit.
> 
> 
> > 
> >> So this patch removes the check dev->disk_total_bytes == 0 in the
> >> function verify_one_dev_extent(), which it does nothing in it.
> > 
> > Removing a check that supposedly does notghing, but the referenced
> > commit says otherwise.
> > 
> 
> IMO the reason for the problem found in that commit was wrong. Qu 
> commit's email thread has some discussion. But nothing more on the problem.
> 
> Also Nikolay had the same question here was my reply.
> https://www.spinics.net/lists/linux-btrfs/msg105645.html

If the same question is asked then it's missing in the changelog, that's
where people will want to read it in the future and not in the
mailinglist archives.

> >> And take this opportunity to introduce a check if the device::total_bytes
> >> is more than the max device size in read_one_dev().
> > 
> > If this is not related to the the check removal, then it should be an
> > independent patch explaing in full what is being fixed. As I read it
> > this should be independent as it's checking the upper bound.
> > 
> 
>   That came from the Josef comments, please refer to the v1 email 
> discussion. Most of the above concerns are already discussed there. I am 
> ok to move it to a new patch if required.

And again. Same questions still unanswered, the whole point of the
iterations is to add what's been found unclear or missing. I've added it
for now but next time I'd prefer not to have to.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning
  2020-11-03  5:49 [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning Anand Jain
                   ` (2 preceding siblings ...)
  2020-11-03  5:49 ` [PATCH RESEND v2 3/3] btrfs: fix devid 0 without a replace item by failing the mount Anand Jain
@ 2020-11-11 15:51 ` David Sterba
  3 siblings, 0 replies; 8+ messages in thread
From: David Sterba @ 2020-11-11 15:51 UTC (permalink / raw)
  To: Anand Jain; +Cc: linux-btrfs, dsterba

On Tue, Nov 03, 2020 at 01:49:41PM +0800, Anand Jain wrote:
> Patch 1 and 2 are cleanups. They were sent before with the cover-letter
> as below.
>  [PATCH RESEND 0/2] fix verify_one_dev_extent and btrfs_find_device
> 
> Patch 3 is a fix for the Warning reported by sysbot. This also was sent
> before with the cover-letter titled as below.
>   [PATCH 0/1] handle attacking device with devid=0
> 
> To avoid conflict fixes, please apply these patches in the order it is
> sent here. But the sets are not related.
> 
> Both of these patchsets are at v2 at the latest. So I am marking all of
> them as v2. The individual changes are in the patches.
> 
> Also earlier resend patches were threaded under its previous cover-letter
> (though --in-reply-to was not used to generate/send those patches). So I am
> trying to resend these patches again, hopefully, they are not threaded to
> the older series again.
> 
> Anand Jain (3):
>   btrfs: drop never met condition of disk_total_bytes == 0
>   btrfs: fix btrfs_find_device unused arg seed
>   btrfs: fix devid 0 without a replace item by failing the mount

Now added to misc-next, thanks.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-11-11 15:52 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-03  5:49 [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning Anand Jain
2020-11-03  5:49 ` [PATCH RESEND v2 1/3] btrfs: drop never met condition of disk_total_bytes == 0 Anand Jain
2020-11-05 22:36   ` David Sterba
2020-11-06  0:20     ` Anand Jain
2020-11-11 15:33       ` David Sterba
2020-11-03  5:49 ` [PATCH RESEND v2 2/3] btrfs: fix btrfs_find_device unused arg seed Anand Jain
2020-11-03  5:49 ` [PATCH RESEND v2 3/3] btrfs: fix devid 0 without a replace item by failing the mount Anand Jain
2020-11-11 15:51 ` [PATCH RESEND v2 0/3] cleanup btrfs_find_device and fix sysbot warning David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.