From: Naohiro Aota <naohiro.aota@wdc.com>
To: linux-btrfs@vger.kernel.org, dsterba@suse.com
Cc: hare@suse.com, linux-fsdevel@vger.kernel.org,
Naohiro Aota <naohiro.aota@wdc.com>,
Josef Bacik <josef@toxicpanda.com>
Subject: [PATCH v15 32/42] btrfs: zoned: mark block groups to copy for device-replace
Date: Thu, 4 Feb 2021 19:22:11 +0900 [thread overview]
Message-ID: <a8afbd3f9cc9a892c5d4f810d29ca9faf6f807f0.1612434091.git.naohiro.aota@wdc.com> (raw)
In-Reply-To: <b36444df121d46c6d9638a8ae8eacecaa845fbe4.1612434091.git.naohiro.aota@wdc.com>
This is the 1/4 patch to support device-replace on zoned filesystems.
We have two types of I/Os during the device-replace process. One is an I/O
to "copy" (by the scrub functions) all the device extents from the source
device to the destination device. The other one is an I/O to "clone" (by
handle_ops_on_dev_replace()) new incoming write I/Os from users to the
source device into the target device.
Cloning incoming I/Os can break the sequential write rule in on target
device. When a write is mapped in the middle of a block group, the I/O is
directed to the middle of a target device zone, which breaks the
sequential write requirement.
However, the cloning function cannot be disabled since incoming I/Os
targeting already copied device extents must be cloned so that the I/O is
executed on the target device.
We cannot use dev_replace->cursor_{left,right} to determine whether a bio
is going to a not yet copied region. Since we have a time gap between
finishing btrfs_scrub_dev() and rewriting the mapping tree in
btrfs_dev_replace_finishing(), we can have a newly allocated device extent
which is never cloned nor copied.
So the point is to copy only already existing device extents. This patch
introduces mark_block_group_to_copy() to mark existing block groups as a
target of copying. Then, handle_ops_on_dev_replace() and dev-replace can
check the flag to do their job.
Also, btrfs_finish_block_group_to_copy() will check if the copied stripe
is the last stripe in the block group. With the last stripe copied,
the to_copy flag is finally disabled. Afterwards we can safely clone
incoming IOs on this block group.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
fs/btrfs/block-group.h | 1 +
fs/btrfs/dev-replace.c | 184 +++++++++++++++++++++++++++++++++++++++++
fs/btrfs/dev-replace.h | 3 +
fs/btrfs/scrub.c | 16 ++++
4 files changed, 204 insertions(+)
diff --git a/fs/btrfs/block-group.h b/fs/btrfs/block-group.h
index a07108d65c44..d37ee576ac6e 100644
--- a/fs/btrfs/block-group.h
+++ b/fs/btrfs/block-group.h
@@ -95,6 +95,7 @@ struct btrfs_block_group {
unsigned int iref:1;
unsigned int has_caching_ctl:1;
unsigned int removed:1;
+ unsigned int to_copy:1;
int disk_cache_state;
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index bc73f798ce3a..3a9c1e046ebe 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -22,6 +22,7 @@
#include "dev-replace.h"
#include "sysfs.h"
#include "zoned.h"
+#include "block-group.h"
/*
* Device replace overview
@@ -459,6 +460,185 @@ static char* btrfs_dev_name(struct btrfs_device *device)
return rcu_str_deref(device->name);
}
+static int mark_block_group_to_copy(struct btrfs_fs_info *fs_info,
+ struct btrfs_device *src_dev)
+{
+ struct btrfs_path *path;
+ struct btrfs_key key;
+ struct btrfs_key found_key;
+ struct btrfs_root *root = fs_info->dev_root;
+ struct btrfs_dev_extent *dev_extent = NULL;
+ struct btrfs_block_group *cache;
+ struct btrfs_trans_handle *trans;
+ int ret = 0;
+ u64 chunk_offset;
+
+ /* Do not use "to_copy" on non zoned filesystem for now */
+ if (!btrfs_is_zoned(fs_info))
+ return 0;
+
+ mutex_lock(&fs_info->chunk_mutex);
+
+ /* Ensure we don't have pending new block group */
+ spin_lock(&fs_info->trans_lock);
+ while (fs_info->running_transaction &&
+ !list_empty(&fs_info->running_transaction->dev_update_list)) {
+ spin_unlock(&fs_info->trans_lock);
+ mutex_unlock(&fs_info->chunk_mutex);
+ trans = btrfs_attach_transaction(root);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ mutex_lock(&fs_info->chunk_mutex);
+ if (ret == -ENOENT) {
+ spin_lock(&fs_info->trans_lock);
+ continue;
+ } else {
+ goto unlock;
+ }
+ }
+
+ ret = btrfs_commit_transaction(trans);
+ mutex_lock(&fs_info->chunk_mutex);
+ if (ret)
+ goto unlock;
+
+ spin_lock(&fs_info->trans_lock);
+ }
+ spin_unlock(&fs_info->trans_lock);
+
+ path = btrfs_alloc_path();
+ if (!path) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ path->reada = READA_FORWARD;
+ path->search_commit_root = 1;
+ path->skip_locking = 1;
+
+ key.objectid = src_dev->devid;
+ key.type = BTRFS_DEV_EXTENT_KEY;
+ key.offset = 0;
+
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0)
+ goto free_path;
+ if (ret > 0) {
+ if (path->slots[0] >=
+ btrfs_header_nritems(path->nodes[0])) {
+ ret = btrfs_next_leaf(root, path);
+ if (ret < 0)
+ goto free_path;
+ if (ret > 0) {
+ ret = 0;
+ goto free_path;
+ }
+ } else {
+ ret = 0;
+ }
+ }
+
+ while (1) {
+ struct extent_buffer *leaf = path->nodes[0];
+ int slot = path->slots[0];
+
+ btrfs_item_key_to_cpu(leaf, &found_key, slot);
+
+ if (found_key.objectid != src_dev->devid)
+ break;
+
+ if (found_key.type != BTRFS_DEV_EXTENT_KEY)
+ break;
+
+ if (found_key.offset < key.offset)
+ break;
+
+ dev_extent = btrfs_item_ptr(leaf, slot, struct btrfs_dev_extent);
+
+ chunk_offset = btrfs_dev_extent_chunk_offset(leaf, dev_extent);
+
+ cache = btrfs_lookup_block_group(fs_info, chunk_offset);
+ if (!cache)
+ goto skip;
+
+ spin_lock(&cache->lock);
+ cache->to_copy = 1;
+ spin_unlock(&cache->lock);
+
+ btrfs_put_block_group(cache);
+
+skip:
+ ret = btrfs_next_item(root, path);
+ if (ret != 0) {
+ if (ret > 0)
+ ret = 0;
+ break;
+ }
+ }
+
+free_path:
+ btrfs_free_path(path);
+unlock:
+ mutex_unlock(&fs_info->chunk_mutex);
+
+ return ret;
+}
+
+bool btrfs_finish_block_group_to_copy(struct btrfs_device *srcdev,
+ struct btrfs_block_group *cache,
+ u64 physical)
+{
+ struct btrfs_fs_info *fs_info = cache->fs_info;
+ struct extent_map *em;
+ struct map_lookup *map;
+ u64 chunk_offset = cache->start;
+ int num_extents, cur_extent;
+ int i;
+
+ /* Do not use "to_copy" on non zoned filesystem for now */
+ if (!btrfs_is_zoned(fs_info))
+ return true;
+
+ spin_lock(&cache->lock);
+ if (cache->removed) {
+ spin_unlock(&cache->lock);
+ return true;
+ }
+ spin_unlock(&cache->lock);
+
+ em = btrfs_get_chunk_map(fs_info, chunk_offset, 1);
+ ASSERT(!IS_ERR(em));
+ map = em->map_lookup;
+
+ num_extents = cur_extent = 0;
+ for (i = 0; i < map->num_stripes; i++) {
+ /* We have more device extent to copy */
+ if (srcdev != map->stripes[i].dev)
+ continue;
+
+ num_extents++;
+ if (physical == map->stripes[i].physical)
+ cur_extent = i;
+ }
+
+ free_extent_map(em);
+
+ if (num_extents > 1 && cur_extent < num_extents - 1) {
+ /*
+ * Has more stripes on this device. Keep this block group
+ * readonly until we finish all the stripes.
+ */
+ return false;
+ }
+
+ /* Last stripe on this device */
+ spin_lock(&cache->lock);
+ cache->to_copy = 0;
+ spin_unlock(&cache->lock);
+
+ return true;
+}
+
static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
const char *tgtdev_name, u64 srcdevid, const char *srcdev_name,
int read_src)
@@ -500,6 +680,10 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
if (ret)
return ret;
+ ret = mark_block_group_to_copy(fs_info, src_device);
+ if (ret)
+ return ret;
+
down_write(&dev_replace->rwsem);
switch (dev_replace->replace_state) {
case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
diff --git a/fs/btrfs/dev-replace.h b/fs/btrfs/dev-replace.h
index 60b70dacc299..3911049a5f23 100644
--- a/fs/btrfs/dev-replace.h
+++ b/fs/btrfs/dev-replace.h
@@ -18,5 +18,8 @@ int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info);
void btrfs_dev_replace_suspend_for_unmount(struct btrfs_fs_info *fs_info);
int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info);
int __pure btrfs_dev_replace_is_ongoing(struct btrfs_dev_replace *dev_replace);
+bool btrfs_finish_block_group_to_copy(struct btrfs_device *srcdev,
+ struct btrfs_block_group *cache,
+ u64 physical);
#endif
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 5f4f88a4d2c8..da4f9c24e42d 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -3561,6 +3561,16 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
if (!cache)
goto skip;
+ if (sctx->is_dev_replace && btrfs_is_zoned(fs_info)) {
+ spin_lock(&cache->lock);
+ if (!cache->to_copy) {
+ spin_unlock(&cache->lock);
+ ro_set = 0;
+ goto done;
+ }
+ spin_unlock(&cache->lock);
+ }
+
/*
* Make sure that while we are scrubbing the corresponding block
* group doesn't get its logical address and its device extents
@@ -3692,6 +3702,12 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
scrub_pause_off(fs_info);
+ if (sctx->is_dev_replace &&
+ !btrfs_finish_block_group_to_copy(dev_replace->srcdev,
+ cache, found_key.offset))
+ ro_set = 0;
+
+done:
down_write(&dev_replace->rwsem);
dev_replace->cursor_left = dev_replace->cursor_right;
dev_replace->item_needs_writeback = 1;
--
2.30.0
next prev parent reply other threads:[~2021-02-04 10:31 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-04 10:21 [PATCH v15 00/42] btrfs: zoned block device support Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 01/42] block: add bio_add_zone_append_page Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 02/42] iomap: support REQ_OP_ZONE_APPEND Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 03/42] btrfs: zoned: defer loading zone info after opening trees Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 04/42] btrfs: zoned: use regular super block location on zone emulation Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 05/42] btrfs: release path before calling to btrfs_load_block_group_zone_info Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 06/42] btrfs: zoned: do not load fs_info::zoned from incompat flag Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 07/42] btrfs: zoned: disallow fitrim on zoned filesystems Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 08/42] btrfs: zoned: allow zoned filesystems on non-zoned block devices Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 09/42] btrfs: zoned: implement zoned chunk allocator Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 10/42] btrfs: zoned: verify device extent is aligned to zone Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 11/42] btrfs: zoned: load zone's allocation offset Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 12/42] btrfs: zoned: calculate allocation offset for conventional zones Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 13/42] btrfs: zoned: track unusable bytes for zones Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 14/42] btrfs: zoned: implement sequential extent allocation Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 15/42] btrfs: zoned: redirty released extent buffers Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 16/42] btrfs: zoned: advance allocation pointer after tree log node Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 17/42] btrfs: zoned: reset zones of unused block groups Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 18/42] btrfs: factor out helper adding a page to bio Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 19/42] btrfs: zoned: use bio_add_zone_append_page Naohiro Aota
2021-02-04 10:21 ` [PATCH v15 20/42] btrfs: zoned: handle REQ_OP_ZONE_APPEND as writing Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 21/42] btrfs: zoned: split ordered extent when bio is sent Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 22/42] btrfs: zoned: check if bio spans across an ordered extent Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 23/42] btrfs: extend btrfs_rmap_block for specifying a device Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 24/42] btrfs: zoned: cache if block-group is on a sequential zone Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 25/42] btrfs: save irq flags when looking up an ordered extent Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 26/42] btrfs: zoned: use ZONE_APPEND write for zoned btrfs Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 27/42] btrfs: zoned: enable zone append writing for direct IO Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 28/42] btrfs: zoned: introduce dedicated data write path for zoned filesystems Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 29/42] btrfs: zoned: serialize metadata IO Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 30/42] btrfs: zoned: wait for existing extents before truncating Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 31/42] btrfs: zoned: do not use async metadata checksum on zoned filesystems Naohiro Aota
2021-02-04 10:22 ` Naohiro Aota [this message]
2021-02-04 10:22 ` [PATCH v15 33/42] btrfs: zoned: implement cloning for zoned device-replace Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 34/42] btrfs: zoned: implement copying " Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 35/42] btrfs: zoned: support dev-replace in zoned filesystems Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 36/42] btrfs: zoned: enable relocation on a zoned filesystem Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 37/42] btrfs: zoned: relocate block group to repair IO failure in zoned filesystems Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 38/42] btrfs: split alloc_log_tree() Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 39/42] btrfs: zoned: extend zoned allocator to use dedicated tree-log block group Naohiro Aota
2021-02-04 10:22 ` [PATCH v15 40/42] btrfs: zoned: serialize log transaction on zoned filesystems Naohiro Aota
2021-02-04 11:50 ` Filipe Manana
2021-02-05 7:21 ` Naohiro Aota
2021-02-05 9:15 ` Naohiro Aota
2021-02-05 11:21 ` Filipe Manana
2021-02-09 1:49 ` David Sterba
2021-02-04 10:22 ` [PATCH v15 41/42] btrfs: zoned: reorder log node allocation on zoned filesystem Naohiro Aota
2021-02-04 11:57 ` Filipe Manana
2021-02-04 14:54 ` Johannes Thumshirn
2021-02-04 15:48 ` David Sterba
2021-02-04 15:51 ` Johannes Thumshirn
2021-02-04 10:22 ` [PATCH v15 42/42] btrfs: zoned: enable to mount ZONED incompat flag Naohiro Aota
2021-02-05 9:26 ` [PATCH v15 43/43] btrfs: zoned: deal with holes writing out tree-log pages Naohiro Aota
2021-02-05 11:49 ` Filipe Manana
2021-02-05 12:55 ` Naohiro Aota
2021-02-05 13:07 ` Filipe Manana
2021-02-05 14:19 ` Filipe Manana
2021-02-05 14:46 ` Naohiro Aota
2021-02-05 14:58 ` [PATCH v15.1 " Naohiro Aota
2021-02-05 16:25 ` Filipe Manana
2021-02-09 1:55 ` David Sterba
2021-02-10 19:58 ` [PATCH v15 00/42] btrfs: zoned block device support David Sterba
2021-02-11 9:58 ` Johannes Thumshirn
2021-02-11 15:19 ` David Sterba
2021-02-11 15:26 ` Johannes Thumshirn
2021-02-11 15:46 ` David Sterba
2021-02-15 16:58 ` Johannes Thumshirn
2021-02-15 17:02 ` David Sterba
2021-02-16 4:33 ` Naohiro Aota
2021-02-16 11:46 ` David Sterba
2021-02-22 7:50 ` Naohiro Aota
2021-02-22 16:00 ` David Sterba
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a8afbd3f9cc9a892c5d4f810d29ca9faf6f807f0.1612434091.git.naohiro.aota@wdc.com \
--to=naohiro.aota@wdc.com \
--cc=dsterba@suse.com \
--cc=hare@suse.com \
--cc=josef@toxicpanda.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).