All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Gruenbacher <agruenba@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [RFC v6 05/10] iomap/gfs2: Get page in page_prepare handler
Date: Sun,  8 Jan 2023 20:40:29 +0100	[thread overview]
Message-ID: <20230108194034.1444764-6-agruenba@redhat.com> (raw)
In-Reply-To: <20230108194034.1444764-1-agruenba@redhat.com>

Change the iomap ->page_prepare() handler to get and return a locked
folio instead of doing that in iomap_write_begin().  This allows to
recover from out-of-memory situations in ->page_prepare(), which
eliminates the corresponding error handling code in iomap_write_begin().
The ->put_folio() handler now also isn't called with NULL as the folio
value anymore.

Filesystems are expected to use the iomap_get_folio() helper for getting
locked folios in their ->page_prepare() handlers.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 fs/gfs2/bmap.c         | 21 +++++++++++++--------
 fs/iomap/buffered-io.c | 17 ++++++-----------
 include/linux/iomap.h  |  9 +++++----
 3 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 0c041459677b..41349e09558b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -956,15 +956,25 @@ static int __gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
 	goto out;
 }
 
-static int gfs2_iomap_page_prepare(struct inode *inode, loff_t pos,
-				   unsigned len)
+static struct folio *
+gfs2_iomap_page_prepare(struct iomap_iter *iter, loff_t pos, unsigned len)
 {
+	struct inode *inode = iter->inode;
 	unsigned int blockmask = i_blocksize(inode) - 1;
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	unsigned int blocks;
+	struct folio *folio;
+	int status;
 
 	blocks = ((pos & blockmask) + len + blockmask) >> inode->i_blkbits;
-	return gfs2_trans_begin(sdp, RES_DINODE + blocks, 0);
+	status = gfs2_trans_begin(sdp, RES_DINODE + blocks, 0);
+	if (status)
+		return ERR_PTR(status);
+
+	folio = iomap_get_folio(iter, pos);
+	if (IS_ERR(folio))
+		gfs2_trans_end(sdp);
+	return folio;
 }
 
 static void gfs2_iomap_put_folio(struct inode *inode, loff_t pos,
@@ -974,11 +984,6 @@ static void gfs2_iomap_put_folio(struct inode *inode, loff_t pos,
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 
-	if (!folio) {
-		gfs2_trans_end(sdp);
-		return;
-	}
-
 	if (!gfs2_is_stuffed(ip))
 		gfs2_page_add_databufs(ip, &folio->page, offset_in_page(pos),
 				       copied);
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index de4a8e5f721a..418519dea2ce 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -609,7 +609,7 @@ static void __iomap_put_folio(struct iomap_iter *iter, loff_t pos, size_t ret,
 
 	if (page_ops && page_ops->put_folio) {
 		page_ops->put_folio(iter->inode, pos, ret, folio);
-	} else if (folio) {
+	} else {
 		folio_unlock(folio);
 		folio_put(folio);
 	}
@@ -642,17 +642,12 @@ static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
 	if (!mapping_large_folio_support(iter->inode->i_mapping))
 		len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
 
-	if (page_ops && page_ops->page_prepare) {
-		status = page_ops->page_prepare(iter->inode, pos, len);
-		if (status)
-			return status;
-	}
-
-	folio = iomap_get_folio(iter, pos);
-	if (IS_ERR(folio)) {
-		__iomap_put_folio(iter, pos, 0, NULL);
+	if (page_ops && page_ops->page_prepare)
+		folio = page_ops->page_prepare(iter, pos, len);
+	else
+		folio = iomap_get_folio(iter, pos);
+	if (IS_ERR(folio))
 		return PTR_ERR(folio);
-	}
 
 	/*
 	 * Now we have a locked folio, before we do anything with it we need to
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 188d14e786a4..d50501781856 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -13,6 +13,7 @@
 struct address_space;
 struct fiemap_extent_info;
 struct inode;
+struct iomap_iter;
 struct iomap_dio;
 struct iomap_writepage_ctx;
 struct iov_iter;
@@ -131,12 +132,12 @@ static inline bool iomap_inline_data_valid(const struct iomap *iomap)
  * associated with them.
  *
  * When page_prepare succeeds, put_folio will always be called to do any
- * cleanup work necessary.  In that put_folio call, @folio will be NULL if the
- * associated folio could not be obtained.  When folio is not NULL, put_folio
- * is responsible for unlocking and putting the folio.
+ * cleanup work necessary.  put_folio is responsible for unlocking and putting
+ * @folio.
  */
 struct iomap_page_ops {
-	int (*page_prepare)(struct inode *inode, loff_t pos, unsigned len);
+	struct folio *(*page_prepare)(struct iomap_iter *iter, loff_t pos,
+			unsigned len);
 	void (*put_folio)(struct inode *inode, loff_t pos, unsigned copied,
 			struct folio *folio);
 
-- 
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,
	Christoph Hellwig <hch@lst.de>
Subject: [RFC v6 05/10] iomap/gfs2: Get page in page_prepare handler
Date: Sun,  8 Jan 2023 20:40:29 +0100	[thread overview]
Message-ID: <20230108194034.1444764-6-agruenba@redhat.com> (raw)
In-Reply-To: <20230108194034.1444764-1-agruenba@redhat.com>

Change the iomap ->page_prepare() handler to get and return a locked
folio instead of doing that in iomap_write_begin().  This allows to
recover from out-of-memory situations in ->page_prepare(), which
eliminates the corresponding error handling code in iomap_write_begin().
The ->put_folio() handler now also isn't called with NULL as the folio
value anymore.

Filesystems are expected to use the iomap_get_folio() helper for getting
locked folios in their ->page_prepare() handlers.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 fs/gfs2/bmap.c         | 21 +++++++++++++--------
 fs/iomap/buffered-io.c | 17 ++++++-----------
 include/linux/iomap.h  |  9 +++++----
 3 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 0c041459677b..41349e09558b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -956,15 +956,25 @@ static int __gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
 	goto out;
 }
 
-static int gfs2_iomap_page_prepare(struct inode *inode, loff_t pos,
-				   unsigned len)
+static struct folio *
+gfs2_iomap_page_prepare(struct iomap_iter *iter, loff_t pos, unsigned len)
 {
+	struct inode *inode = iter->inode;
 	unsigned int blockmask = i_blocksize(inode) - 1;
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	unsigned int blocks;
+	struct folio *folio;
+	int status;
 
 	blocks = ((pos & blockmask) + len + blockmask) >> inode->i_blkbits;
-	return gfs2_trans_begin(sdp, RES_DINODE + blocks, 0);
+	status = gfs2_trans_begin(sdp, RES_DINODE + blocks, 0);
+	if (status)
+		return ERR_PTR(status);
+
+	folio = iomap_get_folio(iter, pos);
+	if (IS_ERR(folio))
+		gfs2_trans_end(sdp);
+	return folio;
 }
 
 static void gfs2_iomap_put_folio(struct inode *inode, loff_t pos,
@@ -974,11 +984,6 @@ static void gfs2_iomap_put_folio(struct inode *inode, loff_t pos,
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 
-	if (!folio) {
-		gfs2_trans_end(sdp);
-		return;
-	}
-
 	if (!gfs2_is_stuffed(ip))
 		gfs2_page_add_databufs(ip, &folio->page, offset_in_page(pos),
 				       copied);
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index de4a8e5f721a..418519dea2ce 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -609,7 +609,7 @@ static void __iomap_put_folio(struct iomap_iter *iter, loff_t pos, size_t ret,
 
 	if (page_ops && page_ops->put_folio) {
 		page_ops->put_folio(iter->inode, pos, ret, folio);
-	} else if (folio) {
+	} else {
 		folio_unlock(folio);
 		folio_put(folio);
 	}
@@ -642,17 +642,12 @@ static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
 	if (!mapping_large_folio_support(iter->inode->i_mapping))
 		len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
 
-	if (page_ops && page_ops->page_prepare) {
-		status = page_ops->page_prepare(iter->inode, pos, len);
-		if (status)
-			return status;
-	}
-
-	folio = iomap_get_folio(iter, pos);
-	if (IS_ERR(folio)) {
-		__iomap_put_folio(iter, pos, 0, NULL);
+	if (page_ops && page_ops->page_prepare)
+		folio = page_ops->page_prepare(iter, pos, len);
+	else
+		folio = iomap_get_folio(iter, pos);
+	if (IS_ERR(folio))
 		return PTR_ERR(folio);
-	}
 
 	/*
 	 * Now we have a locked folio, before we do anything with it we need to
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 188d14e786a4..d50501781856 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -13,6 +13,7 @@
 struct address_space;
 struct fiemap_extent_info;
 struct inode;
+struct iomap_iter;
 struct iomap_dio;
 struct iomap_writepage_ctx;
 struct iov_iter;
@@ -131,12 +132,12 @@ static inline bool iomap_inline_data_valid(const struct iomap *iomap)
  * associated with them.
  *
  * When page_prepare succeeds, put_folio will always be called to do any
- * cleanup work necessary.  In that put_folio call, @folio will be NULL if the
- * associated folio could not be obtained.  When folio is not NULL, put_folio
- * is responsible for unlocking and putting the folio.
+ * cleanup work necessary.  put_folio is responsible for unlocking and putting
+ * @folio.
  */
 struct iomap_page_ops {
-	int (*page_prepare)(struct inode *inode, loff_t pos, unsigned len);
+	struct folio *(*page_prepare)(struct iomap_iter *iter, loff_t pos,
+			unsigned len);
 	void (*put_folio)(struct inode *inode, loff_t pos, unsigned copied,
 			struct folio *folio);
 
-- 
2.38.1


  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 ` Andreas Gruenbacher [this message]
2023-01-08 19:40   ` [RFC v6 05/10] iomap/gfs2: Get page in page_prepare handler 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 ` [Cluster-devel] [RFC v6 08/10] iomap/xfs: Eliminate the iomap_valid handler Andreas Gruenbacher
2023-01-08 19:40   ` 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-6-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.