From: Andreas Gruenbacher <agruenba@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [RFC v6 08/10] iomap/xfs: Eliminate the iomap_valid handler
Date: Sun, 8 Jan 2023 20:40:32 +0100 [thread overview]
Message-ID: <20230108194034.1444764-9-agruenba@redhat.com> (raw)
In-Reply-To: <20230108194034.1444764-1-agruenba@redhat.com>
Eliminate the ->iomap_valid() handler by switching to a ->get_folio()
handler and validating the mapping there.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/iomap/buffered-io.c | 26 +++++---------------------
fs/xfs/xfs_iomap.c | 37 ++++++++++++++++++++++++++-----------
include/linux/iomap.h | 23 ++++++-----------------
3 files changed, 37 insertions(+), 49 deletions(-)
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 006ddf933948..72dfbc3cb086 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -638,10 +638,9 @@ static int iomap_write_begin_inline(const struct iomap_iter *iter,
static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
size_t len, struct folio **foliop)
{
- const struct iomap_page_ops *page_ops = iter->iomap.page_ops;
const struct iomap *srcmap = iomap_iter_srcmap(iter);
struct folio *folio;
- int status = 0;
+ int status;
BUG_ON(pos + len > iter->iomap.offset + iter->iomap.length);
if (srcmap != &iter->iomap)
@@ -654,27 +653,12 @@ static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
folio = __iomap_get_folio(iter, pos, len);
- if (IS_ERR(folio))
- return PTR_ERR(folio);
-
- /*
- * Now we have a locked folio, before we do anything with it we need to
- * check that the iomap we have cached is not stale. The inode extent
- * mapping can change due to concurrent IO in flight (e.g.
- * IOMAP_UNWRITTEN state can change and memory reclaim could have
- * reclaimed a previously partially written page at this index after IO
- * completion before this write reaches this file offset) and hence we
- * could do the wrong thing here (zero a page range incorrectly or fail
- * to zero) and corrupt data.
- */
- if (page_ops && page_ops->iomap_valid) {
- bool iomap_valid = page_ops->iomap_valid(iter->inode,
- &iter->iomap);
- if (!iomap_valid) {
+ if (IS_ERR(folio)) {
+ if (folio == ERR_PTR(-ESTALE)) {
iter->iomap.flags |= IOMAP_F_STALE;
- status = 0;
- goto out_unlock;
+ return 0;
}
+ return PTR_ERR(folio);
}
if (pos + len > folio_pos(folio) + folio_size(folio))
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 669c1bc5c3a7..d0bf99539180 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -62,29 +62,44 @@ xfs_iomap_inode_sequence(
return cookie | READ_ONCE(ip->i_df.if_seq);
}
-/*
- * Check that the iomap passed to us is still valid for the given offset and
- * length.
- */
-static bool
-xfs_iomap_valid(
- struct inode *inode,
- const struct iomap *iomap)
+static struct folio *
+xfs_get_folio(
+ struct iomap_iter *iter,
+ loff_t pos,
+ unsigned len)
{
+ struct inode *inode = iter->inode;
+ struct iomap *iomap = &iter->iomap;
struct xfs_inode *ip = XFS_I(inode);
+ struct folio *folio;
+ folio = iomap_get_folio(iter, pos);
+ if (IS_ERR(folio))
+ return folio;
+
+ /*
+ * Now that we have a locked folio, we need to check that the iomap we
+ * have cached is not stale. The inode extent mapping can change due to
+ * concurrent IO in flight (e.g., IOMAP_UNWRITTEN state can change and
+ * memory reclaim could have reclaimed a previously partially written
+ * page at this index after IO completion before this write reaches
+ * this file offset) and hence we could do the wrong thing here (zero a
+ * page range incorrectly or fail to zero) and corrupt data.
+ */
if (iomap->validity_cookie !=
xfs_iomap_inode_sequence(ip, iomap->flags)) {
trace_xfs_iomap_invalid(ip, iomap);
- return false;
+ folio_unlock(folio);
+ folio_put(folio);
+ return ERR_PTR(-ESTALE);
}
XFS_ERRORTAG_DELAY(ip->i_mount, XFS_ERRTAG_WRITE_DELAY_MS);
- return true;
+ return folio;
}
const struct iomap_page_ops xfs_iomap_page_ops = {
- .iomap_valid = xfs_iomap_valid,
+ .get_folio = xfs_get_folio,
};
int
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index da226032aedc..0ae2cddbedd6 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -134,29 +134,18 @@ static inline bool iomap_inline_data_valid(const struct iomap *iomap)
* When get_folio succeeds, put_folio will always be called to do any
* cleanup work necessary. put_folio is responsible for unlocking and putting
* @folio.
+ *
+ * When an iomap is created, the filesystem can store internal state (e.g., a
+ * sequence number) in iomap->validity_cookie. The get_folio handler can use
+ * this validity cookie to detect when the iomap needs to be refreshed because
+ * it is no longer up to date. In that case, the function should return
+ * ERR_PTR(-ESTALE) to retry the operation with a fresh mapping.
*/
struct iomap_page_ops {
struct folio *(*get_folio)(struct iomap_iter *iter, loff_t pos,
unsigned len);
void (*put_folio)(struct inode *inode, loff_t pos, unsigned copied,
struct folio *folio);
-
- /*
- * Check that the cached iomap still maps correctly to the filesystem's
- * internal extent map. FS internal extent maps can change while iomap
- * is iterating a cached iomap, so this hook allows iomap to detect that
- * the iomap needs to be refreshed during a long running write
- * operation.
- *
- * The filesystem can store internal state (e.g. a sequence number) in
- * iomap->validity_cookie when the iomap is first mapped to be able to
- * detect changes between mapping time and whenever .iomap_valid() is
- * called.
- *
- * This is called with the folio over the specified file position held
- * locked by the iomap code.
- */
- bool (*iomap_valid)(struct inode *inode, const struct iomap *iomap);
};
/*
--
2.38.1
WARNING: multiple messages have this Message-ID (diff)
From: Andreas Gruenbacher <agruenba@redhat.com>
To: Christoph Hellwig <hch@infradead.org>,
"Darrick J . Wong" <djwong@kernel.org>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Matthew Wilcox <willy@infradead.org>
Cc: Andreas Gruenbacher <agruenba@redhat.com>,
linux-xfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-ext4@vger.kernel.org, cluster-devel@redhat.com
Subject: [RFC v6 08/10] iomap/xfs: Eliminate the iomap_valid handler
Date: Sun, 8 Jan 2023 20:40:32 +0100 [thread overview]
Message-ID: <20230108194034.1444764-9-agruenba@redhat.com> (raw)
In-Reply-To: <20230108194034.1444764-1-agruenba@redhat.com>
Eliminate the ->iomap_valid() handler by switching to a ->get_folio()
handler and validating the mapping there.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/iomap/buffered-io.c | 26 +++++---------------------
fs/xfs/xfs_iomap.c | 37 ++++++++++++++++++++++++++-----------
include/linux/iomap.h | 23 ++++++-----------------
3 files changed, 37 insertions(+), 49 deletions(-)
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 006ddf933948..72dfbc3cb086 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -638,10 +638,9 @@ static int iomap_write_begin_inline(const struct iomap_iter *iter,
static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
size_t len, struct folio **foliop)
{
- const struct iomap_page_ops *page_ops = iter->iomap.page_ops;
const struct iomap *srcmap = iomap_iter_srcmap(iter);
struct folio *folio;
- int status = 0;
+ int status;
BUG_ON(pos + len > iter->iomap.offset + iter->iomap.length);
if (srcmap != &iter->iomap)
@@ -654,27 +653,12 @@ static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
folio = __iomap_get_folio(iter, pos, len);
- if (IS_ERR(folio))
- return PTR_ERR(folio);
-
- /*
- * Now we have a locked folio, before we do anything with it we need to
- * check that the iomap we have cached is not stale. The inode extent
- * mapping can change due to concurrent IO in flight (e.g.
- * IOMAP_UNWRITTEN state can change and memory reclaim could have
- * reclaimed a previously partially written page at this index after IO
- * completion before this write reaches this file offset) and hence we
- * could do the wrong thing here (zero a page range incorrectly or fail
- * to zero) and corrupt data.
- */
- if (page_ops && page_ops->iomap_valid) {
- bool iomap_valid = page_ops->iomap_valid(iter->inode,
- &iter->iomap);
- if (!iomap_valid) {
+ if (IS_ERR(folio)) {
+ if (folio == ERR_PTR(-ESTALE)) {
iter->iomap.flags |= IOMAP_F_STALE;
- status = 0;
- goto out_unlock;
+ return 0;
}
+ return PTR_ERR(folio);
}
if (pos + len > folio_pos(folio) + folio_size(folio))
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 669c1bc5c3a7..d0bf99539180 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -62,29 +62,44 @@ xfs_iomap_inode_sequence(
return cookie | READ_ONCE(ip->i_df.if_seq);
}
-/*
- * Check that the iomap passed to us is still valid for the given offset and
- * length.
- */
-static bool
-xfs_iomap_valid(
- struct inode *inode,
- const struct iomap *iomap)
+static struct folio *
+xfs_get_folio(
+ struct iomap_iter *iter,
+ loff_t pos,
+ unsigned len)
{
+ struct inode *inode = iter->inode;
+ struct iomap *iomap = &iter->iomap;
struct xfs_inode *ip = XFS_I(inode);
+ struct folio *folio;
+ folio = iomap_get_folio(iter, pos);
+ if (IS_ERR(folio))
+ return folio;
+
+ /*
+ * Now that we have a locked folio, we need to check that the iomap we
+ * have cached is not stale. The inode extent mapping can change due to
+ * concurrent IO in flight (e.g., IOMAP_UNWRITTEN state can change and
+ * memory reclaim could have reclaimed a previously partially written
+ * page at this index after IO completion before this write reaches
+ * this file offset) and hence we could do the wrong thing here (zero a
+ * page range incorrectly or fail to zero) and corrupt data.
+ */
if (iomap->validity_cookie !=
xfs_iomap_inode_sequence(ip, iomap->flags)) {
trace_xfs_iomap_invalid(ip, iomap);
- return false;
+ folio_unlock(folio);
+ folio_put(folio);
+ return ERR_PTR(-ESTALE);
}
XFS_ERRORTAG_DELAY(ip->i_mount, XFS_ERRTAG_WRITE_DELAY_MS);
- return true;
+ return folio;
}
const struct iomap_page_ops xfs_iomap_page_ops = {
- .iomap_valid = xfs_iomap_valid,
+ .get_folio = xfs_get_folio,
};
int
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index da226032aedc..0ae2cddbedd6 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -134,29 +134,18 @@ static inline bool iomap_inline_data_valid(const struct iomap *iomap)
* When get_folio succeeds, put_folio will always be called to do any
* cleanup work necessary. put_folio is responsible for unlocking and putting
* @folio.
+ *
+ * When an iomap is created, the filesystem can store internal state (e.g., a
+ * sequence number) in iomap->validity_cookie. The get_folio handler can use
+ * this validity cookie to detect when the iomap needs to be refreshed because
+ * it is no longer up to date. In that case, the function should return
+ * ERR_PTR(-ESTALE) to retry the operation with a fresh mapping.
*/
struct iomap_page_ops {
struct folio *(*get_folio)(struct iomap_iter *iter, loff_t pos,
unsigned len);
void (*put_folio)(struct inode *inode, loff_t pos, unsigned copied,
struct folio *folio);
-
- /*
- * Check that the cached iomap still maps correctly to the filesystem's
- * internal extent map. FS internal extent maps can change while iomap
- * is iterating a cached iomap, so this hook allows iomap to detect that
- * the iomap needs to be refreshed during a long running write
- * operation.
- *
- * The filesystem can store internal state (e.g. a sequence number) in
- * iomap->validity_cookie when the iomap is first mapped to be able to
- * detect changes between mapping time and whenever .iomap_valid() is
- * called.
- *
- * This is called with the folio over the specified file position held
- * locked by the iomap code.
- */
- bool (*iomap_valid)(struct inode *inode, const struct iomap *iomap);
};
/*
--
2.38.1
next prev parent reply other threads:[~2023-01-08 19:40 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-08 19:40 [Cluster-devel] [RFC v6 00/10] Turn iomap_page_ops into iomap_folio_ops Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 01/10] iomap: Add __iomap_put_folio helper Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 02/10] iomap/gfs2: Unlock and put folio in page_done handler Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 03/10] iomap: Rename page_done handler to put_folio Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 04/10] iomap: Add iomap_get_folio helper Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-08 21:33 ` [Cluster-devel] " Dave Chinner
2023-01-08 21:33 ` Dave Chinner
2023-01-09 12:46 ` [Cluster-devel] " Andreas Gruenbacher
2023-01-09 12:46 ` Andreas Gruenbacher
2023-01-10 8:46 ` [Cluster-devel] " Christoph Hellwig
2023-01-10 8:46 ` Christoph Hellwig
2023-01-10 9:07 ` [Cluster-devel] " Andreas Grünbacher
2023-01-10 9:07 ` Andreas Grünbacher
2023-01-10 13:34 ` [Cluster-devel] " Matthew Wilcox
2023-01-10 13:34 ` Matthew Wilcox
2023-01-10 15:24 ` [Cluster-devel] " Christoph Hellwig
2023-01-10 15:24 ` Christoph Hellwig
2023-01-11 19:36 ` [Cluster-devel] " Matthew Wilcox
2023-01-11 19:36 ` Matthew Wilcox
2023-01-11 20:52 ` [Cluster-devel] " Dave Chinner
2023-01-11 20:52 ` Dave Chinner
2023-01-12 8:41 ` [Cluster-devel] " Christoph Hellwig
2023-01-12 8:41 ` Christoph Hellwig
2023-01-15 17:01 ` [Cluster-devel] " Darrick J. Wong
2023-01-15 17:01 ` Darrick J. Wong
2023-01-15 17:06 ` [Cluster-devel] " Darrick J. Wong
2023-01-15 17:06 ` Darrick J. Wong
2023-01-16 5:46 ` [Cluster-devel] " Matthew Wilcox
2023-01-16 5:46 ` Matthew Wilcox
2023-01-16 7:34 ` [Cluster-devel] " Christoph Hellwig
2023-01-16 7:34 ` Christoph Hellwig
2023-01-16 13:18 ` [Cluster-devel] " Matthew Wilcox
2023-01-16 13:18 ` Matthew Wilcox
2023-01-16 16:02 ` [Cluster-devel] " Christoph Hellwig
2023-01-16 16:02 ` Christoph Hellwig
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 05/10] iomap/gfs2: Get page in page_prepare handler Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-31 19:37 ` [Cluster-devel] " Matthew Wilcox
2023-01-31 19:37 ` Matthew Wilcox
2023-01-31 21:33 ` [Cluster-devel] " Andreas Gruenbacher
2023-01-31 21:33 ` Andreas Gruenbacher
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 06/10] iomap: Add __iomap_get_folio helper Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-10 8:48 ` [Cluster-devel] " Christoph Hellwig
2023-01-10 8:48 ` Christoph Hellwig
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 07/10] iomap: Rename page_prepare handler to get_folio Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher [this message]
2023-01-08 19:40 ` [RFC v6 08/10] iomap/xfs: Eliminate the iomap_valid handler Andreas Gruenbacher
2023-01-08 21:59 ` [Cluster-devel] " Dave Chinner
2023-01-08 21:59 ` Dave Chinner
2023-01-09 18:45 ` [Cluster-devel] " Andreas Gruenbacher
2023-01-09 18:45 ` Andreas Gruenbacher
2023-01-09 22:54 ` [Cluster-devel] " Dave Chinner
2023-01-09 22:54 ` Dave Chinner
2023-01-10 1:09 ` [Cluster-devel] " Andreas Grünbacher
2023-01-10 1:09 ` Andreas Grünbacher
2023-01-15 17:29 ` [Cluster-devel] " Darrick J. Wong
2023-01-15 17:29 ` Darrick J. Wong
2023-01-18 7:21 ` [Cluster-devel] " Christoph Hellwig
2023-01-18 7:21 ` Christoph Hellwig
2023-01-18 9:11 ` [Cluster-devel] " Damien Le Moal
2023-01-18 9:11 ` Damien Le Moal
2023-01-18 19:04 ` [Cluster-devel] " Darrick J. Wong
2023-01-18 19:04 ` Darrick J. Wong
2023-01-18 19:57 ` [Cluster-devel] " Andreas Grünbacher
2023-01-18 19:57 ` Andreas Grünbacher
2023-01-18 21:42 ` [Cluster-devel] " Dave Chinner
2023-01-18 21:42 ` Dave Chinner
2023-01-10 8:51 ` [Cluster-devel] " Christoph Hellwig
2023-01-10 8:51 ` Christoph Hellwig
2023-01-10 8:52 ` [Cluster-devel] " Christoph Hellwig
2023-01-10 8:52 ` Christoph Hellwig
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 09/10] iomap: Rename page_ops to folio_ops Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
2023-01-08 19:40 ` [Cluster-devel] [RFC v6 10/10] xfs: Make xfs_iomap_folio_ops static Andreas Gruenbacher
2023-01-08 19:40 ` Andreas Gruenbacher
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=20230108194034.1444764-9-agruenba@redhat.com \
--to=agruenba@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.