* [PATCH 1/2] btrfs-progs: zoned: introduce sb_bytenr_to_sb_zone()
2023-10-12 14:19 [PATCH 0/2] btrfs-progs: zoned: check existence of SB zone, not LBA Naohiro Aota
@ 2023-10-12 14:19 ` Naohiro Aota
2023-10-12 14:19 ` [PATCH 2/2] btrfs-progs: zoned: check SB zone existence properly Naohiro Aota
2023-10-12 16:25 ` [PATCH 0/2] btrfs-progs: zoned: check existence of SB zone, not LBA David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: Naohiro Aota @ 2023-10-12 14:19 UTC (permalink / raw)
To: linux-btrfs; +Cc: Naohiro Aota
Introduce sb_bytenr_to_sb_zone(), which converts the original superblock
location to the zone number of superblock log writing.
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
kernel-shared/zoned.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/kernel-shared/zoned.c b/kernel-shared/zoned.c
index 16e83f8b6331..206ad906c985 100644
--- a/kernel-shared/zoned.c
+++ b/kernel-shared/zoned.c
@@ -478,6 +478,21 @@ static int sb_log_location(int fd, struct blk_zone *zones, int rw, u64 *bytenr_r
return 0;
}
+static u32 sb_bytenr_to_sb_zone(u64 bytenr, int zone_size_shift)
+{
+ int i, mirror = -1;
+
+ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
+ if (bytenr == btrfs_sb_offset(i)) {
+ mirror = i;
+ break;
+ }
+ }
+ ASSERT(mirror != -1);
+
+ return sb_zone_number(zone_size_shift, mirror);
+}
+
size_t btrfs_sb_io(int fd, void *buf, off_t offset, int rw)
{
size_t count = BTRFS_SUPER_INFO_SIZE;
@@ -489,8 +504,6 @@ size_t btrfs_sb_io(int fd, void *buf, off_t offset, int rw)
u32 zone_num;
u32 zone_size_sector;
size_t rep_size;
- int mirror = -1;
- int i;
int ret;
size_t ret_sz;
@@ -532,16 +545,7 @@ size_t btrfs_sb_io(int fd, void *buf, off_t offset, int rw)
ASSERT(IS_ALIGNED(zone_size_sector, sb_size_sector));
- for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
- if (offset == btrfs_sb_offset(i)) {
- mirror = i;
- break;
- }
- }
- ASSERT(mirror != -1);
-
- zone_num = sb_zone_number(ilog2(zone_size_sector) + SECTOR_SHIFT,
- mirror);
+ zone_num = sb_bytenr_to_sb_zone(offset, ilog2(zone_size_sector) + SECTOR_SHIFT);
rep_size = sizeof(struct blk_zone_report) + sizeof(struct blk_zone) * 2;
rep = calloc(1, rep_size);
--
2.42.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] btrfs-progs: zoned: check SB zone existence properly
2023-10-12 14:19 [PATCH 0/2] btrfs-progs: zoned: check existence of SB zone, not LBA Naohiro Aota
2023-10-12 14:19 ` [PATCH 1/2] btrfs-progs: zoned: introduce sb_bytenr_to_sb_zone() Naohiro Aota
@ 2023-10-12 14:19 ` Naohiro Aota
2023-10-12 16:25 ` [PATCH 0/2] btrfs-progs: zoned: check existence of SB zone, not LBA David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: Naohiro Aota @ 2023-10-12 14:19 UTC (permalink / raw)
To: linux-btrfs; +Cc: Naohiro Aota
Currently, write_dev_supers() compares the superblock location vs the size
of the device to check if it can write the superblock. This is not correct
for a zoned device, whose superblock location is different than a regular
device.
Introduce check_sb_location() to check if the superblock zone exists for
the zoned case.
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
kernel-shared/disk-io.c | 9 ++++++++-
kernel-shared/zoned.c | 8 ++++++++
kernel-shared/zoned.h | 6 ++++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index 1b1531c52ad7..a056f2ca0560 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -1998,6 +1998,13 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr,
return transid > 0 ? 0 : -1;
}
+static bool check_sb_location(struct btrfs_device *device, u64 bytenr)
+{
+ if (!device->zone_info)
+ return bytenr + BTRFS_SUPER_INFO_SIZE <= device->total_bytes;
+ return btrfs_sb_zone_exists(device, bytenr);
+}
+
static int write_dev_supers(struct btrfs_fs_info *fs_info,
struct btrfs_super_block *sb,
struct btrfs_device *device)
@@ -2048,7 +2055,7 @@ static int write_dev_supers(struct btrfs_fs_info *fs_info,
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
bytenr = btrfs_sb_offset(i);
- if (bytenr + BTRFS_SUPER_INFO_SIZE > device->total_bytes)
+ if (!check_sb_location(device, bytenr))
break;
btrfs_set_super_bytenr(sb, bytenr);
diff --git a/kernel-shared/zoned.c b/kernel-shared/zoned.c
index 206ad906c985..491d52eab942 100644
--- a/kernel-shared/zoned.c
+++ b/kernel-shared/zoned.c
@@ -1175,3 +1175,11 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info)
out:
return ret;
}
+
+bool btrfs_sb_zone_exists(struct btrfs_device *device, u64 bytenr)
+{
+ u32 zone_num = sb_bytenr_to_sb_zone(bytenr,
+ ilog2(device->zone_info->zone_size));
+
+ return zone_num + 1 <= device->zone_info->nr_zones - 1;
+}
diff --git a/kernel-shared/zoned.h b/kernel-shared/zoned.h
index f4b0d5d06301..6eba86d266bf 100644
--- a/kernel-shared/zoned.h
+++ b/kernel-shared/zoned.h
@@ -153,6 +153,7 @@ int btrfs_reset_all_zones(int fd, struct btrfs_zoned_device_info *zinfo);
int zero_zone_blocks(int fd, struct btrfs_zoned_device_info *zinfo, off_t start,
size_t len);
int btrfs_wipe_temporary_sb(struct btrfs_fs_devices *fs_devices);
+bool btrfs_sb_zone_exists(struct btrfs_device *device, u64 bytenr);
#else
@@ -225,6 +226,11 @@ static inline bool zoned_profile_supported(u64 map_type, bool rst)
return false;
}
+static inline bool btrfs_sb_zone_exists(struct btrfs_device *device, u64 bytenr)
+{
+ return true;
+}
+
#endif /* BTRFS_ZONED */
/*
--
2.42.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 0/2] btrfs-progs: zoned: check existence of SB zone, not LBA
2023-10-12 14:19 [PATCH 0/2] btrfs-progs: zoned: check existence of SB zone, not LBA Naohiro Aota
2023-10-12 14:19 ` [PATCH 1/2] btrfs-progs: zoned: introduce sb_bytenr_to_sb_zone() Naohiro Aota
2023-10-12 14:19 ` [PATCH 2/2] btrfs-progs: zoned: check SB zone existence properly Naohiro Aota
@ 2023-10-12 16:25 ` David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: David Sterba @ 2023-10-12 16:25 UTC (permalink / raw)
To: Naohiro Aota; +Cc: linux-btrfs
On Thu, Oct 12, 2023 at 11:19:28PM +0900, Naohiro Aota wrote:
> Running btrfs check can fail on a certain zoned decice setup (e.g,
> zone size = 128MB, device size = 16GB):
>
> (from generic/330)
> yes|/usr/local/bin/btrfs check --repair --force /dev/nullb1
> [1/7] checking root items
> Fixed 0 roots.
> [2/7] checking extents
> ERROR: zoned: failed to read zone info of 4096 and 4097: Invalid argument
> ERROR: failed to write super block for devid 1: write error: Input/output error
> failed to write new super block err -5
> failed to repair damaged filesystem, aborting
>
> This happens because write_dev_supers() is comparing the original
> superblock location vs the device size to check if it can write out a
> superblock copy or not.
>
> For the above example, since the first copy location (64MB) < device size
> (16GB), it tries to write out the copy. But, the copy must be written into
> zone 4096 (512G / zone size (128M) = 4096), which is out of the device.
I've added the text above to changelog of patch 2 as it's relevant for
the change.
> To address the issue, this series introduces check_sb_location() to check
> if a SB copy can be written out.
>
> The patch 1 is a preparation to factor out logic of converting the original
> superblock location to SB log writing superblock zone. And, the second one
> implements check_sb_location() to write_dev_supers().
>
> Naohiro Aota (2):
> btrfs-progs: zoned: introduce sb_bytenr_to_sb_zone()
> btrfs-progs: zoned: check SB zone existence properly
Added to devel, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread