diff mbox series

[RFC,01/31] iomap: Check if blocksize == PAGE_SIZE in to_iomap_page()

Message ID 79781ca99470475ff33382e67571eeb914edac63.1623567940.git.rgoldwyn@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs buffered iomap support | expand

Commit Message

Goldwyn Rodrigues June 13, 2021, 1:39 p.m. UTC
From: Goldwyn Rodrigues <rgoldwyn@suse.com>

btrfs requires page->private set to get a callback to releasepage(). So,
for normal circumstances of blocksize==PAGE_SIZE, btrfs will have
page->private set to 1. In order to avoid a crash, check for the
blocksize==PAGE_SIZE in to_iomap_page().
---
 fs/iomap/buffered-io.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

Comments

Nikolay Borisov June 15, 2021, 2:17 p.m. UTC | #1
On 13.06.21 г. 16:39, Goldwyn Rodrigues wrote:
> From: Goldwyn Rodrigues <rgoldwyn@suse.com>
> 
> btrfs requires page->private set to get a callback to releasepage(). 

nit: This is somewhat terse of an explanation and someone not familiar
with btrfs might wonder what's going on. In fact, btrfs uses the
PagePrivate flag to indicate that the page has undergone CoW and has
ordered extents created. And this is in fact problematic because iomap
assume page_private is not in use by the underlying fs.

So,
> for normal circumstances of blocksize==PAGE_SIZE, btrfs will have
> page->private set to 1. In order to avoid a crash, check for the
> blocksize==PAGE_SIZE in to_iomap_page().
> ---
>  fs/iomap/buffered-io.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 9023717c5188..d30683734d01 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -41,9 +41,11 @@ static inline struct iomap_page *to_iomap_page(struct page *page)
>  	 */
>  	VM_BUG_ON_PGFLAGS(PageTail(page), page);
>  
> -	if (page_has_private(page))
> -		return (struct iomap_page *)page_private(page);
> -	return NULL;
> +	if (i_blocksize(page->mapping->host) == PAGE_SIZE)
> +		return NULL;
> +	if (!page_has_private(page))
> +		return NULL;
> +	return (struct iomap_page *)page_private(page);
>  }
>  
>  static struct bio_set iomap_ioend_bioset;
> @@ -163,7 +165,7 @@ iomap_set_range_uptodate(struct page *page, unsigned off, unsigned len)
>  	if (PageError(page))
>  		return;
>  
> -	if (page_has_private(page))
> +	if (i_blocksize(page->mapping->host) != PAGE_SIZE)
>  		iomap_iop_set_range_uptodate(page, off, len);
>  	else
>  		SetPageUptodate(page);
>
diff mbox series

Patch

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 9023717c5188..d30683734d01 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -41,9 +41,11 @@  static inline struct iomap_page *to_iomap_page(struct page *page)
 	 */
 	VM_BUG_ON_PGFLAGS(PageTail(page), page);
 
-	if (page_has_private(page))
-		return (struct iomap_page *)page_private(page);
-	return NULL;
+	if (i_blocksize(page->mapping->host) == PAGE_SIZE)
+		return NULL;
+	if (!page_has_private(page))
+		return NULL;
+	return (struct iomap_page *)page_private(page);
 }
 
 static struct bio_set iomap_ioend_bioset;
@@ -163,7 +165,7 @@  iomap_set_range_uptodate(struct page *page, unsigned off, unsigned len)
 	if (PageError(page))
 		return;
 
-	if (page_has_private(page))
+	if (i_blocksize(page->mapping->host) != PAGE_SIZE)
 		iomap_iop_set_range_uptodate(page, off, len);
 	else
 		SetPageUptodate(page);