From: Naohiro Aota <naohiro.aota@wdc.com>
To: linux-btrfs@vger.kernel.org, David Sterba <dsterba@suse.com>
Cc: Chris Mason <clm@fb.com>, Josef Bacik <josef@toxicpanda.com>,
Nikolay Borisov <nborisov@suse.com>,
Damien Le Moal <damien.lemoal@wdc.com>,
Matias Bjorling <Matias.Bjorling@wdc.com>,
Johannes Thumshirn <jthumshirn@suse.de>,
Hannes Reinecke <hare@suse.com>,
Anand Jain <anand.jain@oracle.com>,
linux-fsdevel@vger.kernel.org,
Naohiro Aota <naohiro.aota@wdc.com>
Subject: [PATCH v4 16/27] btrfs: serialize data allocation and submit IOs
Date: Fri, 23 Aug 2019 19:10:25 +0900 [thread overview]
Message-ID: <20190823101036.796932-17-naohiro.aota@wdc.com> (raw)
In-Reply-To: <20190823101036.796932-1-naohiro.aota@wdc.com>
To preserve sequential write pattern on the drives, we must serialize
allocation and submit_bio. This commit add per-block group mutex
"zone_io_lock" and find_free_extent_seq() hold the lock. The lock is kept
even after returning from find_free_extent(). It is released when submiting
IOs corresponding to the allocation is completed.
Implementing such behavior under __extent_writepage_io is almost impossible
because once pages are unlocked we are not sure when submiting IOs for an
allocated region is finished or not. Instead, this commit add
run_delalloc_hmzoned() to write out non-compressed data IOs at once using
extent_write_locked_rage(). After the write, we can call
btrfs_hmzoned_unlock_allocation() to unlock the block group for new
allocation.
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
fs/btrfs/ctree.h | 1 +
fs/btrfs/extent-tree.c | 5 +++++
fs/btrfs/hmzoned.h | 34 +++++++++++++++++++++++++++++++
fs/btrfs/inode.c | 45 ++++++++++++++++++++++++++++++++++++++++--
4 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3b24ce49e84b..d4df9624cb04 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -618,6 +618,7 @@ struct btrfs_block_group_cache {
* zone.
*/
u64 alloc_offset;
+ struct mutex zone_io_lock;
};
/* delayed seq elem */
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c0d7cb95a8c9..9f9c09e28b5b 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -5533,6 +5533,7 @@ static int find_free_extent_seq(struct btrfs_block_group_cache *cache,
if (cache->alloc_type != BTRFS_ALLOC_SEQ)
return 1;
+ btrfs_hmzoned_data_io_lock(cache);
spin_lock(&space_info->lock);
spin_lock(&cache->lock);
@@ -5564,6 +5565,9 @@ static int find_free_extent_seq(struct btrfs_block_group_cache *cache,
out:
spin_unlock(&cache->lock);
spin_unlock(&space_info->lock);
+ /* if succeeds, unlock after submit_bio */
+ if (ret)
+ btrfs_hmzoned_data_io_unlock(cache);
return ret;
}
@@ -8096,6 +8100,7 @@ btrfs_create_block_group_cache(struct btrfs_fs_info *fs_info,
btrfs_init_free_space_ctl(cache);
atomic_set(&cache->trimming, 0);
mutex_init(&cache->free_space_lock);
+ mutex_init(&cache->zone_io_lock);
btrfs_init_full_stripe_locks_tree(&cache->full_stripe_locks_root);
cache->alloc_type = BTRFS_ALLOC_FIT;
diff --git a/fs/btrfs/hmzoned.h b/fs/btrfs/hmzoned.h
index 3a73c3c5e1da..a8e7286708d4 100644
--- a/fs/btrfs/hmzoned.h
+++ b/fs/btrfs/hmzoned.h
@@ -39,6 +39,7 @@ int btrfs_hmzoned_check_metadata_space(struct btrfs_fs_info *fs_info);
void btrfs_redirty_list_add(struct btrfs_transaction *trans,
struct extent_buffer *eb);
void btrfs_free_redirty_list(struct btrfs_transaction *trans);
+void btrfs_hmzoned_data_io_unlock_at(struct inode *inode, u64 start, u64 len);
static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)
{
@@ -140,4 +141,37 @@ static inline bool btrfs_check_super_location(struct btrfs_device *device,
!btrfs_dev_is_sequential(device, pos);
}
+
+static inline void btrfs_hmzoned_data_io_lock(
+ struct btrfs_block_group_cache *cache)
+{
+ /* No need to lock metadata BGs or non-sequential BGs */
+ if (!(cache->flags & BTRFS_BLOCK_GROUP_DATA) ||
+ cache->alloc_type != BTRFS_ALLOC_SEQ)
+ return;
+ mutex_lock(&cache->zone_io_lock);
+}
+
+static inline void btrfs_hmzoned_data_io_unlock(
+ struct btrfs_block_group_cache *cache)
+{
+ if (!(cache->flags & BTRFS_BLOCK_GROUP_DATA) ||
+ cache->alloc_type != BTRFS_ALLOC_SEQ)
+ return;
+ mutex_unlock(&cache->zone_io_lock);
+}
+
+static inline void btrfs_hmzoned_data_io_unlock_logical(
+ struct btrfs_fs_info *fs_info, u64 logical)
+{
+ struct btrfs_block_group_cache *cache;
+
+ if (!btrfs_fs_incompat(fs_info, HMZONED))
+ return;
+
+ cache = btrfs_lookup_block_group(fs_info, logical);
+ btrfs_hmzoned_data_io_unlock(cache);
+ btrfs_put_block_group(cache);
+}
+
#endif
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index ee582a36653d..d504200c9767 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -48,6 +48,7 @@
#include "qgroup.h"
#include "dedupe.h"
#include "delalloc-space.h"
+#include "hmzoned.h"
struct btrfs_iget_args {
struct btrfs_key *location;
@@ -1279,6 +1280,39 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
return 0;
}
+static noinline int run_delalloc_hmzoned(struct inode *inode,
+ struct page *locked_page, u64 start,
+ u64 end, int *page_started,
+ unsigned long *nr_written)
+{
+ struct extent_map *em;
+ u64 logical;
+ int ret;
+
+ ret = cow_file_range(inode, locked_page, start, end,
+ end, page_started, nr_written, 0, NULL);
+ if (ret)
+ return ret;
+
+ if (*page_started)
+ return 0;
+
+ em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, end - start + 1,
+ 0);
+ ASSERT(em != NULL && em->block_start < EXTENT_MAP_LAST_BYTE);
+ logical = em->block_start;
+ free_extent_map(em);
+
+ __set_page_dirty_nobuffers(locked_page);
+ account_page_redirty(locked_page);
+ extent_write_locked_range(inode, start, end, WB_SYNC_ALL);
+ *page_started = 1;
+
+ btrfs_hmzoned_data_io_unlock_logical(btrfs_sb(inode->i_sb), logical);
+
+ return 0;
+}
+
static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info,
u64 bytenr, u64 num_bytes)
{
@@ -1645,17 +1679,24 @@ int btrfs_run_delalloc_range(struct inode *inode, struct page *locked_page,
int ret;
int force_cow = need_force_cow(inode, start, end);
unsigned int write_flags = wbc_to_write_flags(wbc);
+ int do_compress = inode_can_compress(inode) &&
+ inode_need_compress(inode, start, end);
+ int hmzoned = btrfs_fs_incompat(btrfs_sb(inode->i_sb), HMZONED);
if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW && !force_cow) {
+ ASSERT(!hmzoned);
ret = run_delalloc_nocow(inode, locked_page, start, end,
page_started, 1, nr_written);
} else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC && !force_cow) {
+ ASSERT(!hmzoned);
ret = run_delalloc_nocow(inode, locked_page, start, end,
page_started, 0, nr_written);
- } else if (!inode_can_compress(inode) ||
- !inode_need_compress(inode, start, end)) {
+ } else if (!do_compress && !hmzoned) {
ret = cow_file_range(inode, locked_page, start, end, end,
page_started, nr_written, 1, NULL);
+ } else if (!do_compress && hmzoned) {
+ ret = run_delalloc_hmzoned(inode, locked_page, start, end,
+ page_started, nr_written);
} else {
set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
&BTRFS_I(inode)->runtime_flags);
--
2.23.0
next prev parent reply other threads:[~2019-08-23 10:11 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-23 10:10 [PATCH v4 00/27] btrfs zoned block device support Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 01/27] btrfs: introduce HMZONED feature flag Naohiro Aota
2019-08-23 11:45 ` Johannes Thumshirn
2019-08-23 10:10 ` [PATCH v4 02/27] btrfs: Get zone information of zoned block devices Naohiro Aota
2019-08-23 11:57 ` Johannes Thumshirn
2019-08-26 6:29 ` Naohiro Aota
2019-08-24 9:22 ` kbuild test robot
2019-08-24 10:49 ` kbuild test robot
2019-08-23 10:10 ` [PATCH v4 03/27] btrfs: Check and enable HMZONED mode Naohiro Aota
2019-08-23 12:07 ` Johannes Thumshirn
2019-08-26 8:38 ` Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 04/27] btrfs: disallow RAID5/6 in " Naohiro Aota
2019-08-23 12:09 ` Johannes Thumshirn
2019-08-23 10:10 ` [PATCH v4 05/27] btrfs: disallow space_cache " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 06/27] btrfs: disallow NODATACOW " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 07/27] btrfs: disable tree-log " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 08/27] btrfs: disable fallocate " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 09/27] btrfs: align device extent allocation to zone boundary Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 10/27] btrfs: do sequential extent allocation in HMZONED mode Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 11/27] btrfs: make unmirroed BGs readonly only if we have at least one writable BG Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 12/27] btrfs: ensure metadata space available on/after degraded mount in HMZONED Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 13/27] btrfs: reset zones of unused block groups Naohiro Aota
2019-08-24 11:32 ` kbuild test robot
2019-08-25 4:56 ` kbuild test robot
2019-08-23 10:10 ` [PATCH v4 14/27] btrfs: limit super block locations in HMZONED mode Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 15/27] btrfs: redirty released extent buffers in sequential BGs Naohiro Aota
2019-08-23 10:10 ` Naohiro Aota [this message]
2019-08-23 10:10 ` [PATCH v4 17/27] btrfs: implement atomic compressed IO submission Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 18/27] btrfs: support direct write IO in HMZONED Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 19/27] btrfs: serialize meta IOs on HMZONED mode Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 20/27] btrfs: wait existing extents before truncating Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 21/27] btrfs: avoid async checksum/submit on HMZONED mode Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 22/27] btrfs: disallow mixed-bg in " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 23/27] btrfs: disallow inode_cache " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 24/27] btrfs: support dev-replace " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 25/27] btrfs: enable relocation " Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 26/27] btrfs: relocate block group to repair IO failure in HMZONED Naohiro Aota
2019-08-23 10:10 ` [PATCH v4 27/27] btrfs: enable to mount HMZONED incompat flag Naohiro Aota
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=20190823101036.796932-17-naohiro.aota@wdc.com \
--to=naohiro.aota@wdc.com \
--cc=Matias.Bjorling@wdc.com \
--cc=anand.jain@oracle.com \
--cc=clm@fb.com \
--cc=damien.lemoal@wdc.com \
--cc=dsterba@suse.com \
--cc=hare@suse.com \
--cc=josef@toxicpanda.com \
--cc=jthumshirn@suse.de \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=nborisov@suse.com \
/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).