* [PATCH v3 00/14] gfs2/buffer folio changes for 6.5
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
This kind of started off as a gfs2 patch series, then became entwined
with buffer heads once I realised that gfs2 was the only remaining
caller of __block_write_full_page(). For those not in the gfs2 world,
the big point of this series is that block_write_full_page() should now
handle large folios correctly.
Andrew, if you want, I'll drop it into the pagecache tree, or you
can just take it.
v3:
- Fix a patch title
- Fix some checks against i_size to be >= instead of >
- Call folio_mark_dirty() instead of folio_set_dirty()
Matthew Wilcox (Oracle) (14):
gfs2: Use a folio inside gfs2_jdata_writepage()
gfs2: Pass a folio to __gfs2_jdata_write_folio()
gfs2: Convert gfs2_write_jdata_page() to gfs2_write_jdata_folio()
buffer: Convert __block_write_full_page() to
__block_write_full_folio()
gfs2: Support ludicrously large folios in gfs2_trans_add_databufs()
buffer: Make block_write_full_page() handle large folios correctly
buffer: Convert block_page_mkwrite() to use a folio
buffer: Convert __block_commit_write() to take a folio
buffer: Convert page_zero_new_buffers() to folio_zero_new_buffers()
buffer: Convert grow_dev_page() to use a folio
buffer: Convert init_page_buffers() to folio_init_buffers()
buffer: Convert link_dev_buffers to take a folio
buffer: Use a folio in __find_get_block_slow()
buffer: Convert block_truncate_page() to use a folio
fs/buffer.c | 257 ++++++++++++++++++------------------
fs/ext4/inode.c | 4 +-
fs/gfs2/aops.c | 69 +++++-----
fs/gfs2/aops.h | 2 +-
fs/ntfs/aops.c | 2 +-
fs/reiserfs/inode.c | 9 +-
include/linux/buffer_head.h | 4 +-
7 files changed, 172 insertions(+), 175 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 00/14] gfs2/buffer folio changes for 6.5
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
This kind of started off as a gfs2 patch series, then became entwined
with buffer heads once I realised that gfs2 was the only remaining
caller of __block_write_full_page(). For those not in the gfs2 world,
the big point of this series is that block_write_full_page() should now
handle large folios correctly.
Andrew, if you want, I'll drop it into the pagecache tree, or you
can just take it.
v3:
- Fix a patch title
- Fix some checks against i_size to be >= instead of >
- Call folio_mark_dirty() instead of folio_set_dirty()
Matthew Wilcox (Oracle) (14):
gfs2: Use a folio inside gfs2_jdata_writepage()
gfs2: Pass a folio to __gfs2_jdata_write_folio()
gfs2: Convert gfs2_write_jdata_page() to gfs2_write_jdata_folio()
buffer: Convert __block_write_full_page() to
__block_write_full_folio()
gfs2: Support ludicrously large folios in gfs2_trans_add_databufs()
buffer: Make block_write_full_page() handle large folios correctly
buffer: Convert block_page_mkwrite() to use a folio
buffer: Convert __block_commit_write() to take a folio
buffer: Convert page_zero_new_buffers() to folio_zero_new_buffers()
buffer: Convert grow_dev_page() to use a folio
buffer: Convert init_page_buffers() to folio_init_buffers()
buffer: Convert link_dev_buffers to take a folio
buffer: Use a folio in __find_get_block_slow()
buffer: Convert block_truncate_page() to use a folio
fs/buffer.c | 257 ++++++++++++++++++------------------
fs/ext4/inode.c | 4 +-
fs/gfs2/aops.c | 69 +++++-----
fs/gfs2/aops.h | 2 +-
fs/ntfs/aops.c | 2 +-
fs/reiserfs/inode.c | 9 +-
include/linux/buffer_head.h | 4 +-
7 files changed, 172 insertions(+), 175 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 01/14] gfs2: Use a folio inside gfs2_jdata_writepage()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher, Bob Peterson
Replace a few implicit calls to compound_head() with one explicit one.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index a5f4be6b9213..0518861df783 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -150,20 +150,21 @@ static int __gfs2_jdata_writepage(struct page *page, struct writeback_control *w
static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc)
{
+ struct folio *folio = page_folio(page);
struct inode *inode = page->mapping->host;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
goto out;
- if (PageChecked(page) || current->journal_info)
+ if (folio_test_checked(folio) || current->journal_info)
goto out_ignore;
- return __gfs2_jdata_writepage(page, wbc);
+ return __gfs2_jdata_writepage(&folio->page, wbc);
out_ignore:
- redirty_page_for_writepage(wbc, page);
+ folio_redirty_for_writepage(wbc, folio);
out:
- unlock_page(page);
+ folio_unlock(folio);
return 0;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 01/14] gfs2: Use a folio inside gfs2_jdata_writepage()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Replace a few implicit calls to compound_head() with one explicit one.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index a5f4be6b9213..0518861df783 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -150,20 +150,21 @@ static int __gfs2_jdata_writepage(struct page *page, struct writeback_control *w
static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc)
{
+ struct folio *folio = page_folio(page);
struct inode *inode = page->mapping->host;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
goto out;
- if (PageChecked(page) || current->journal_info)
+ if (folio_test_checked(folio) || current->journal_info)
goto out_ignore;
- return __gfs2_jdata_writepage(page, wbc);
+ return __gfs2_jdata_writepage(&folio->page, wbc);
out_ignore:
- redirty_page_for_writepage(wbc, page);
+ folio_redirty_for_writepage(wbc, folio);
out:
- unlock_page(page);
+ folio_unlock(folio);
return 0;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 02/14] gfs2: Pass a folio to __gfs2_jdata_write_folio()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher, Bob Peterson
Remove a couple of folio->page conversions in the callers, and two
calls to compound_head() in the function itself. Rename it from
__gfs2_jdata_writepage() to __gfs2_jdata_write_folio().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 0518861df783..749135252d52 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -113,30 +113,31 @@ static int gfs2_write_jdata_page(struct page *page,
}
/**
- * __gfs2_jdata_writepage - The core of jdata writepage
- * @page: The page to write
+ * __gfs2_jdata_write_folio - The core of jdata writepage
+ * @folio: The folio to write
* @wbc: The writeback control
*
* This is shared between writepage and writepages and implements the
* core of the writepage operation. If a transaction is required then
- * PageChecked will have been set and the transaction will have
+ * the checked flag will have been set and the transaction will have
* already been started before this is called.
*/
-
-static int __gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc)
+static int __gfs2_jdata_write_folio(struct folio *folio,
+ struct writeback_control *wbc)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = folio->mapping->host;
struct gfs2_inode *ip = GFS2_I(inode);
- if (PageChecked(page)) {
- ClearPageChecked(page);
- if (!page_has_buffers(page)) {
- create_empty_buffers(page, inode->i_sb->s_blocksize,
- BIT(BH_Dirty)|BIT(BH_Uptodate));
+ if (folio_test_checked(folio)) {
+ folio_clear_checked(folio);
+ if (!folio_buffers(folio)) {
+ folio_create_empty_buffers(folio,
+ inode->i_sb->s_blocksize,
+ BIT(BH_Dirty)|BIT(BH_Uptodate));
}
- gfs2_trans_add_databufs(ip, page_folio(page), 0, PAGE_SIZE);
+ gfs2_trans_add_databufs(ip, folio, 0, folio_size(folio));
}
- return gfs2_write_jdata_page(page, wbc);
+ return gfs2_write_jdata_page(&folio->page, wbc);
}
/**
@@ -159,7 +160,7 @@ static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc
goto out;
if (folio_test_checked(folio) || current->journal_info)
goto out_ignore;
- return __gfs2_jdata_writepage(&folio->page, wbc);
+ return __gfs2_jdata_write_folio(folio, wbc);
out_ignore:
folio_redirty_for_writepage(wbc, folio);
@@ -256,7 +257,7 @@ static int gfs2_write_jdata_batch(struct address_space *mapping,
trace_wbc_writepage(wbc, inode_to_bdi(inode));
- ret = __gfs2_jdata_writepage(&folio->page, wbc);
+ ret = __gfs2_jdata_write_folio(folio, wbc);
if (unlikely(ret)) {
if (ret == AOP_WRITEPAGE_ACTIVATE) {
folio_unlock(folio);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 02/14] gfs2: Pass a folio to __gfs2_jdata_write_folio()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Remove a couple of folio->page conversions in the callers, and two
calls to compound_head() in the function itself. Rename it from
__gfs2_jdata_writepage() to __gfs2_jdata_write_folio().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 0518861df783..749135252d52 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -113,30 +113,31 @@ static int gfs2_write_jdata_page(struct page *page,
}
/**
- * __gfs2_jdata_writepage - The core of jdata writepage
- * @page: The page to write
+ * __gfs2_jdata_write_folio - The core of jdata writepage
+ * @folio: The folio to write
* @wbc: The writeback control
*
* This is shared between writepage and writepages and implements the
* core of the writepage operation. If a transaction is required then
- * PageChecked will have been set and the transaction will have
+ * the checked flag will have been set and the transaction will have
* already been started before this is called.
*/
-
-static int __gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc)
+static int __gfs2_jdata_write_folio(struct folio *folio,
+ struct writeback_control *wbc)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = folio->mapping->host;
struct gfs2_inode *ip = GFS2_I(inode);
- if (PageChecked(page)) {
- ClearPageChecked(page);
- if (!page_has_buffers(page)) {
- create_empty_buffers(page, inode->i_sb->s_blocksize,
- BIT(BH_Dirty)|BIT(BH_Uptodate));
+ if (folio_test_checked(folio)) {
+ folio_clear_checked(folio);
+ if (!folio_buffers(folio)) {
+ folio_create_empty_buffers(folio,
+ inode->i_sb->s_blocksize,
+ BIT(BH_Dirty)|BIT(BH_Uptodate));
}
- gfs2_trans_add_databufs(ip, page_folio(page), 0, PAGE_SIZE);
+ gfs2_trans_add_databufs(ip, folio, 0, folio_size(folio));
}
- return gfs2_write_jdata_page(page, wbc);
+ return gfs2_write_jdata_page(&folio->page, wbc);
}
/**
@@ -159,7 +160,7 @@ static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc
goto out;
if (folio_test_checked(folio) || current->journal_info)
goto out_ignore;
- return __gfs2_jdata_writepage(&folio->page, wbc);
+ return __gfs2_jdata_write_folio(folio, wbc);
out_ignore:
folio_redirty_for_writepage(wbc, folio);
@@ -256,7 +257,7 @@ static int gfs2_write_jdata_batch(struct address_space *mapping,
trace_wbc_writepage(wbc, inode_to_bdi(inode));
- ret = __gfs2_jdata_writepage(&folio->page, wbc);
+ ret = __gfs2_jdata_write_folio(folio, wbc);
if (unlikely(ret)) {
if (ret == AOP_WRITEPAGE_ACTIVATE) {
folio_unlock(folio);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 03/14] gfs2: Convert gfs2_write_jdata_page() to gfs2_write_jdata_folio()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher, Bob Peterson
Add support for large folios and remove some accesses to page->mapping
and page->index.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 749135252d52..ec5b5c1ea634 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -82,33 +82,33 @@ static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock,
}
/**
- * gfs2_write_jdata_page - gfs2 jdata-specific version of block_write_full_page
- * @page: The page to write
+ * gfs2_write_jdata_folio - gfs2 jdata-specific version of block_write_full_page
+ * @folio: The folio to write
* @wbc: The writeback control
*
* This is the same as calling block_write_full_page, but it also
* writes pages outside of i_size
*/
-static int gfs2_write_jdata_page(struct page *page,
+static int gfs2_write_jdata_folio(struct folio *folio,
struct writeback_control *wbc)
{
- struct inode * const inode = page->mapping->host;
+ struct inode * const inode = folio->mapping->host;
loff_t i_size = i_size_read(inode);
- const pgoff_t end_index = i_size >> PAGE_SHIFT;
- unsigned offset;
/*
- * The page straddles i_size. It must be zeroed out on each and every
+ * The folio straddles i_size. It must be zeroed out on each and every
* writepage invocation because it may be mmapped. "A file is mapped
* in multiples of the page size. For a file that is not a multiple of
- * the page size, the remaining memory is zeroed when mapped, and
+ * the page size, the remaining memory is zeroed when mapped, and
* writes to that region are not written out to the file."
*/
- offset = i_size & (PAGE_SIZE - 1);
- if (page->index == end_index && offset)
- zero_user_segment(page, offset, PAGE_SIZE);
+ if (folio_pos(folio) < i_size &&
+ i_size < folio_pos(folio) + folio_size(folio))
+ folio_zero_segment(folio, offset_in_folio(folio, i_size),
+ folio_size(folio));
- return __block_write_full_page(inode, page, gfs2_get_block_noalloc, wbc,
+ return __block_write_full_page(inode, &folio->page,
+ gfs2_get_block_noalloc, wbc,
end_buffer_async_write);
}
@@ -137,7 +137,7 @@ static int __gfs2_jdata_write_folio(struct folio *folio,
}
gfs2_trans_add_databufs(ip, folio, 0, folio_size(folio));
}
- return gfs2_write_jdata_page(&folio->page, wbc);
+ return gfs2_write_jdata_folio(folio, wbc);
}
/**
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 03/14] gfs2: Convert gfs2_write_jdata_page() to gfs2_write_jdata_folio()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Add support for large folios and remove some accesses to page->mapping
and page->index.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 749135252d52..ec5b5c1ea634 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -82,33 +82,33 @@ static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock,
}
/**
- * gfs2_write_jdata_page - gfs2 jdata-specific version of block_write_full_page
- * @page: The page to write
+ * gfs2_write_jdata_folio - gfs2 jdata-specific version of block_write_full_page
+ * @folio: The folio to write
* @wbc: The writeback control
*
* This is the same as calling block_write_full_page, but it also
* writes pages outside of i_size
*/
-static int gfs2_write_jdata_page(struct page *page,
+static int gfs2_write_jdata_folio(struct folio *folio,
struct writeback_control *wbc)
{
- struct inode * const inode = page->mapping->host;
+ struct inode * const inode = folio->mapping->host;
loff_t i_size = i_size_read(inode);
- const pgoff_t end_index = i_size >> PAGE_SHIFT;
- unsigned offset;
/*
- * The page straddles i_size. It must be zeroed out on each and every
+ * The folio straddles i_size. It must be zeroed out on each and every
* writepage invocation because it may be mmapped. "A file is mapped
* in multiples of the page size. For a file that is not a multiple of
- * the page size, the remaining memory is zeroed when mapped, and
+ * the page size, the remaining memory is zeroed when mapped, and
* writes to that region are not written out to the file."
*/
- offset = i_size & (PAGE_SIZE - 1);
- if (page->index == end_index && offset)
- zero_user_segment(page, offset, PAGE_SIZE);
+ if (folio_pos(folio) < i_size &&
+ i_size < folio_pos(folio) + folio_size(folio))
+ folio_zero_segment(folio, offset_in_folio(folio, i_size),
+ folio_size(folio));
- return __block_write_full_page(inode, page, gfs2_get_block_noalloc, wbc,
+ return __block_write_full_page(inode, &folio->page,
+ gfs2_get_block_noalloc, wbc,
end_buffer_async_write);
}
@@ -137,7 +137,7 @@ static int __gfs2_jdata_write_folio(struct folio *folio,
}
gfs2_trans_add_databufs(ip, folio, 0, folio_size(folio));
}
- return gfs2_write_jdata_page(&folio->page, wbc);
+ return gfs2_write_jdata_folio(folio, wbc);
}
/**
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 04/14] buffer: Convert __block_write_full_page() to __block_write_full_folio()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher, Bob Peterson
Remove nine hidden calls to compound_head() by using a folio instead
of a page.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/buffer.c | 53 +++++++++++++++++++------------------
fs/gfs2/aops.c | 5 ++--
fs/ntfs/aops.c | 2 +-
fs/reiserfs/inode.c | 2 +-
include/linux/buffer_head.h | 2 +-
5 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index a7fc561758b1..4d518df50fab 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1764,7 +1764,7 @@ static struct buffer_head *folio_create_buffers(struct folio *folio,
* WB_SYNC_ALL, the writes are posted using REQ_SYNC; this
* causes the writes to be flagged as synchronous writes.
*/
-int __block_write_full_page(struct inode *inode, struct page *page,
+int __block_write_full_folio(struct inode *inode, struct folio *folio,
get_block_t *get_block, struct writeback_control *wbc,
bh_end_io_t *handler)
{
@@ -1776,14 +1776,14 @@ int __block_write_full_page(struct inode *inode, struct page *page,
int nr_underway = 0;
blk_opf_t write_flags = wbc_to_write_flags(wbc);
- head = folio_create_buffers(page_folio(page), inode,
+ head = folio_create_buffers(folio, inode,
(1 << BH_Dirty) | (1 << BH_Uptodate));
/*
* Be very careful. We have no exclusion from block_dirty_folio
* here, and the (potentially unmapped) buffers may become dirty at
* any time. If a buffer becomes dirty here after we've inspected it
- * then we just miss that fact, and the page stays dirty.
+ * then we just miss that fact, and the folio stays dirty.
*
* Buffers outside i_size may be dirtied by block_dirty_folio;
* handle that here by just cleaning them.
@@ -1793,7 +1793,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
blocksize = bh->b_size;
bbits = block_size_bits(blocksize);
- block = (sector_t)page->index << (PAGE_SHIFT - bbits);
+ block = (sector_t)folio->index << (PAGE_SHIFT - bbits);
last_block = (i_size_read(inode) - 1) >> bbits;
/*
@@ -1804,7 +1804,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
if (block > last_block) {
/*
* mapped buffers outside i_size will occur, because
- * this page can be outside i_size when there is a
+ * this folio can be outside i_size when there is a
* truncate in progress.
*/
/*
@@ -1834,7 +1834,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
continue;
/*
* If it's a fully non-blocking write attempt and we cannot
- * lock the buffer then redirty the page. Note that this can
+ * lock the buffer then redirty the folio. Note that this can
* potentially cause a busy-wait loop from writeback threads
* and kswapd activity, but those code paths have their own
* higher-level throttling.
@@ -1842,7 +1842,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
if (wbc->sync_mode != WB_SYNC_NONE) {
lock_buffer(bh);
} else if (!trylock_buffer(bh)) {
- redirty_page_for_writepage(wbc, page);
+ folio_redirty_for_writepage(wbc, folio);
continue;
}
if (test_clear_buffer_dirty(bh)) {
@@ -1853,11 +1853,11 @@ int __block_write_full_page(struct inode *inode, struct page *page,
} while ((bh = bh->b_this_page) != head);
/*
- * The page and its buffers are protected by PageWriteback(), so we can
- * drop the bh refcounts early.
+ * The folio and its buffers are protected by the writeback flag,
+ * so we can drop the bh refcounts early.
*/
- BUG_ON(PageWriteback(page));
- set_page_writeback(page);
+ BUG_ON(folio_test_writeback(folio));
+ folio_start_writeback(folio);
do {
struct buffer_head *next = bh->b_this_page;
@@ -1867,20 +1867,20 @@ int __block_write_full_page(struct inode *inode, struct page *page,
}
bh = next;
} while (bh != head);
- unlock_page(page);
+ folio_unlock(folio);
err = 0;
done:
if (nr_underway == 0) {
/*
- * The page was marked dirty, but the buffers were
+ * The folio was marked dirty, but the buffers were
* clean. Someone wrote them back by hand with
* write_dirty_buffer/submit_bh. A rare case.
*/
- end_page_writeback(page);
+ folio_end_writeback(folio);
/*
- * The page and buffer_heads can be released at any time from
+ * The folio and buffer_heads can be released at any time from
* here on.
*/
}
@@ -1891,7 +1891,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
* ENOSPC, or some other error. We may already have added some
* blocks to the file, so we need to write these out to avoid
* exposing stale data.
- * The page is currently locked and not marked for writeback
+ * The folio is currently locked and not marked for writeback
*/
bh = head;
/* Recovery: lock and submit the mapped buffers */
@@ -1903,15 +1903,15 @@ int __block_write_full_page(struct inode *inode, struct page *page,
} else {
/*
* The buffer may have been set dirty during
- * attachment to a dirty page.
+ * attachment to a dirty folio.
*/
clear_buffer_dirty(bh);
}
} while ((bh = bh->b_this_page) != head);
- SetPageError(page);
- BUG_ON(PageWriteback(page));
- mapping_set_error(page->mapping, err);
- set_page_writeback(page);
+ folio_set_error(folio);
+ BUG_ON(folio_test_writeback(folio));
+ mapping_set_error(folio->mapping, err);
+ folio_start_writeback(folio);
do {
struct buffer_head *next = bh->b_this_page;
if (buffer_async_write(bh)) {
@@ -1921,10 +1921,10 @@ int __block_write_full_page(struct inode *inode, struct page *page,
}
bh = next;
} while (bh != head);
- unlock_page(page);
+ folio_unlock(folio);
goto done;
}
-EXPORT_SYMBOL(__block_write_full_page);
+EXPORT_SYMBOL(__block_write_full_folio);
/*
* If a page has any new buffers, zero them out here, and mark them uptodate
@@ -2677,6 +2677,7 @@ EXPORT_SYMBOL(block_truncate_page);
int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc)
{
+ struct folio *folio = page_folio(page);
struct inode * const inode = page->mapping->host;
loff_t i_size = i_size_read(inode);
const pgoff_t end_index = i_size >> PAGE_SHIFT;
@@ -2684,13 +2685,13 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
/* Is the page fully inside i_size? */
if (page->index < end_index)
- return __block_write_full_page(inode, page, get_block, wbc,
+ return __block_write_full_folio(inode, folio, get_block, wbc,
end_buffer_async_write);
/* Is the page fully outside i_size? (truncate in progress) */
offset = i_size & (PAGE_SIZE-1);
if (page->index >= end_index+1 || !offset) {
- unlock_page(page);
+ folio_unlock(folio);
return 0; /* don't care */
}
@@ -2702,7 +2703,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
* writes to that region are not written out to the file."
*/
zero_user_segment(page, offset, PAGE_SIZE);
- return __block_write_full_page(inode, page, get_block, wbc,
+ return __block_write_full_folio(inode, folio, get_block, wbc,
end_buffer_async_write);
}
EXPORT_SYMBOL(block_write_full_page);
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index ec5b5c1ea634..3a2be1901e1e 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -107,9 +107,8 @@ static int gfs2_write_jdata_folio(struct folio *folio,
folio_zero_segment(folio, offset_in_folio(folio, i_size),
folio_size(folio));
- return __block_write_full_page(inode, &folio->page,
- gfs2_get_block_noalloc, wbc,
- end_buffer_async_write);
+ return __block_write_full_folio(inode, folio, gfs2_get_block_noalloc,
+ wbc, end_buffer_async_write);
}
/**
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index e8aeba124a95..4e158bce4192 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -526,7 +526,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
*
* Return 0 on success and -errno on error.
*
- * Based on ntfs_read_block() and __block_write_full_page().
+ * Based on ntfs_read_block() and __block_write_full_folio().
*/
static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
{
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index d8debbb6105f..ff34ee49106f 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2506,7 +2506,7 @@ static int map_block_for_writepage(struct inode *inode,
/*
* mason@suse.com: updated in 2.5.54 to follow the same general io
- * start/recovery path as __block_write_full_page, along with special
+ * start/recovery path as __block_write_full_folio, along with special
* code to handle reiserfs tails.
*/
static int reiserfs_write_full_page(struct page *page,
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 1520793c72da..a366e01f8bd4 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -263,7 +263,7 @@ extern int buffer_heads_over_limit;
void block_invalidate_folio(struct folio *folio, size_t offset, size_t length);
int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc);
-int __block_write_full_page(struct inode *inode, struct page *page,
+int __block_write_full_folio(struct inode *inode, struct folio *folio,
get_block_t *get_block, struct writeback_control *wbc,
bh_end_io_t *handler);
int block_read_full_folio(struct folio *, get_block_t *);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 04/14] buffer: Convert __block_write_full_page() to __block_write_full_folio()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Remove nine hidden calls to compound_head() by using a folio instead
of a page.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/buffer.c | 53 +++++++++++++++++++------------------
fs/gfs2/aops.c | 5 ++--
fs/ntfs/aops.c | 2 +-
fs/reiserfs/inode.c | 2 +-
include/linux/buffer_head.h | 2 +-
5 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index a7fc561758b1..4d518df50fab 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1764,7 +1764,7 @@ static struct buffer_head *folio_create_buffers(struct folio *folio,
* WB_SYNC_ALL, the writes are posted using REQ_SYNC; this
* causes the writes to be flagged as synchronous writes.
*/
-int __block_write_full_page(struct inode *inode, struct page *page,
+int __block_write_full_folio(struct inode *inode, struct folio *folio,
get_block_t *get_block, struct writeback_control *wbc,
bh_end_io_t *handler)
{
@@ -1776,14 +1776,14 @@ int __block_write_full_page(struct inode *inode, struct page *page,
int nr_underway = 0;
blk_opf_t write_flags = wbc_to_write_flags(wbc);
- head = folio_create_buffers(page_folio(page), inode,
+ head = folio_create_buffers(folio, inode,
(1 << BH_Dirty) | (1 << BH_Uptodate));
/*
* Be very careful. We have no exclusion from block_dirty_folio
* here, and the (potentially unmapped) buffers may become dirty at
* any time. If a buffer becomes dirty here after we've inspected it
- * then we just miss that fact, and the page stays dirty.
+ * then we just miss that fact, and the folio stays dirty.
*
* Buffers outside i_size may be dirtied by block_dirty_folio;
* handle that here by just cleaning them.
@@ -1793,7 +1793,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
blocksize = bh->b_size;
bbits = block_size_bits(blocksize);
- block = (sector_t)page->index << (PAGE_SHIFT - bbits);
+ block = (sector_t)folio->index << (PAGE_SHIFT - bbits);
last_block = (i_size_read(inode) - 1) >> bbits;
/*
@@ -1804,7 +1804,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
if (block > last_block) {
/*
* mapped buffers outside i_size will occur, because
- * this page can be outside i_size when there is a
+ * this folio can be outside i_size when there is a
* truncate in progress.
*/
/*
@@ -1834,7 +1834,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
continue;
/*
* If it's a fully non-blocking write attempt and we cannot
- * lock the buffer then redirty the page. Note that this can
+ * lock the buffer then redirty the folio. Note that this can
* potentially cause a busy-wait loop from writeback threads
* and kswapd activity, but those code paths have their own
* higher-level throttling.
@@ -1842,7 +1842,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
if (wbc->sync_mode != WB_SYNC_NONE) {
lock_buffer(bh);
} else if (!trylock_buffer(bh)) {
- redirty_page_for_writepage(wbc, page);
+ folio_redirty_for_writepage(wbc, folio);
continue;
}
if (test_clear_buffer_dirty(bh)) {
@@ -1853,11 +1853,11 @@ int __block_write_full_page(struct inode *inode, struct page *page,
} while ((bh = bh->b_this_page) != head);
/*
- * The page and its buffers are protected by PageWriteback(), so we can
- * drop the bh refcounts early.
+ * The folio and its buffers are protected by the writeback flag,
+ * so we can drop the bh refcounts early.
*/
- BUG_ON(PageWriteback(page));
- set_page_writeback(page);
+ BUG_ON(folio_test_writeback(folio));
+ folio_start_writeback(folio);
do {
struct buffer_head *next = bh->b_this_page;
@@ -1867,20 +1867,20 @@ int __block_write_full_page(struct inode *inode, struct page *page,
}
bh = next;
} while (bh != head);
- unlock_page(page);
+ folio_unlock(folio);
err = 0;
done:
if (nr_underway == 0) {
/*
- * The page was marked dirty, but the buffers were
+ * The folio was marked dirty, but the buffers were
* clean. Someone wrote them back by hand with
* write_dirty_buffer/submit_bh. A rare case.
*/
- end_page_writeback(page);
+ folio_end_writeback(folio);
/*
- * The page and buffer_heads can be released at any time from
+ * The folio and buffer_heads can be released at any time from
* here on.
*/
}
@@ -1891,7 +1891,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
* ENOSPC, or some other error. We may already have added some
* blocks to the file, so we need to write these out to avoid
* exposing stale data.
- * The page is currently locked and not marked for writeback
+ * The folio is currently locked and not marked for writeback
*/
bh = head;
/* Recovery: lock and submit the mapped buffers */
@@ -1903,15 +1903,15 @@ int __block_write_full_page(struct inode *inode, struct page *page,
} else {
/*
* The buffer may have been set dirty during
- * attachment to a dirty page.
+ * attachment to a dirty folio.
*/
clear_buffer_dirty(bh);
}
} while ((bh = bh->b_this_page) != head);
- SetPageError(page);
- BUG_ON(PageWriteback(page));
- mapping_set_error(page->mapping, err);
- set_page_writeback(page);
+ folio_set_error(folio);
+ BUG_ON(folio_test_writeback(folio));
+ mapping_set_error(folio->mapping, err);
+ folio_start_writeback(folio);
do {
struct buffer_head *next = bh->b_this_page;
if (buffer_async_write(bh)) {
@@ -1921,10 +1921,10 @@ int __block_write_full_page(struct inode *inode, struct page *page,
}
bh = next;
} while (bh != head);
- unlock_page(page);
+ folio_unlock(folio);
goto done;
}
-EXPORT_SYMBOL(__block_write_full_page);
+EXPORT_SYMBOL(__block_write_full_folio);
/*
* If a page has any new buffers, zero them out here, and mark them uptodate
@@ -2677,6 +2677,7 @@ EXPORT_SYMBOL(block_truncate_page);
int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc)
{
+ struct folio *folio = page_folio(page);
struct inode * const inode = page->mapping->host;
loff_t i_size = i_size_read(inode);
const pgoff_t end_index = i_size >> PAGE_SHIFT;
@@ -2684,13 +2685,13 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
/* Is the page fully inside i_size? */
if (page->index < end_index)
- return __block_write_full_page(inode, page, get_block, wbc,
+ return __block_write_full_folio(inode, folio, get_block, wbc,
end_buffer_async_write);
/* Is the page fully outside i_size? (truncate in progress) */
offset = i_size & (PAGE_SIZE-1);
if (page->index >= end_index+1 || !offset) {
- unlock_page(page);
+ folio_unlock(folio);
return 0; /* don't care */
}
@@ -2702,7 +2703,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
* writes to that region are not written out to the file."
*/
zero_user_segment(page, offset, PAGE_SIZE);
- return __block_write_full_page(inode, page, get_block, wbc,
+ return __block_write_full_folio(inode, folio, get_block, wbc,
end_buffer_async_write);
}
EXPORT_SYMBOL(block_write_full_page);
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index ec5b5c1ea634..3a2be1901e1e 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -107,9 +107,8 @@ static int gfs2_write_jdata_folio(struct folio *folio,
folio_zero_segment(folio, offset_in_folio(folio, i_size),
folio_size(folio));
- return __block_write_full_page(inode, &folio->page,
- gfs2_get_block_noalloc, wbc,
- end_buffer_async_write);
+ return __block_write_full_folio(inode, folio, gfs2_get_block_noalloc,
+ wbc, end_buffer_async_write);
}
/**
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index e8aeba124a95..4e158bce4192 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -526,7 +526,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
*
* Return 0 on success and -errno on error.
*
- * Based on ntfs_read_block() and __block_write_full_page().
+ * Based on ntfs_read_block() and __block_write_full_folio().
*/
static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
{
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index d8debbb6105f..ff34ee49106f 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2506,7 +2506,7 @@ static int map_block_for_writepage(struct inode *inode,
/*
* mason at suse.com: updated in 2.5.54 to follow the same general io
- * start/recovery path as __block_write_full_page, along with special
+ * start/recovery path as __block_write_full_folio, along with special
* code to handle reiserfs tails.
*/
static int reiserfs_write_full_page(struct page *page,
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 1520793c72da..a366e01f8bd4 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -263,7 +263,7 @@ extern int buffer_heads_over_limit;
void block_invalidate_folio(struct folio *folio, size_t offset, size_t length);
int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc);
-int __block_write_full_page(struct inode *inode, struct page *page,
+int __block_write_full_folio(struct inode *inode, struct folio *folio,
get_block_t *get_block, struct writeback_control *wbc,
bh_end_io_t *handler);
int block_read_full_folio(struct folio *, get_block_t *);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 05/14] gfs2: Support ludicrously large folios in gfs2_trans_add_databufs()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher, Bob Peterson
We may someday support folios larger than 4GB, so use a size_t for
the byte count within a folio to prevent unpleasant truncations.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 6 +++---
fs/gfs2/aops.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 3a2be1901e1e..1c407eba1e30 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -38,13 +38,13 @@
void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
- unsigned int from, unsigned int len)
+ size_t from, size_t len)
{
struct buffer_head *head = folio_buffers(folio);
unsigned int bsize = head->b_size;
struct buffer_head *bh;
- unsigned int to = from + len;
- unsigned int start, end;
+ size_t to = from + len;
+ size_t start, end;
for (bh = head, start = 0; bh != head || !start;
bh = bh->b_this_page, start = end) {
diff --git a/fs/gfs2/aops.h b/fs/gfs2/aops.h
index 09db1914425e..f08322ef41cf 100644
--- a/fs/gfs2/aops.h
+++ b/fs/gfs2/aops.h
@@ -10,6 +10,6 @@
extern void adjust_fs_space(struct inode *inode);
extern void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
- unsigned int from, unsigned int len);
+ size_t from, size_t len);
#endif /* __AOPS_DOT_H__ */
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 05/14] gfs2: Support ludicrously large folios in gfs2_trans_add_databufs()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
We may someday support folios larger than 4GB, so use a size_t for
the byte count within a folio to prevent unpleasant truncations.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 6 +++---
fs/gfs2/aops.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 3a2be1901e1e..1c407eba1e30 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -38,13 +38,13 @@
void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
- unsigned int from, unsigned int len)
+ size_t from, size_t len)
{
struct buffer_head *head = folio_buffers(folio);
unsigned int bsize = head->b_size;
struct buffer_head *bh;
- unsigned int to = from + len;
- unsigned int start, end;
+ size_t to = from + len;
+ size_t start, end;
for (bh = head, start = 0; bh != head || !start;
bh = bh->b_this_page, start = end) {
diff --git a/fs/gfs2/aops.h b/fs/gfs2/aops.h
index 09db1914425e..f08322ef41cf 100644
--- a/fs/gfs2/aops.h
+++ b/fs/gfs2/aops.h
@@ -10,6 +10,6 @@
extern void adjust_fs_space(struct inode *inode);
extern void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
- unsigned int from, unsigned int len);
+ size_t from, size_t len);
#endif /* __AOPS_DOT_H__ */
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 06/14] buffer: Make block_write_full_page() handle large folios correctly
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher, Bob Peterson
Keep the interface as struct page, but work entirely on the folio
internally. Removes several PAGE_SIZE assumptions and removes
some references to page->index and page->mapping.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/buffer.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 4d518df50fab..34ecf55d2f12 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2678,33 +2678,31 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc)
{
struct folio *folio = page_folio(page);
- struct inode * const inode = page->mapping->host;
+ struct inode * const inode = folio->mapping->host;
loff_t i_size = i_size_read(inode);
- const pgoff_t end_index = i_size >> PAGE_SHIFT;
- unsigned offset;
- /* Is the page fully inside i_size? */
- if (page->index < end_index)
+ /* Is the folio fully inside i_size? */
+ if (folio_pos(folio) + folio_size(folio) <= i_size)
return __block_write_full_folio(inode, folio, get_block, wbc,
end_buffer_async_write);
- /* Is the page fully outside i_size? (truncate in progress) */
- offset = i_size & (PAGE_SIZE-1);
- if (page->index >= end_index+1 || !offset) {
+ /* Is the folio fully outside i_size? (truncate in progress) */
+ if (folio_pos(folio) >= i_size) {
folio_unlock(folio);
return 0; /* don't care */
}
/*
- * The page straddles i_size. It must be zeroed out on each and every
+ * The folio straddles i_size. It must be zeroed out on each and every
* writepage invocation because it may be mmapped. "A file is mapped
* in multiples of the page size. For a file that is not a multiple of
- * the page size, the remaining memory is zeroed when mapped, and
+ * the page size, the remaining memory is zeroed when mapped, and
* writes to that region are not written out to the file."
*/
- zero_user_segment(page, offset, PAGE_SIZE);
+ folio_zero_segment(folio, offset_in_folio(folio, i_size),
+ folio_size(folio));
return __block_write_full_folio(inode, folio, get_block, wbc,
- end_buffer_async_write);
+ end_buffer_async_write);
}
EXPORT_SYMBOL(block_write_full_page);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 06/14] buffer: Make block_write_full_page() handle large folios correctly
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Keep the interface as struct page, but work entirely on the folio
internally. Removes several PAGE_SIZE assumptions and removes
some references to page->index and page->mapping.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
---
fs/buffer.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 4d518df50fab..34ecf55d2f12 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2678,33 +2678,31 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc)
{
struct folio *folio = page_folio(page);
- struct inode * const inode = page->mapping->host;
+ struct inode * const inode = folio->mapping->host;
loff_t i_size = i_size_read(inode);
- const pgoff_t end_index = i_size >> PAGE_SHIFT;
- unsigned offset;
- /* Is the page fully inside i_size? */
- if (page->index < end_index)
+ /* Is the folio fully inside i_size? */
+ if (folio_pos(folio) + folio_size(folio) <= i_size)
return __block_write_full_folio(inode, folio, get_block, wbc,
end_buffer_async_write);
- /* Is the page fully outside i_size? (truncate in progress) */
- offset = i_size & (PAGE_SIZE-1);
- if (page->index >= end_index+1 || !offset) {
+ /* Is the folio fully outside i_size? (truncate in progress) */
+ if (folio_pos(folio) >= i_size) {
folio_unlock(folio);
return 0; /* don't care */
}
/*
- * The page straddles i_size. It must be zeroed out on each and every
+ * The folio straddles i_size. It must be zeroed out on each and every
* writepage invocation because it may be mmapped. "A file is mapped
* in multiples of the page size. For a file that is not a multiple of
- * the page size, the remaining memory is zeroed when mapped, and
+ * the page size, the remaining memory is zeroed when mapped, and
* writes to that region are not written out to the file."
*/
- zero_user_segment(page, offset, PAGE_SIZE);
+ folio_zero_segment(folio, offset_in_folio(folio, i_size),
+ folio_size(folio));
return __block_write_full_folio(inode, folio, get_block, wbc,
- end_buffer_async_write);
+ end_buffer_async_write);
}
EXPORT_SYMBOL(block_write_full_page);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 07/14] buffer: Convert block_page_mkwrite() to use a folio
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
If any page in a folio is dirtied, dirty the entire folio. Removes a
number of hidden calls to compound_head() and references to page->mapping
and page->index. Fixes a pre-existing bug where we could mark a folio
as dirty if the file is truncated to a multiple of the page size just
as we take the page fault. I don't believe this bug has any bad effect,
it's just inefficient.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 34ecf55d2f12..0af167e8a9c6 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2564,38 +2564,37 @@ EXPORT_SYMBOL(block_commit_write);
int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
get_block_t get_block)
{
- struct page *page = vmf->page;
+ struct folio *folio = page_folio(vmf->page);
struct inode *inode = file_inode(vma->vm_file);
unsigned long end;
loff_t size;
int ret;
- lock_page(page);
+ folio_lock(folio);
size = i_size_read(inode);
- if ((page->mapping != inode->i_mapping) ||
- (page_offset(page) > size)) {
+ if ((folio->mapping != inode->i_mapping) ||
+ (folio_pos(folio) >= size)) {
/* We overload EFAULT to mean page got truncated */
ret = -EFAULT;
goto out_unlock;
}
- /* page is wholly or partially inside EOF */
- if (((page->index + 1) << PAGE_SHIFT) > size)
- end = size & ~PAGE_MASK;
- else
- end = PAGE_SIZE;
+ end = folio_size(folio);
+ /* folio is wholly or partially inside EOF */
+ if (folio_pos(folio) + end > size)
+ end = size - folio_pos(folio);
- ret = __block_write_begin(page, 0, end, get_block);
+ ret = __block_write_begin_int(folio, 0, end, get_block, NULL);
if (!ret)
- ret = block_commit_write(page, 0, end);
+ ret = block_commit_write(&folio->page, 0, end);
if (unlikely(ret < 0))
goto out_unlock;
- set_page_dirty(page);
- wait_for_stable_page(page);
+ folio_mark_dirty(folio);
+ folio_wait_stable(folio);
return 0;
out_unlock:
- unlock_page(page);
+ folio_unlock(folio);
return ret;
}
EXPORT_SYMBOL(block_page_mkwrite);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 07/14] buffer: Convert block_page_mkwrite() to use a folio
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
If any page in a folio is dirtied, dirty the entire folio. Removes a
number of hidden calls to compound_head() and references to page->mapping
and page->index. Fixes a pre-existing bug where we could mark a folio
as dirty if the file is truncated to a multiple of the page size just
as we take the page fault. I don't believe this bug has any bad effect,
it's just inefficient.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 34ecf55d2f12..0af167e8a9c6 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2564,38 +2564,37 @@ EXPORT_SYMBOL(block_commit_write);
int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
get_block_t get_block)
{
- struct page *page = vmf->page;
+ struct folio *folio = page_folio(vmf->page);
struct inode *inode = file_inode(vma->vm_file);
unsigned long end;
loff_t size;
int ret;
- lock_page(page);
+ folio_lock(folio);
size = i_size_read(inode);
- if ((page->mapping != inode->i_mapping) ||
- (page_offset(page) > size)) {
+ if ((folio->mapping != inode->i_mapping) ||
+ (folio_pos(folio) >= size)) {
/* We overload EFAULT to mean page got truncated */
ret = -EFAULT;
goto out_unlock;
}
- /* page is wholly or partially inside EOF */
- if (((page->index + 1) << PAGE_SHIFT) > size)
- end = size & ~PAGE_MASK;
- else
- end = PAGE_SIZE;
+ end = folio_size(folio);
+ /* folio is wholly or partially inside EOF */
+ if (folio_pos(folio) + end > size)
+ end = size - folio_pos(folio);
- ret = __block_write_begin(page, 0, end, get_block);
+ ret = __block_write_begin_int(folio, 0, end, get_block, NULL);
if (!ret)
- ret = block_commit_write(page, 0, end);
+ ret = block_commit_write(&folio->page, 0, end);
if (unlikely(ret < 0))
goto out_unlock;
- set_page_dirty(page);
- wait_for_stable_page(page);
+ folio_mark_dirty(folio);
+ folio_wait_stable(folio);
return 0;
out_unlock:
- unlock_page(page);
+ folio_unlock(folio);
return ret;
}
EXPORT_SYMBOL(block_page_mkwrite);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 08/14] buffer: Convert __block_commit_write() to take a folio
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
This removes a hidden call to compound_head() inside
__block_commit_write() and moves it to those callers which are still
page based. Also make block_write_end() safe for large folios.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 0af167e8a9c6..97c64b05151f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2116,15 +2116,15 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len,
}
EXPORT_SYMBOL(__block_write_begin);
-static int __block_commit_write(struct inode *inode, struct page *page,
- unsigned from, unsigned to)
+static int __block_commit_write(struct inode *inode, struct folio *folio,
+ size_t from, size_t to)
{
- unsigned block_start, block_end;
- int partial = 0;
+ size_t block_start, block_end;
+ bool partial = false;
unsigned blocksize;
struct buffer_head *bh, *head;
- bh = head = page_buffers(page);
+ bh = head = folio_buffers(folio);
blocksize = bh->b_size;
block_start = 0;
@@ -2132,7 +2132,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
block_end = block_start + blocksize;
if (block_end <= from || block_start >= to) {
if (!buffer_uptodate(bh))
- partial = 1;
+ partial = true;
} else {
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
@@ -2147,11 +2147,11 @@ static int __block_commit_write(struct inode *inode, struct page *page,
/*
* If this is a partial write which happened to make all buffers
* uptodate then we can optimize away a bogus read_folio() for
- * the next read(). Here we 'discover' whether the page went
+ * the next read(). Here we 'discover' whether the folio went
* uptodate as a result of this (potentially partial) write.
*/
if (!partial)
- SetPageUptodate(page);
+ folio_mark_uptodate(folio);
return 0;
}
@@ -2188,10 +2188,9 @@ int block_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
{
+ struct folio *folio = page_folio(page);
struct inode *inode = mapping->host;
- unsigned start;
-
- start = pos & (PAGE_SIZE - 1);
+ size_t start = pos - folio_pos(folio);
if (unlikely(copied < len)) {
/*
@@ -2203,18 +2202,18 @@ int block_write_end(struct file *file, struct address_space *mapping,
* read_folio might come in and destroy our partial write.
*
* Do the simplest thing, and just treat any short write to a
- * non uptodate page as a zero-length write, and force the
+ * non uptodate folio as a zero-length write, and force the
* caller to redo the whole thing.
*/
- if (!PageUptodate(page))
+ if (!folio_test_uptodate(folio))
copied = 0;
- page_zero_new_buffers(page, start+copied, start+len);
+ page_zero_new_buffers(&folio->page, start+copied, start+len);
}
- flush_dcache_page(page);
+ flush_dcache_folio(folio);
/* This could be a short (even 0-length) commit */
- __block_commit_write(inode, page, start, start+copied);
+ __block_commit_write(inode, folio, start, start + copied);
return copied;
}
@@ -2537,8 +2536,9 @@ EXPORT_SYMBOL(cont_write_begin);
int block_commit_write(struct page *page, unsigned from, unsigned to)
{
- struct inode *inode = page->mapping->host;
- __block_commit_write(inode,page,from,to);
+ struct folio *folio = page_folio(page);
+ struct inode *inode = folio->mapping->host;
+ __block_commit_write(inode, folio, from, to);
return 0;
}
EXPORT_SYMBOL(block_commit_write);
@@ -2586,7 +2586,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
ret = __block_write_begin_int(folio, 0, end, get_block, NULL);
if (!ret)
- ret = block_commit_write(&folio->page, 0, end);
+ ret = __block_commit_write(inode, folio, 0, end);
if (unlikely(ret < 0))
goto out_unlock;
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 08/14] buffer: Convert __block_commit_write() to take a folio
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
This removes a hidden call to compound_head() inside
__block_commit_write() and moves it to those callers which are still
page based. Also make block_write_end() safe for large folios.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 0af167e8a9c6..97c64b05151f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2116,15 +2116,15 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len,
}
EXPORT_SYMBOL(__block_write_begin);
-static int __block_commit_write(struct inode *inode, struct page *page,
- unsigned from, unsigned to)
+static int __block_commit_write(struct inode *inode, struct folio *folio,
+ size_t from, size_t to)
{
- unsigned block_start, block_end;
- int partial = 0;
+ size_t block_start, block_end;
+ bool partial = false;
unsigned blocksize;
struct buffer_head *bh, *head;
- bh = head = page_buffers(page);
+ bh = head = folio_buffers(folio);
blocksize = bh->b_size;
block_start = 0;
@@ -2132,7 +2132,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
block_end = block_start + blocksize;
if (block_end <= from || block_start >= to) {
if (!buffer_uptodate(bh))
- partial = 1;
+ partial = true;
} else {
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
@@ -2147,11 +2147,11 @@ static int __block_commit_write(struct inode *inode, struct page *page,
/*
* If this is a partial write which happened to make all buffers
* uptodate then we can optimize away a bogus read_folio() for
- * the next read(). Here we 'discover' whether the page went
+ * the next read(). Here we 'discover' whether the folio went
* uptodate as a result of this (potentially partial) write.
*/
if (!partial)
- SetPageUptodate(page);
+ folio_mark_uptodate(folio);
return 0;
}
@@ -2188,10 +2188,9 @@ int block_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
{
+ struct folio *folio = page_folio(page);
struct inode *inode = mapping->host;
- unsigned start;
-
- start = pos & (PAGE_SIZE - 1);
+ size_t start = pos - folio_pos(folio);
if (unlikely(copied < len)) {
/*
@@ -2203,18 +2202,18 @@ int block_write_end(struct file *file, struct address_space *mapping,
* read_folio might come in and destroy our partial write.
*
* Do the simplest thing, and just treat any short write to a
- * non uptodate page as a zero-length write, and force the
+ * non uptodate folio as a zero-length write, and force the
* caller to redo the whole thing.
*/
- if (!PageUptodate(page))
+ if (!folio_test_uptodate(folio))
copied = 0;
- page_zero_new_buffers(page, start+copied, start+len);
+ page_zero_new_buffers(&folio->page, start+copied, start+len);
}
- flush_dcache_page(page);
+ flush_dcache_folio(folio);
/* This could be a short (even 0-length) commit */
- __block_commit_write(inode, page, start, start+copied);
+ __block_commit_write(inode, folio, start, start + copied);
return copied;
}
@@ -2537,8 +2536,9 @@ EXPORT_SYMBOL(cont_write_begin);
int block_commit_write(struct page *page, unsigned from, unsigned to)
{
- struct inode *inode = page->mapping->host;
- __block_commit_write(inode,page,from,to);
+ struct folio *folio = page_folio(page);
+ struct inode *inode = folio->mapping->host;
+ __block_commit_write(inode, folio, from, to);
return 0;
}
EXPORT_SYMBOL(block_commit_write);
@@ -2586,7 +2586,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
ret = __block_write_begin_int(folio, 0, end, get_block, NULL);
if (!ret)
- ret = block_commit_write(&folio->page, 0, end);
+ ret = __block_commit_write(inode, folio, 0, end);
if (unlikely(ret < 0))
goto out_unlock;
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 09/14] buffer: Convert page_zero_new_buffers() to folio_zero_new_buffers()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
Most of the callers already have a folio; convert reiserfs_write_end()
to have a folio. Removes a couple of hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 27 ++++++++++++++-------------
fs/ext4/inode.c | 4 ++--
fs/reiserfs/inode.c | 7 ++++---
include/linux/buffer_head.h | 2 +-
4 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 97c64b05151f..e4bd465ecee8 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1927,33 +1927,34 @@ int __block_write_full_folio(struct inode *inode, struct folio *folio,
EXPORT_SYMBOL(__block_write_full_folio);
/*
- * If a page has any new buffers, zero them out here, and mark them uptodate
+ * If a folio has any new buffers, zero them out here, and mark them uptodate
* and dirty so they'll be written out (in order to prevent uninitialised
* block data from leaking). And clear the new bit.
*/
-void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
+void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to)
{
- unsigned int block_start, block_end;
+ size_t block_start, block_end;
struct buffer_head *head, *bh;
- BUG_ON(!PageLocked(page));
- if (!page_has_buffers(page))
+ BUG_ON(!folio_test_locked(folio));
+ head = folio_buffers(folio);
+ if (!head)
return;
- bh = head = page_buffers(page);
+ bh = head;
block_start = 0;
do {
block_end = block_start + bh->b_size;
if (buffer_new(bh)) {
if (block_end > from && block_start < to) {
- if (!PageUptodate(page)) {
- unsigned start, size;
+ if (!folio_test_uptodate(folio)) {
+ size_t start, xend;
start = max(from, block_start);
- size = min(to, block_end) - start;
+ xend = min(to, block_end);
- zero_user(page, start, size);
+ folio_zero_segment(folio, start, xend);
set_buffer_uptodate(bh);
}
@@ -1966,7 +1967,7 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
bh = bh->b_this_page;
} while (bh != head);
}
-EXPORT_SYMBOL(page_zero_new_buffers);
+EXPORT_SYMBOL(folio_zero_new_buffers);
static void
iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
@@ -2104,7 +2105,7 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
err = -EIO;
}
if (unlikely(err))
- page_zero_new_buffers(&folio->page, from, to);
+ folio_zero_new_buffers(folio, from, to);
return err;
}
@@ -2208,7 +2209,7 @@ int block_write_end(struct file *file, struct address_space *mapping,
if (!folio_test_uptodate(folio))
copied = 0;
- page_zero_new_buffers(&folio->page, start+copied, start+len);
+ folio_zero_new_buffers(folio, start+copied, start+len);
}
flush_dcache_folio(folio);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 02de439bf1f0..9ca583360166 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1093,7 +1093,7 @@ static int ext4_block_write_begin(struct folio *folio, loff_t pos, unsigned len,
err = -EIO;
}
if (unlikely(err)) {
- page_zero_new_buffers(&folio->page, from, to);
+ folio_zero_new_buffers(folio, from, to);
} else if (fscrypt_inode_uses_fs_layer_crypto(inode)) {
for (i = 0; i < nr_wait; i++) {
int err2;
@@ -1339,7 +1339,7 @@ static int ext4_write_end(struct file *file,
}
/*
- * This is a private version of page_zero_new_buffers() which doesn't
+ * This is a private version of folio_zero_new_buffers() which doesn't
* set the buffer to be dirty, since in data=journalled mode we need
* to call ext4_dirty_journalled_data() instead.
*/
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ff34ee49106f..77bd3b27059f 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2872,6 +2872,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
{
+ struct folio *folio = page_folio(page);
struct inode *inode = page->mapping->host;
int ret = 0;
int update_sd = 0;
@@ -2887,12 +2888,12 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
start = pos & (PAGE_SIZE - 1);
if (unlikely(copied < len)) {
- if (!PageUptodate(page))
+ if (!folio_test_uptodate(folio))
copied = 0;
- page_zero_new_buffers(page, start + copied, start + len);
+ folio_zero_new_buffers(folio, start + copied, start + len);
}
- flush_dcache_page(page);
+ flush_dcache_folio(folio);
reiserfs_commit_page(inode, page, start, start + copied);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index a366e01f8bd4..c794ea7096ba 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -278,7 +278,7 @@ int block_write_end(struct file *, struct address_space *,
int generic_write_end(struct file *, struct address_space *,
loff_t, unsigned, unsigned,
struct page *, void *);
-void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
+void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to);
void clean_page_buffers(struct page *page);
int cont_write_begin(struct file *, struct address_space *, loff_t,
unsigned, struct page **, void **,
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 09/14] buffer: Convert page_zero_new_buffers() to folio_zero_new_buffers()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Most of the callers already have a folio; convert reiserfs_write_end()
to have a folio. Removes a couple of hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 27 ++++++++++++++-------------
fs/ext4/inode.c | 4 ++--
fs/reiserfs/inode.c | 7 ++++---
include/linux/buffer_head.h | 2 +-
4 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 97c64b05151f..e4bd465ecee8 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1927,33 +1927,34 @@ int __block_write_full_folio(struct inode *inode, struct folio *folio,
EXPORT_SYMBOL(__block_write_full_folio);
/*
- * If a page has any new buffers, zero them out here, and mark them uptodate
+ * If a folio has any new buffers, zero them out here, and mark them uptodate
* and dirty so they'll be written out (in order to prevent uninitialised
* block data from leaking). And clear the new bit.
*/
-void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
+void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to)
{
- unsigned int block_start, block_end;
+ size_t block_start, block_end;
struct buffer_head *head, *bh;
- BUG_ON(!PageLocked(page));
- if (!page_has_buffers(page))
+ BUG_ON(!folio_test_locked(folio));
+ head = folio_buffers(folio);
+ if (!head)
return;
- bh = head = page_buffers(page);
+ bh = head;
block_start = 0;
do {
block_end = block_start + bh->b_size;
if (buffer_new(bh)) {
if (block_end > from && block_start < to) {
- if (!PageUptodate(page)) {
- unsigned start, size;
+ if (!folio_test_uptodate(folio)) {
+ size_t start, xend;
start = max(from, block_start);
- size = min(to, block_end) - start;
+ xend = min(to, block_end);
- zero_user(page, start, size);
+ folio_zero_segment(folio, start, xend);
set_buffer_uptodate(bh);
}
@@ -1966,7 +1967,7 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
bh = bh->b_this_page;
} while (bh != head);
}
-EXPORT_SYMBOL(page_zero_new_buffers);
+EXPORT_SYMBOL(folio_zero_new_buffers);
static void
iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
@@ -2104,7 +2105,7 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
err = -EIO;
}
if (unlikely(err))
- page_zero_new_buffers(&folio->page, from, to);
+ folio_zero_new_buffers(folio, from, to);
return err;
}
@@ -2208,7 +2209,7 @@ int block_write_end(struct file *file, struct address_space *mapping,
if (!folio_test_uptodate(folio))
copied = 0;
- page_zero_new_buffers(&folio->page, start+copied, start+len);
+ folio_zero_new_buffers(folio, start+copied, start+len);
}
flush_dcache_folio(folio);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 02de439bf1f0..9ca583360166 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1093,7 +1093,7 @@ static int ext4_block_write_begin(struct folio *folio, loff_t pos, unsigned len,
err = -EIO;
}
if (unlikely(err)) {
- page_zero_new_buffers(&folio->page, from, to);
+ folio_zero_new_buffers(folio, from, to);
} else if (fscrypt_inode_uses_fs_layer_crypto(inode)) {
for (i = 0; i < nr_wait; i++) {
int err2;
@@ -1339,7 +1339,7 @@ static int ext4_write_end(struct file *file,
}
/*
- * This is a private version of page_zero_new_buffers() which doesn't
+ * This is a private version of folio_zero_new_buffers() which doesn't
* set the buffer to be dirty, since in data=journalled mode we need
* to call ext4_dirty_journalled_data() instead.
*/
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ff34ee49106f..77bd3b27059f 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2872,6 +2872,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
{
+ struct folio *folio = page_folio(page);
struct inode *inode = page->mapping->host;
int ret = 0;
int update_sd = 0;
@@ -2887,12 +2888,12 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
start = pos & (PAGE_SIZE - 1);
if (unlikely(copied < len)) {
- if (!PageUptodate(page))
+ if (!folio_test_uptodate(folio))
copied = 0;
- page_zero_new_buffers(page, start + copied, start + len);
+ folio_zero_new_buffers(folio, start + copied, start + len);
}
- flush_dcache_page(page);
+ flush_dcache_folio(folio);
reiserfs_commit_page(inode, page, start, start + copied);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index a366e01f8bd4..c794ea7096ba 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -278,7 +278,7 @@ int block_write_end(struct file *, struct address_space *,
int generic_write_end(struct file *, struct address_space *,
loff_t, unsigned, unsigned,
struct page *, void *);
-void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
+void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to);
void clean_page_buffers(struct page *page);
int cont_write_begin(struct file *, struct address_space *, loff_t,
unsigned, struct page **, void **,
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 10/14] buffer: Convert grow_dev_page() to use a folio
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
Get a folio from the page cache instead of a page, then use the
folio API throughout. Removes a few calls to compound_head()
and may be needed to support block size > PAGE_SIZE.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 34 +++++++++++++++-------------------
1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index e4bd465ecee8..06d031e28bee 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -976,7 +976,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
pgoff_t index, int size, int sizebits, gfp_t gfp)
{
struct inode *inode = bdev->bd_inode;
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
sector_t end_block;
int ret = 0;
@@ -992,42 +992,38 @@ grow_dev_page(struct block_device *bdev, sector_t block,
*/
gfp_mask |= __GFP_NOFAIL;
- page = find_or_create_page(inode->i_mapping, index, gfp_mask);
-
- BUG_ON(!PageLocked(page));
+ folio = __filemap_get_folio(inode->i_mapping, index,
+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp_mask);
- if (page_has_buffers(page)) {
- bh = page_buffers(page);
+ bh = folio_buffers(folio);
+ if (bh) {
if (bh->b_size == size) {
- end_block = init_page_buffers(page, bdev,
+ end_block = init_page_buffers(&folio->page, bdev,
(sector_t)index << sizebits,
size);
goto done;
}
- if (!try_to_free_buffers(page_folio(page)))
+ if (!try_to_free_buffers(folio))
goto failed;
}
- /*
- * Allocate some buffers for this page
- */
- bh = alloc_page_buffers(page, size, true);
+ bh = folio_alloc_buffers(folio, size, true);
/*
- * Link the page to the buffers and initialise them. Take the
+ * Link the folio to the buffers and initialise them. Take the
* lock to be atomic wrt __find_get_block(), which does not
- * run under the page lock.
+ * run under the folio lock.
*/
spin_lock(&inode->i_mapping->private_lock);
- link_dev_buffers(page, bh);
- end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits,
- size);
+ link_dev_buffers(&folio->page, bh);
+ end_block = init_page_buffers(&folio->page, bdev,
+ (sector_t)index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
done:
ret = (block < end_block) ? 1 : -ENXIO;
failed:
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return ret;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 10/14] buffer: Convert grow_dev_page() to use a folio
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Get a folio from the page cache instead of a page, then use the
folio API throughout. Removes a few calls to compound_head()
and may be needed to support block size > PAGE_SIZE.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 34 +++++++++++++++-------------------
1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index e4bd465ecee8..06d031e28bee 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -976,7 +976,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
pgoff_t index, int size, int sizebits, gfp_t gfp)
{
struct inode *inode = bdev->bd_inode;
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
sector_t end_block;
int ret = 0;
@@ -992,42 +992,38 @@ grow_dev_page(struct block_device *bdev, sector_t block,
*/
gfp_mask |= __GFP_NOFAIL;
- page = find_or_create_page(inode->i_mapping, index, gfp_mask);
-
- BUG_ON(!PageLocked(page));
+ folio = __filemap_get_folio(inode->i_mapping, index,
+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp_mask);
- if (page_has_buffers(page)) {
- bh = page_buffers(page);
+ bh = folio_buffers(folio);
+ if (bh) {
if (bh->b_size == size) {
- end_block = init_page_buffers(page, bdev,
+ end_block = init_page_buffers(&folio->page, bdev,
(sector_t)index << sizebits,
size);
goto done;
}
- if (!try_to_free_buffers(page_folio(page)))
+ if (!try_to_free_buffers(folio))
goto failed;
}
- /*
- * Allocate some buffers for this page
- */
- bh = alloc_page_buffers(page, size, true);
+ bh = folio_alloc_buffers(folio, size, true);
/*
- * Link the page to the buffers and initialise them. Take the
+ * Link the folio to the buffers and initialise them. Take the
* lock to be atomic wrt __find_get_block(), which does not
- * run under the page lock.
+ * run under the folio lock.
*/
spin_lock(&inode->i_mapping->private_lock);
- link_dev_buffers(page, bh);
- end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits,
- size);
+ link_dev_buffers(&folio->page, bh);
+ end_block = init_page_buffers(&folio->page, bdev,
+ (sector_t)index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
done:
ret = (block < end_block) ? 1 : -ENXIO;
failed:
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return ret;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 11/14] buffer: Convert init_page_buffers() to folio_init_buffers()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
Use the folio API and pass the folio from both callers.
Saves a hidden call to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 06d031e28bee..9b9dee417467 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -934,15 +934,14 @@ static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
}
/*
- * Initialise the state of a blockdev page's buffers.
+ * Initialise the state of a blockdev folio's buffers.
*/
-static sector_t
-init_page_buffers(struct page *page, struct block_device *bdev,
- sector_t block, int size)
+static sector_t folio_init_buffers(struct folio *folio,
+ struct block_device *bdev, sector_t block, int size)
{
- struct buffer_head *head = page_buffers(page);
+ struct buffer_head *head = folio_buffers(folio);
struct buffer_head *bh = head;
- int uptodate = PageUptodate(page);
+ bool uptodate = folio_test_uptodate(folio);
sector_t end_block = blkdev_max_block(bdev, size);
do {
@@ -998,9 +997,8 @@ grow_dev_page(struct block_device *bdev, sector_t block,
bh = folio_buffers(folio);
if (bh) {
if (bh->b_size == size) {
- end_block = init_page_buffers(&folio->page, bdev,
- (sector_t)index << sizebits,
- size);
+ end_block = folio_init_buffers(folio, bdev,
+ (sector_t)index << sizebits, size);
goto done;
}
if (!try_to_free_buffers(folio))
@@ -1016,7 +1014,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
*/
spin_lock(&inode->i_mapping->private_lock);
link_dev_buffers(&folio->page, bh);
- end_block = init_page_buffers(&folio->page, bdev,
+ end_block = folio_init_buffers(folio, bdev,
(sector_t)index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
done:
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 11/14] buffer: Convert init_page_buffers() to folio_init_buffers()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Use the folio API and pass the folio from both callers.
Saves a hidden call to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 06d031e28bee..9b9dee417467 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -934,15 +934,14 @@ static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
}
/*
- * Initialise the state of a blockdev page's buffers.
+ * Initialise the state of a blockdev folio's buffers.
*/
-static sector_t
-init_page_buffers(struct page *page, struct block_device *bdev,
- sector_t block, int size)
+static sector_t folio_init_buffers(struct folio *folio,
+ struct block_device *bdev, sector_t block, int size)
{
- struct buffer_head *head = page_buffers(page);
+ struct buffer_head *head = folio_buffers(folio);
struct buffer_head *bh = head;
- int uptodate = PageUptodate(page);
+ bool uptodate = folio_test_uptodate(folio);
sector_t end_block = blkdev_max_block(bdev, size);
do {
@@ -998,9 +997,8 @@ grow_dev_page(struct block_device *bdev, sector_t block,
bh = folio_buffers(folio);
if (bh) {
if (bh->b_size == size) {
- end_block = init_page_buffers(&folio->page, bdev,
- (sector_t)index << sizebits,
- size);
+ end_block = folio_init_buffers(folio, bdev,
+ (sector_t)index << sizebits, size);
goto done;
}
if (!try_to_free_buffers(folio))
@@ -1016,7 +1014,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
*/
spin_lock(&inode->i_mapping->private_lock);
link_dev_buffers(&folio->page, bh);
- end_block = init_page_buffers(&folio->page, bdev,
+ end_block = folio_init_buffers(folio, bdev,
(sector_t)index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
done:
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 12/14] buffer: Convert link_dev_buffers to take a folio
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
Its one caller already has a folio, so switch it to use the
folio API. Removes a hidden call to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 9b9dee417467..4ca2eb2b3dca 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -907,8 +907,8 @@ struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
}
EXPORT_SYMBOL_GPL(alloc_page_buffers);
-static inline void
-link_dev_buffers(struct page *page, struct buffer_head *head)
+static inline void link_dev_buffers(struct folio *folio,
+ struct buffer_head *head)
{
struct buffer_head *bh, *tail;
@@ -918,7 +918,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
bh = bh->b_this_page;
} while (bh);
tail->b_this_page = head;
- attach_page_private(page, head);
+ folio_attach_private(folio, head);
}
static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
@@ -1013,7 +1013,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
* run under the folio lock.
*/
spin_lock(&inode->i_mapping->private_lock);
- link_dev_buffers(&folio->page, bh);
+ link_dev_buffers(folio, bh);
end_block = folio_init_buffers(folio, bdev,
(sector_t)index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 12/14] buffer: Convert link_dev_buffers to take a folio
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Its one caller already has a folio, so switch it to use the
folio API. Removes a hidden call to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 9b9dee417467..4ca2eb2b3dca 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -907,8 +907,8 @@ struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
}
EXPORT_SYMBOL_GPL(alloc_page_buffers);
-static inline void
-link_dev_buffers(struct page *page, struct buffer_head *head)
+static inline void link_dev_buffers(struct folio *folio,
+ struct buffer_head *head)
{
struct buffer_head *bh, *tail;
@@ -918,7 +918,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
bh = bh->b_this_page;
} while (bh);
tail->b_this_page = head;
- attach_page_private(page, head);
+ folio_attach_private(folio, head);
}
static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
@@ -1013,7 +1013,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
* run under the folio lock.
*/
spin_lock(&inode->i_mapping->private_lock);
- link_dev_buffers(&folio->page, bh);
+ link_dev_buffers(folio, bh);
end_block = folio_init_buffers(folio, bdev,
(sector_t)index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 13/14] buffer: Use a folio in __find_get_block_slow()
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
Saves a call to compound_head() and may be needed to support
block size > PAGE_SIZE.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 4ca2eb2b3dca..c38fdcaa32ff 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -195,19 +195,19 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
pgoff_t index;
struct buffer_head *bh;
struct buffer_head *head;
- struct page *page;
+ struct folio *folio;
int all_mapped = 1;
static DEFINE_RATELIMIT_STATE(last_warned, HZ, 1);
index = block >> (PAGE_SHIFT - bd_inode->i_blkbits);
- page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED);
- if (!page)
+ folio = __filemap_get_folio(bd_mapping, index, FGP_ACCESSED, 0);
+ if (IS_ERR(folio))
goto out;
spin_lock(&bd_mapping->private_lock);
- if (!page_has_buffers(page))
+ head = folio_buffers(folio);
+ if (!head)
goto out_unlock;
- head = page_buffers(page);
bh = head;
do {
if (!buffer_mapped(bh))
@@ -237,7 +237,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
}
out_unlock:
spin_unlock(&bd_mapping->private_lock);
- put_page(page);
+ folio_put(folio);
out:
return ret;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 13/14] buffer: Use a folio in __find_get_block_slow()
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Saves a call to compound_head() and may be needed to support
block size > PAGE_SIZE.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 4ca2eb2b3dca..c38fdcaa32ff 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -195,19 +195,19 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
pgoff_t index;
struct buffer_head *bh;
struct buffer_head *head;
- struct page *page;
+ struct folio *folio;
int all_mapped = 1;
static DEFINE_RATELIMIT_STATE(last_warned, HZ, 1);
index = block >> (PAGE_SHIFT - bd_inode->i_blkbits);
- page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED);
- if (!page)
+ folio = __filemap_get_folio(bd_mapping, index, FGP_ACCESSED, 0);
+ if (IS_ERR(folio))
goto out;
spin_lock(&bd_mapping->private_lock);
- if (!page_has_buffers(page))
+ head = folio_buffers(folio);
+ if (!head)
goto out_unlock;
- head = page_buffers(page);
bh = head;
do {
if (!buffer_mapped(bh))
@@ -237,7 +237,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
}
out_unlock:
spin_unlock(&bd_mapping->private_lock);
- put_page(page);
+ folio_put(folio);
out:
return ret;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 14/14] buffer: Convert block_truncate_page() to use a folio
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:01 ` Matthew Wilcox
-1 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-06-12 21:01 UTC (permalink / raw)
To: linux-fsdevel
Cc: Matthew Wilcox (Oracle),
cluster-devel, Hannes Reinecke, Luis Chamberlain, Andrew Morton,
Andreas Gruenbacher
Support large folios in block_truncate_page() and avoid three hidden
calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index c38fdcaa32ff..5a5b0c9d9769 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2598,17 +2598,16 @@ int block_truncate_page(struct address_space *mapping,
loff_t from, get_block_t *get_block)
{
pgoff_t index = from >> PAGE_SHIFT;
- unsigned offset = from & (PAGE_SIZE-1);
unsigned blocksize;
sector_t iblock;
- unsigned length, pos;
+ size_t offset, length, pos;
struct inode *inode = mapping->host;
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
int err = 0;
blocksize = i_blocksize(inode);
- length = offset & (blocksize - 1);
+ length = from & (blocksize - 1);
/* Block boundary? Nothing to do */
if (!length)
@@ -2617,15 +2616,18 @@ int block_truncate_page(struct address_space *mapping,
length = blocksize - length;
iblock = (sector_t)index << (PAGE_SHIFT - inode->i_blkbits);
- page = grab_cache_page(mapping, index);
- if (!page)
+ folio = filemap_grab_folio(mapping, index);
+ if (!folio)
return -ENOMEM;
- if (!page_has_buffers(page))
- create_empty_buffers(page, blocksize, 0);
+ bh = folio_buffers(folio);
+ if (!bh) {
+ folio_create_empty_buffers(folio, blocksize, 0);
+ bh = folio_buffers(folio);
+ }
/* Find the buffer that contains "offset" */
- bh = page_buffers(page);
+ offset = offset_in_folio(folio, from);
pos = blocksize;
while (offset >= pos) {
bh = bh->b_this_page;
@@ -2644,7 +2646,7 @@ int block_truncate_page(struct address_space *mapping,
}
/* Ok, it's mapped. Make sure it's up-to-date */
- if (PageUptodate(page))
+ if (folio_test_uptodate(folio))
set_buffer_uptodate(bh);
if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
@@ -2654,12 +2656,12 @@ int block_truncate_page(struct address_space *mapping,
goto unlock;
}
- zero_user(page, offset, length);
+ folio_zero_range(folio, offset, length);
mark_buffer_dirty(bh);
unlock:
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return err;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 14/14] buffer: Convert block_truncate_page() to use a folio
@ 2023-06-12 21:01 ` Matthew Wilcox
0 siblings, 0 replies; 32+ messages in thread
From: Matthew Wilcox @ 2023-06-12 21:01 UTC (permalink / raw)
To: cluster-devel.redhat.com
Support large folios in block_truncate_page() and avoid three hidden
calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index c38fdcaa32ff..5a5b0c9d9769 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2598,17 +2598,16 @@ int block_truncate_page(struct address_space *mapping,
loff_t from, get_block_t *get_block)
{
pgoff_t index = from >> PAGE_SHIFT;
- unsigned offset = from & (PAGE_SIZE-1);
unsigned blocksize;
sector_t iblock;
- unsigned length, pos;
+ size_t offset, length, pos;
struct inode *inode = mapping->host;
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
int err = 0;
blocksize = i_blocksize(inode);
- length = offset & (blocksize - 1);
+ length = from & (blocksize - 1);
/* Block boundary? Nothing to do */
if (!length)
@@ -2617,15 +2616,18 @@ int block_truncate_page(struct address_space *mapping,
length = blocksize - length;
iblock = (sector_t)index << (PAGE_SHIFT - inode->i_blkbits);
- page = grab_cache_page(mapping, index);
- if (!page)
+ folio = filemap_grab_folio(mapping, index);
+ if (!folio)
return -ENOMEM;
- if (!page_has_buffers(page))
- create_empty_buffers(page, blocksize, 0);
+ bh = folio_buffers(folio);
+ if (!bh) {
+ folio_create_empty_buffers(folio, blocksize, 0);
+ bh = folio_buffers(folio);
+ }
/* Find the buffer that contains "offset" */
- bh = page_buffers(page);
+ offset = offset_in_folio(folio, from);
pos = blocksize;
while (offset >= pos) {
bh = bh->b_this_page;
@@ -2644,7 +2646,7 @@ int block_truncate_page(struct address_space *mapping,
}
/* Ok, it's mapped. Make sure it's up-to-date */
- if (PageUptodate(page))
+ if (folio_test_uptodate(folio))
set_buffer_uptodate(bh);
if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
@@ -2654,12 +2656,12 @@ int block_truncate_page(struct address_space *mapping,
goto unlock;
}
- zero_user(page, offset, length);
+ folio_zero_range(folio, offset, length);
mark_buffer_dirty(bh);
unlock:
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return err;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH v3 00/14] gfs2/buffer folio changes for 6.5
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
@ 2023-06-12 21:28 ` Andreas Gruenbacher
-1 siblings, 0 replies; 32+ messages in thread
From: Andreas Gruenbacher @ 2023-06-12 21:28 UTC (permalink / raw)
To: Matthew Wilcox (Oracle)
Cc: linux-fsdevel, cluster-devel, Hannes Reinecke, Luis Chamberlain,
Andrew Morton
On Mon, Jun 12, 2023 at 11:02 PM Matthew Wilcox (Oracle)
<willy@infradead.org> wrote:
> This kind of started off as a gfs2 patch series, then became entwined
> with buffer heads once I realised that gfs2 was the only remaining
> caller of __block_write_full_page(). For those not in the gfs2 world,
> the big point of this series is that block_write_full_page() should now
> handle large folios correctly.
This is great, thank you. For the gfs2 bits:
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
> Andrew, if you want, I'll drop it into the pagecache tree, or you
> can just take it.
>
> v3:
> - Fix a patch title
> - Fix some checks against i_size to be >= instead of >
> - Call folio_mark_dirty() instead of folio_set_dirty()
>
> Matthew Wilcox (Oracle) (14):
> gfs2: Use a folio inside gfs2_jdata_writepage()
> gfs2: Pass a folio to __gfs2_jdata_write_folio()
> gfs2: Convert gfs2_write_jdata_page() to gfs2_write_jdata_folio()
> buffer: Convert __block_write_full_page() to
> __block_write_full_folio()
> gfs2: Support ludicrously large folios in gfs2_trans_add_databufs()
> buffer: Make block_write_full_page() handle large folios correctly
> buffer: Convert block_page_mkwrite() to use a folio
> buffer: Convert __block_commit_write() to take a folio
> buffer: Convert page_zero_new_buffers() to folio_zero_new_buffers()
> buffer: Convert grow_dev_page() to use a folio
> buffer: Convert init_page_buffers() to folio_init_buffers()
> buffer: Convert link_dev_buffers to take a folio
> buffer: Use a folio in __find_get_block_slow()
> buffer: Convert block_truncate_page() to use a folio
>
> fs/buffer.c | 257 ++++++++++++++++++------------------
> fs/ext4/inode.c | 4 +-
> fs/gfs2/aops.c | 69 +++++-----
> fs/gfs2/aops.h | 2 +-
> fs/ntfs/aops.c | 2 +-
> fs/reiserfs/inode.c | 9 +-
> include/linux/buffer_head.h | 4 +-
> 7 files changed, 172 insertions(+), 175 deletions(-)
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Cluster-devel] [PATCH v3 00/14] gfs2/buffer folio changes for 6.5
@ 2023-06-12 21:28 ` Andreas Gruenbacher
0 siblings, 0 replies; 32+ messages in thread
From: Andreas Gruenbacher @ 2023-06-12 21:28 UTC (permalink / raw)
To: cluster-devel.redhat.com
On Mon, Jun 12, 2023 at 11:02?PM Matthew Wilcox (Oracle)
<willy@infradead.org> wrote:
> This kind of started off as a gfs2 patch series, then became entwined
> with buffer heads once I realised that gfs2 was the only remaining
> caller of __block_write_full_page(). For those not in the gfs2 world,
> the big point of this series is that block_write_full_page() should now
> handle large folios correctly.
This is great, thank you. For the gfs2 bits:
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
> Andrew, if you want, I'll drop it into the pagecache tree, or you
> can just take it.
>
> v3:
> - Fix a patch title
> - Fix some checks against i_size to be >= instead of >
> - Call folio_mark_dirty() instead of folio_set_dirty()
>
> Matthew Wilcox (Oracle) (14):
> gfs2: Use a folio inside gfs2_jdata_writepage()
> gfs2: Pass a folio to __gfs2_jdata_write_folio()
> gfs2: Convert gfs2_write_jdata_page() to gfs2_write_jdata_folio()
> buffer: Convert __block_write_full_page() to
> __block_write_full_folio()
> gfs2: Support ludicrously large folios in gfs2_trans_add_databufs()
> buffer: Make block_write_full_page() handle large folios correctly
> buffer: Convert block_page_mkwrite() to use a folio
> buffer: Convert __block_commit_write() to take a folio
> buffer: Convert page_zero_new_buffers() to folio_zero_new_buffers()
> buffer: Convert grow_dev_page() to use a folio
> buffer: Convert init_page_buffers() to folio_init_buffers()
> buffer: Convert link_dev_buffers to take a folio
> buffer: Use a folio in __find_get_block_slow()
> buffer: Convert block_truncate_page() to use a folio
>
> fs/buffer.c | 257 ++++++++++++++++++------------------
> fs/ext4/inode.c | 4 +-
> fs/gfs2/aops.c | 69 +++++-----
> fs/gfs2/aops.h | 2 +-
> fs/ntfs/aops.c | 2 +-
> fs/reiserfs/inode.c | 9 +-
> include/linux/buffer_head.h | 4 +-
> 7 files changed, 172 insertions(+), 175 deletions(-)
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2023-06-12 21:29 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-12 21:01 [PATCH v3 00/14] gfs2/buffer folio changes for 6.5 Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 01/14] gfs2: Use a folio inside gfs2_jdata_writepage() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 02/14] gfs2: Pass a folio to __gfs2_jdata_write_folio() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 03/14] gfs2: Convert gfs2_write_jdata_page() to gfs2_write_jdata_folio() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 04/14] buffer: Convert __block_write_full_page() to __block_write_full_folio() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 05/14] gfs2: Support ludicrously large folios in gfs2_trans_add_databufs() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 06/14] buffer: Make block_write_full_page() handle large folios correctly Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 07/14] buffer: Convert block_page_mkwrite() to use a folio Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 08/14] buffer: Convert __block_commit_write() to take " Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 09/14] buffer: Convert page_zero_new_buffers() to folio_zero_new_buffers() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 10/14] buffer: Convert grow_dev_page() to use a folio Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 11/14] buffer: Convert init_page_buffers() to folio_init_buffers() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 12/14] buffer: Convert link_dev_buffers to take a folio Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 13/14] buffer: Use a folio in __find_get_block_slow() Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:01 ` [PATCH v3 14/14] buffer: Convert block_truncate_page() to use a folio Matthew Wilcox (Oracle)
2023-06-12 21:01 ` [Cluster-devel] " Matthew Wilcox
2023-06-12 21:28 ` [PATCH v3 00/14] gfs2/buffer folio changes for 6.5 Andreas Gruenbacher
2023-06-12 21:28 ` [Cluster-devel] " Andreas Gruenbacher
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.