[v4,14/27] btrfs: limit super block locations in HMZONED mode
diff mbox series

Message ID 20190823101036.796932-15-naohiro.aota@wdc.com
State New
Headers show
Series
  • btrfs zoned block device support
Related show

Commit Message

Naohiro Aota Aug. 23, 2019, 10:10 a.m. UTC
When in HMZONED mode, make sure that device super blocks are located in
randomly writable zones of zoned block devices. That is, do not write super
blocks in sequential write required zones of host-managed zoned block
devices as update would not be possible.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
 fs/btrfs/disk-io.c     |  4 ++++
 fs/btrfs/extent-tree.c |  8 ++++++++
 fs/btrfs/hmzoned.h     | 12 ++++++++++++
 fs/btrfs/scrub.c       |  3 +++
 4 files changed, 27 insertions(+)

Patch
diff mbox series

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b25cff8af3b7..38a9830b4893 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3545,6 +3545,8 @@  static int write_dev_supers(struct btrfs_device *device,
 		if (bytenr + BTRFS_SUPER_INFO_SIZE >=
 		    device->commit_total_bytes)
 			break;
+		if (!btrfs_check_super_location(device, bytenr))
+			continue;
 
 		btrfs_set_super_bytenr(sb, bytenr);
 
@@ -3611,6 +3613,8 @@  static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
 		if (bytenr + BTRFS_SUPER_INFO_SIZE >=
 		    device->commit_total_bytes)
 			break;
+		if (!btrfs_check_super_location(device, bytenr))
+			continue;
 
 		bh = __find_get_block(device->bdev,
 				      bytenr / BTRFS_BDEV_BLOCKSIZE,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 457252ac7782..ddf5c26b9f58 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -239,6 +239,14 @@  static int exclude_super_stripes(struct btrfs_block_group_cache *cache)
 			if (logical[nr] + stripe_len <= cache->key.objectid)
 				continue;
 
+			/* shouldn't have super stripes in sequential zones */
+			if (cache->alloc_type == BTRFS_ALLOC_SEQ) {
+				btrfs_err(fs_info,
+		"sequentil allocation bg %llu should not have super blocks",
+					  cache->key.objectid);
+				return -EUCLEAN;
+			}
+
 			start = logical[nr];
 			if (start < cache->key.objectid) {
 				start = cache->key.objectid;
diff --git a/fs/btrfs/hmzoned.h b/fs/btrfs/hmzoned.h
index 40b4151fc935..9de26d6b8c4e 100644
--- a/fs/btrfs/hmzoned.h
+++ b/fs/btrfs/hmzoned.h
@@ -10,6 +10,7 @@ 
 #define BTRFS_HMZONED_H
 
 #include <linux/blkdev.h>
+#include "volumes.h"
 
 struct btrfs_zoned_device_info {
 	/*
@@ -125,4 +126,15 @@  static inline bool btrfs_can_zone_reset(struct btrfs_device *device,
 	return true;
 }
 
+static inline bool btrfs_check_super_location(struct btrfs_device *device,
+					      u64 pos)
+{
+	/*
+	 * On a non-zoned device, any address is OK. On a zoned
+	 * device, non-SEQUENTIAL WRITE REQUIRED zones are capable.
+	 */
+	return device->zone_info == NULL ||
+		!btrfs_dev_is_sequential(device, pos);
+}
+
 #endif
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 0c99cf9fb595..e15d846c700a 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -18,6 +18,7 @@ 
 #include "check-integrity.h"
 #include "rcu-string.h"
 #include "raid56.h"
+#include "hmzoned.h"
 
 /*
  * This is only the first step towards a full-features scrub. It reads all
@@ -3732,6 +3733,8 @@  static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
 		if (bytenr + BTRFS_SUPER_INFO_SIZE >
 		    scrub_dev->commit_total_bytes)
 			break;
+		if (!btrfs_check_super_location(scrub_dev, bytenr))
+			continue;
 
 		ret = scrub_pages(sctx, bytenr, BTRFS_SUPER_INFO_SIZE, bytenr,
 				  scrub_dev, BTRFS_EXTENT_FLAG_SUPER, gen, i,