From: Zhang Yi <yi.zhang@huaweicloud.com>
To: linux-ext4@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org, tytso@mit.edu,
adilger.kernel@dilger.ca, jack@suse.cz, ritesh.list@gmail.com,
hch@infradead.org, djwong@kernel.org, yi.zhang@huawei.com,
yi.zhang@huaweicloud.com, chengzhihao1@huawei.com,
yukuai3@huawei.com
Subject: [RFC PATCH 07/18] ext4: allow reserving multi-delayed blocks
Date: Thu, 23 Nov 2023 20:51:09 +0800 [thread overview]
Message-ID: <20231123125121.4064694-8-yi.zhang@huaweicloud.com> (raw)
In-Reply-To: <20231123125121.4064694-1-yi.zhang@huaweicloud.com>
From: Zhang Yi <yi.zhang@huawei.com>
Introduce a new helper ext4_insert_delayed_blocks() to support adding
multi-delayed blocks into the extent status tree, it doesn't support
bigalloc feature yet. Also rename ext4_es_insert_delayed_block() to
ext4_es_insert_delayed_extent(), which matches the name style of other
ext4_es_{insert|remove}_extent() helpers.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/extents_status.c | 20 +++++----
fs/ext4/extents_status.h | 4 +-
fs/ext4/inode.c | 82 ++++++++++++++++++++++++-------------
include/trace/events/ext4.h | 12 +++---
4 files changed, 74 insertions(+), 44 deletions(-)
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 19a0cc904cd8..c8783b4009ec 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -2043,19 +2043,21 @@ bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk)
}
/*
- * ext4_es_insert_delayed_block - adds a delayed block to the extents status
- * tree, adding a pending reservation where
- * needed
+ * ext4_es_insert_delayed_extent - adds delayed blocks to the extents status
+ * tree, adding a pending reservation where
+ * needed
*
* @inode - file containing the newly added block
- * @lblk - logical block to be added
+ * @lblk - first logical block to be added
+ * @len - length of blocks to be added
* @allocated - indicates whether a physical cluster has been allocated for
* the logical cluster that contains the block
*/
-void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
- bool allocated)
+void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
+ unsigned int len, bool allocated)
{
struct extent_status newes;
+ ext4_lblk_t end = lblk + len - 1;
int err1 = 0;
int err2 = 0;
struct extent_status *es1 = NULL;
@@ -2068,9 +2070,9 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
lblk, inode->i_ino);
newes.es_lblk = lblk;
- newes.es_len = 1;
+ newes.es_len = len;
ext4_es_store_pblock_status(&newes, ~0, EXTENT_STATUS_DELAYED);
- trace_ext4_es_insert_delayed_block(inode, &newes, allocated);
+ trace_ext4_es_insert_delayed_extent(inode, &newes, allocated);
ext4_es_insert_extent_check(inode, &newes);
@@ -2081,7 +2083,7 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
es2 = __es_alloc_extent(true);
write_lock(&EXT4_I(inode)->i_es_lock);
- err1 = __es_remove_extent(inode, lblk, lblk, NULL, es1);
+ err1 = __es_remove_extent(inode, lblk, end, NULL, es1);
if (err1 != 0)
goto error;
/* Free preallocated extent if it didn't get used. */
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
index 4f69322dd626..4ccc965a9876 100644
--- a/fs/ext4/extents_status.h
+++ b/fs/ext4/extents_status.h
@@ -251,8 +251,8 @@ extern void ext4_exit_pending(void);
extern void ext4_init_pending_tree(struct ext4_pending_tree *tree);
extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk);
extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk);
-extern void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
- bool allocated);
+extern void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
+ unsigned int len, bool allocated);
extern unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk,
ext4_lblk_t len);
extern void ext4_clear_inode_es(struct inode *inode);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 17fe2bd83617..e92b205b3b24 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1462,7 +1462,7 @@ static int ext4_journalled_write_end(struct file *file,
/*
* Reserve space for a single cluster
*/
-static int ext4_da_reserve_space(struct inode *inode)
+static int ext4_da_reserve_space(struct inode *inode, unsigned int len)
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
struct ext4_inode_info *ei = EXT4_I(inode);
@@ -1473,18 +1473,18 @@ static int ext4_da_reserve_space(struct inode *inode)
* us from metadata over-estimation, though we may go over by
* a small amount in the end. Here we just reserve for data.
*/
- ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1));
+ ret = dquot_reserve_block(inode, EXT4_C2B(sbi, len));
if (ret)
return ret;
spin_lock(&ei->i_block_reservation_lock);
- if (ext4_claim_free_clusters(sbi, 1, 0)) {
+ if (ext4_claim_free_clusters(sbi, len, 0)) {
spin_unlock(&ei->i_block_reservation_lock);
- dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
+ dquot_release_reservation_block(inode, EXT4_C2B(sbi, len));
return -ENOSPC;
}
- ei->i_reserved_data_blocks++;
- trace_ext4_da_reserve_space(inode);
+ ei->i_reserved_data_blocks += len;
+ trace_ext4_da_reserve_space(inode, len);
spin_unlock(&ei->i_block_reservation_lock);
return 0; /* success */
@@ -1630,6 +1630,37 @@ static void ext4_print_free_blocks(struct inode *inode)
return;
}
+
+/*
+ * ext4_insert_delayed_blocks - adds multi-delayed blocks to the extents
+ * status tree, incrementing the reserved
+ * cluster/block count or making a pending
+ * reservation where needed.
+ *
+ * @inode - file containing the newly added block
+ * @lblk - start logical block to be added
+ * @len - length of blocks to be added
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+static int ext4_insert_delayed_blocks(struct inode *inode, ext4_lblk_t lblk,
+ ext4_lblk_t len)
+{
+ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ int ret;
+
+ /* TODO: support bigalloc and replace ext4_insert_delayed_block(). */
+ if (sbi->s_cluster_ratio != 1)
+ return -EOPNOTSUPP;
+
+ ret = ext4_da_reserve_space(inode, len);
+ if (ret) /* ENOSPC */
+ return ret;
+
+ ext4_es_insert_delayed_extent(inode, lblk, len, false);
+ return 0;
+}
+
/*
* ext4_insert_delayed_block - adds a delayed block to the extents status
* tree, incrementing the reserved cluster/block
@@ -1647,10 +1678,13 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
int ret;
bool allocated = false;
+ if (sbi->s_cluster_ratio == 1)
+ return ext4_insert_delayed_blocks(inode, lblk, 1);
+
/*
- * If the cluster containing lblk is shared with a delayed,
- * written, or unwritten extent in a bigalloc file system, it's
- * already been accounted for and does not need to be reserved.
+ * For bigalloc, if the cluster containing lblk is shared with a
+ * delayed, written, or unwritten extent in a bigalloc file system,
+ * it's already been accounted for and does not need to be reserved.
* A pending reservation must be made for the cluster if it's
* shared with a written or unwritten extent and doesn't already
* have one. Written and unwritten extents can be purged from the
@@ -1658,32 +1692,24 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
* it's necessary to examine the extent tree if a search of the
* extents status tree doesn't get a match.
*/
- if (sbi->s_cluster_ratio == 1) {
- ret = ext4_da_reserve_space(inode);
- if (ret != 0) /* ENOSPC */
- return ret;
- } else { /* bigalloc */
- if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) {
- if (!ext4_es_scan_clu(inode,
- &ext4_es_is_mapped, lblk)) {
- ret = ext4_clu_mapped(inode,
- EXT4_B2C(sbi, lblk));
- if (ret < 0)
+ if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) {
+ if (!ext4_es_scan_clu(inode, &ext4_es_is_mapped, lblk)) {
+ ret = ext4_clu_mapped(inode, EXT4_B2C(sbi, lblk));
+ if (ret < 0)
+ return ret;
+ if (ret == 0) {
+ ret = ext4_da_reserve_space(inode, 1);
+ if (ret != 0) /* ENOSPC */
return ret;
- if (ret == 0) {
- ret = ext4_da_reserve_space(inode);
- if (ret != 0) /* ENOSPC */
- return ret;
- } else {
- allocated = true;
- }
} else {
allocated = true;
}
+ } else {
+ allocated = true;
}
}
- ext4_es_insert_delayed_block(inode, lblk, allocated);
+ ext4_es_insert_delayed_extent(inode, lblk, 1, allocated);
return 0;
}
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 84421cecec0b..6b871d42b259 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -1249,14 +1249,15 @@ TRACE_EVENT(ext4_da_update_reserve_space,
);
TRACE_EVENT(ext4_da_reserve_space,
- TP_PROTO(struct inode *inode),
+ TP_PROTO(struct inode *inode, int reserved_blocks),
- TP_ARGS(inode),
+ TP_ARGS(inode, reserved_blocks),
TP_STRUCT__entry(
__field( dev_t, dev )
__field( ino_t, ino )
__field( __u64, i_blocks )
+ __field( int, reserved_blocks )
__field( int, reserved_data_blocks )
__field( __u16, mode )
),
@@ -1265,16 +1266,17 @@ TRACE_EVENT(ext4_da_reserve_space,
__entry->dev = inode->i_sb->s_dev;
__entry->ino = inode->i_ino;
__entry->i_blocks = inode->i_blocks;
+ __entry->reserved_blocks = reserved_blocks;
__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
__entry->mode = inode->i_mode;
),
- TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu "
+ TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu reserved_blocks %u "
"reserved_data_blocks %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino,
__entry->mode, __entry->i_blocks,
- __entry->reserved_data_blocks)
+ __entry->reserved_blocks, __entry->reserved_data_blocks)
);
TRACE_EVENT(ext4_da_release_space,
@@ -2509,7 +2511,7 @@ TRACE_EVENT(ext4_es_shrink,
__entry->scan_time, __entry->nr_skipped, __entry->retried)
);
-TRACE_EVENT(ext4_es_insert_delayed_block,
+TRACE_EVENT(ext4_es_insert_delayed_extent,
TP_PROTO(struct inode *inode, struct extent_status *es,
bool allocated),
--
2.39.2
next prev parent reply other threads:[~2023-11-23 12:52 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-23 12:51 [RFC PATCH 00/18] ext4: use iomap for regular file's buffered IO path and enable large foilo Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 01/18] ext4: introduce ext4_es_skip_hole_extent() to skip hole extents Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 02/18] ext4: make ext4_es_lookup_extent() return the next extent if not found Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 03/18] ext4: correct the hole length returned by ext4_map_blocks() Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 04/18] ext4: add a hole extent entry in cache after punch Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 05/18] ext4: make ext4_map_blocks() distinguish delayed only mapping Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 06/18] ext4: make ext4_set_iomap() recognize IOMAP_DELALLOC mapping type Zhang Yi
2023-11-23 12:51 ` Zhang Yi [this message]
2023-11-23 12:51 ` [RFC PATCH 08/18] ext4: add a new iomap aops for regular file's buffered IO path Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 09/18] ext4: implement buffered read iomap path Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 10/18] ext4: implement buffered write " Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 11/18] iomap: add a fs private parameter to iomap_ioend Zhang Yi
2023-11-23 15:36 ` Christoph Hellwig
2023-11-24 1:36 ` Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 12/18] iomap: don't increase i_size if it's not a write operation Zhang Yi
2023-11-23 15:34 ` Christoph Hellwig
2023-11-24 1:41 ` Zhang Yi
2023-11-30 12:26 ` Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 13/18] ext4: impliment writeback iomap path Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 14/18] ext4: impliment zero_range " Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 15/18] ext4: writeback partial blocks before zero range Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 16/18] ext4: impliment mmap iomap path Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 17/18] ext4: partial enable iomap for regular file's buffered IO path Zhang Yi
2023-11-24 13:57 ` Zhang Yi
2023-11-23 12:51 ` Zhang Yi
2023-11-23 12:51 ` [RFC PATCH 18/18] ext4: enable large folio for regular file which has been switched to use iomap Zhang Yi
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=20231123125121.4064694-8-yi.zhang@huaweicloud.com \
--to=yi.zhang@huaweicloud.com \
--cc=adilger.kernel@dilger.ca \
--cc=chengzhihao1@huawei.com \
--cc=djwong@kernel.org \
--cc=hch@infradead.org \
--cc=jack@suse.cz \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=ritesh.list@gmail.com \
--cc=tytso@mit.edu \
--cc=yi.zhang@huawei.com \
--cc=yukuai3@huawei.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).