* [PATCH v2 00/27] Finish the create_empty_buffers() transition
@ 2023-10-16 20:10 Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 01/27] buffer: Return bool from grow_dev_folio() Matthew Wilcox (Oracle)
` (26 more replies)
0 siblings, 27 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Pankaj recently added folio_create_empty_buffers() as the folio
equivalent to create_empty_buffers(). This patch set finishes
the conversion by first converting all remaining filesystems
to call folio_create_empty_buffers(), then renaming it back
to create_empty_buffers(). I took the opportunity to make a few
simplifications like making folio_create_empty_buffers() return the head
buffer and extracting get_nth_bh() from nilfs2.
A few of the patches in this series aren't directly related to
create_empty_buffers(), but I saw them while I was working on this and
thought they'd be easy enough to add to this series. Compile-tested only,
other than ext4.
v2:
- Added the patch to fix the return type from grow_dev_page()
- Fixed typo in subject line noticed by Andreas
- Fixed missed assignment to 'bh' spotted by Andreas
- Exported folio_copy() spotted by Ryusuke
- Added various Reviewed-by tags from Pankaj, Ryusuke & Andreas
Matthew Wilcox (Oracle) (27):
buffer: Return bool from grow_dev_folio()
buffer: Make folio_create_empty_buffers() return a buffer_head
mpage: Convert map_buffer_to_folio() to folio_create_empty_buffers()
ext4: Convert to folio_create_empty_buffers
buffer: Add get_nth_bh()
gfs2: Convert inode unstuffing to use a folio
gfs2: Convert gfs2_getbuf() to folios
gfs2: Convert gfs2_getjdatabuf to use a folio
gfs2: Convert gfs2_write_buf_to_page() to use a folio
nilfs2: Convert nilfs_mdt_freeze_buffer to use a folio
nilfs2: Convert nilfs_grab_buffer() to use a folio
nilfs2: Convert nilfs_copy_page() to nilfs_copy_folio()
nilfs2: Convert nilfs_mdt_forget_block() to use a folio
nilfs2: Convert nilfs_mdt_get_frozen_buffer to use a folio
nilfs2: Remove nilfs_page_get_nth_block
nilfs2: Convert nilfs_lookup_dirty_data_buffers to use
folio_create_empty_buffers
ntfs: Convert ntfs_read_block() to use a folio
ntfs: Convert ntfs_writepage to use a folio
ntfs: Convert ntfs_prepare_pages_for_non_resident_write() to folios
ntfs3: Convert ntfs_zero_range() to use a folio
ocfs2: Convert ocfs2_map_page_blocks to use a folio
reiserfs: Convert writepage to use a folio
ufs: Add ufs_get_locked_folio and ufs_put_locked_folio
ufs: Use ufs_get_locked_folio() in ufs_alloc_lastblock()
ufs; Convert ufs_change_blocknr() to use folios
ufs: Remove ufs_get_locked_page()
buffer: Remove folio_create_empty_buffers()
fs/buffer.c | 68 +++++-----
fs/ext4/inode.c | 14 +-
fs/ext4/move_extent.c | 11 +-
fs/gfs2/aops.c | 2 +-
fs/gfs2/bmap.c | 48 ++++---
fs/gfs2/meta_io.c | 61 ++++-----
fs/gfs2/quota.c | 37 +++---
fs/mpage.c | 3 +-
fs/nilfs2/mdt.c | 66 +++++-----
fs/nilfs2/page.c | 76 +++++------
fs/nilfs2/page.h | 11 --
fs/nilfs2/segment.c | 7 +-
fs/ntfs/aops.c | 255 +++++++++++++++++-------------------
fs/ntfs/file.c | 89 ++++++-------
fs/ntfs3/file.c | 31 ++---
fs/ocfs2/aops.c | 19 +--
fs/reiserfs/inode.c | 80 +++++------
fs/ufs/balloc.c | 20 ++-
fs/ufs/inode.c | 25 ++--
fs/ufs/util.c | 34 +++--
fs/ufs/util.h | 10 +-
include/linux/buffer_head.h | 28 +++-
mm/util.c | 1 +
23 files changed, 481 insertions(+), 515 deletions(-)
--
2.40.1
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 01/27] buffer: Return bool from grow_dev_folio()
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-17 19:41 ` Ryusuke Konishi
2023-10-16 20:10 ` [PATCH v2 02/27] buffer: Make folio_create_empty_buffers() return a buffer_head Matthew Wilcox (Oracle)
` (25 subsequent siblings)
26 siblings, 1 reply; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Rename grow_dev_page() to grow_dev_folio() and make it return a bool.
Document what that bool means; it's more subtle than it first appears.
Also rename the 'failed' label to 'unlock' beacuse it's not exactly
'failed'. It just hasn't succeeded.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 39 ++++++++++++++++++++++-----------------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index b33cc74e9649..dec41d84044b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1024,24 +1024,26 @@ static sector_t folio_init_buffers(struct folio *folio,
}
/*
- * Create the page-cache page that contains the requested block.
+ * Create the page-cache folio that contains the requested block.
*
* This is used purely for blockdev mappings.
+ *
+ * Returns false if we have a 'permanent' failure. Returns true if
+ * we succeeded, or the caller should retry.
*/
-static int
-grow_dev_page(struct block_device *bdev, sector_t block,
+static bool grow_dev_folio(struct block_device *bdev, sector_t block,
pgoff_t index, int size, int sizebits, gfp_t gfp)
{
struct inode *inode = bdev->bd_inode;
struct folio *folio;
struct buffer_head *bh;
sector_t end_block;
- int ret = 0;
+ bool ret;
folio = __filemap_get_folio(inode->i_mapping, index,
FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
if (IS_ERR(folio))
- return PTR_ERR(folio);
+ return false;
bh = folio_buffers(folio);
if (bh) {
@@ -1050,14 +1052,17 @@ grow_dev_page(struct block_device *bdev, sector_t block,
(sector_t)index << sizebits, size);
goto done;
}
+
+ /* Caller should retry if this call fails */
+ ret = true;
if (!try_to_free_buffers(folio))
- goto failed;
+ goto unlock;
}
- ret = -ENOMEM;
+ ret = false;
bh = folio_alloc_buffers(folio, size, gfp | __GFP_ACCOUNT);
if (!bh)
- goto failed;
+ goto unlock;
/*
* Link the folio to the buffers and initialise them. Take the
@@ -1070,19 +1075,19 @@ grow_dev_page(struct block_device *bdev, sector_t block,
(sector_t)index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
done:
- ret = (block < end_block) ? 1 : -ENXIO;
-failed:
+ ret = block < end_block;
+unlock:
folio_unlock(folio);
folio_put(folio);
return ret;
}
/*
- * Create buffers for the specified block device block's page. If
- * that page was dirty, the buffers are set dirty also.
+ * Create buffers for the specified block device block's folio. If
+ * that folio was dirty, the buffers are set dirty also.
*/
-static int
-grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
+static bool grow_buffers(struct block_device *bdev, sector_t block,
+ int size, gfp_t gfp)
{
pgoff_t index;
int sizebits;
@@ -1099,11 +1104,11 @@ grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
"device %pg\n",
__func__, (unsigned long long)block,
bdev);
- return -EIO;
+ return false;
}
- /* Create a page with the proper size buffers.. */
- return grow_dev_page(bdev, block, index, size, sizebits, gfp);
+ /* Create a folio with the proper size buffers.. */
+ return grow_dev_folio(bdev, block, index, size, sizebits, gfp);
}
static struct buffer_head *
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 02/27] buffer: Make folio_create_empty_buffers() return a buffer_head
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 01/27] buffer: Return bool from grow_dev_folio() Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 03/27] mpage: Convert map_buffer_to_folio() to folio_create_empty_buffers() Matthew Wilcox (Oracle)
` (24 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Almost all callers want to know the first BH that was allocated
for this folio. We already have that handy, so return it.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
---
fs/buffer.c | 24 +++++++++++++-----------
include/linux/buffer_head.h | 4 ++--
2 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index dec41d84044b..81cdf36e5196 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1646,8 +1646,8 @@ EXPORT_SYMBOL(block_invalidate_folio);
* block_dirty_folio() via private_lock. try_to_free_buffers
* is already excluded via the folio lock.
*/
-void folio_create_empty_buffers(struct folio *folio, unsigned long blocksize,
- unsigned long b_state)
+struct buffer_head *folio_create_empty_buffers(struct folio *folio,
+ unsigned long blocksize, unsigned long b_state)
{
struct buffer_head *bh, *head, *tail;
gfp_t gfp = GFP_NOFS | __GFP_ACCOUNT | __GFP_NOFAIL;
@@ -1674,6 +1674,8 @@ void folio_create_empty_buffers(struct folio *folio, unsigned long blocksize,
}
folio_attach_private(folio, head);
spin_unlock(&folio->mapping->private_lock);
+
+ return head;
}
EXPORT_SYMBOL(folio_create_empty_buffers);
@@ -1775,13 +1777,15 @@ static struct buffer_head *folio_create_buffers(struct folio *folio,
struct inode *inode,
unsigned int b_state)
{
+ struct buffer_head *bh;
+
BUG_ON(!folio_test_locked(folio));
- if (!folio_buffers(folio))
- folio_create_empty_buffers(folio,
- 1 << READ_ONCE(inode->i_blkbits),
- b_state);
- return folio_buffers(folio);
+ bh = folio_buffers(folio);
+ if (!bh)
+ bh = folio_create_empty_buffers(folio,
+ 1 << READ_ONCE(inode->i_blkbits), b_state);
+ return bh;
}
/*
@@ -2681,10 +2685,8 @@ int block_truncate_page(struct address_space *mapping,
return PTR_ERR(folio);
bh = folio_buffers(folio);
- if (!bh) {
- folio_create_empty_buffers(folio, blocksize, 0);
- bh = folio_buffers(folio);
- }
+ if (!bh)
+ bh = folio_create_empty_buffers(folio, blocksize, 0);
/* Find the buffer that contains "offset" */
offset = offset_in_folio(folio, from);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 3dc4720e4773..1001244a8941 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -203,8 +203,8 @@ struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
bool retry);
void create_empty_buffers(struct page *, unsigned long,
unsigned long b_state);
-void folio_create_empty_buffers(struct folio *folio, unsigned long blocksize,
- unsigned long b_state);
+struct buffer_head *folio_create_empty_buffers(struct folio *folio,
+ unsigned long blocksize, unsigned long b_state);
void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
void end_buffer_async_write(struct buffer_head *bh, int uptodate);
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 03/27] mpage: Convert map_buffer_to_folio() to folio_create_empty_buffers()
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 01/27] buffer: Return bool from grow_dev_folio() Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 02/27] buffer: Make folio_create_empty_buffers() return a buffer_head Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 04/27] ext4: Convert to folio_create_empty_buffers Matthew Wilcox (Oracle)
` (23 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Saves a folio->page->folio conversion.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
---
fs/mpage.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fs/mpage.c b/fs/mpage.c
index 242e213ee064..964a6efe594d 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -119,8 +119,7 @@ static void map_buffer_to_folio(struct folio *folio, struct buffer_head *bh,
folio_mark_uptodate(folio);
return;
}
- create_empty_buffers(&folio->page, i_blocksize(inode), 0);
- head = folio_buffers(folio);
+ head = folio_create_empty_buffers(folio, i_blocksize(inode), 0);
}
page_bh = head;
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 04/27] ext4: Convert to folio_create_empty_buffers
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (2 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 03/27] mpage: Convert map_buffer_to_folio() to folio_create_empty_buffers() Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 05/27] buffer: Add get_nth_bh() Matthew Wilcox (Oracle)
` (22 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Remove an unnecessary folio->page->folio conversion and take advantage
of the new return value from folio_create_empty_buffers().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
---
fs/ext4/inode.c | 14 +++++---------
fs/ext4/move_extent.c | 11 +++++------
2 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a6838f54ae91..31c8f2641870 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1032,10 +1032,8 @@ static int ext4_block_write_begin(struct folio *folio, loff_t pos, unsigned len,
BUG_ON(from > to);
head = folio_buffers(folio);
- if (!head) {
- create_empty_buffers(&folio->page, blocksize, 0);
- head = folio_buffers(folio);
- }
+ if (!head)
+ head = folio_create_empty_buffers(folio, blocksize, 0);
bbits = ilog2(blocksize);
block = (sector_t)folio->index << (PAGE_SHIFT - bbits);
@@ -1165,7 +1163,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
* starting the handle.
*/
if (!folio_buffers(folio))
- create_empty_buffers(&folio->page, inode->i_sb->s_blocksize, 0);
+ folio_create_empty_buffers(folio, inode->i_sb->s_blocksize, 0);
folio_unlock(folio);
@@ -3655,10 +3653,8 @@ static int __ext4_block_zero_page_range(handle_t *handle,
iblock = index << (PAGE_SHIFT - inode->i_sb->s_blocksize_bits);
bh = folio_buffers(folio);
- if (!bh) {
- create_empty_buffers(&folio->page, blocksize, 0);
- bh = folio_buffers(folio);
- }
+ if (!bh)
+ bh = folio_create_empty_buffers(folio, blocksize, 0);
/* Find the buffer that contains "offset" */
pos = blocksize;
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 18a9e7c47975..7fe448fb948b 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -183,10 +183,8 @@ mext_page_mkuptodate(struct folio *folio, unsigned from, unsigned to)
blocksize = i_blocksize(inode);
head = folio_buffers(folio);
- if (!head) {
- create_empty_buffers(&folio->page, blocksize, 0);
- head = folio_buffers(folio);
- }
+ if (!head)
+ head = folio_create_empty_buffers(folio, blocksize, 0);
block = (sector_t)folio->index << (PAGE_SHIFT - inode->i_blkbits);
for (bh = head, block_start = 0; bh != head || !block_start;
@@ -380,9 +378,10 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
}
/* Perform all necessary steps similar write_begin()/write_end()
* but keeping in mind that i_size will not change */
- if (!folio_buffers(folio[0]))
- create_empty_buffers(&folio[0]->page, 1 << orig_inode->i_blkbits, 0);
bh = folio_buffers(folio[0]);
+ if (!bh)
+ bh = folio_create_empty_buffers(folio[0],
+ 1 << orig_inode->i_blkbits, 0);
for (i = 0; i < data_offset_in_page; i++)
bh = bh->b_this_page;
for (i = 0; i < block_len_in_page; i++) {
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 05/27] buffer: Add get_nth_bh()
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (3 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 04/27] ext4: Convert to folio_create_empty_buffers Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 06/27] gfs2: Convert inode unstuffing to use a folio Matthew Wilcox (Oracle)
` (21 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
Extract this useful helper from nilfs_page_get_nth_block()
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/page.h | 7 +------
include/linux/buffer_head.h | 22 ++++++++++++++++++++++
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h
index 21ddcdd4d63e..344d71942d36 100644
--- a/fs/nilfs2/page.h
+++ b/fs/nilfs2/page.h
@@ -55,12 +55,7 @@ unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
static inline struct buffer_head *
nilfs_page_get_nth_block(struct page *page, unsigned int count)
{
- struct buffer_head *bh = page_buffers(page);
-
- while (count-- > 0)
- bh = bh->b_this_page;
- get_bh(bh);
- return bh;
+ return get_nth_bh(page_buffers(page), count);
}
#endif /* _NILFS_PAGE_H */
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 1001244a8941..3d85a0cf0ca5 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -457,6 +457,28 @@ __bread(struct block_device *bdev, sector_t block, unsigned size)
return __bread_gfp(bdev, block, size, __GFP_MOVABLE);
}
+/**
+ * get_nth_bh - Get a reference on the n'th buffer after this one.
+ * @bh: The buffer to start counting from.
+ * @count: How many buffers to skip.
+ *
+ * This is primarily useful for finding the nth buffer in a folio; in
+ * that case you pass the head buffer and the byte offset in the folio
+ * divided by the block size. It can be used for other purposes, but
+ * it will wrap at the end of the folio rather than returning NULL or
+ * proceeding to the next folio for you.
+ *
+ * Return: The requested buffer with an elevated refcount.
+ */
+static inline __must_check
+struct buffer_head *get_nth_bh(struct buffer_head *bh, unsigned int count)
+{
+ while (count--)
+ bh = bh->b_this_page;
+ get_bh(bh);
+ return bh;
+}
+
bool block_dirty_folio(struct address_space *mapping, struct folio *folio);
#ifdef CONFIG_BUFFER_HEAD
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 06/27] gfs2: Convert inode unstuffing to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (4 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 05/27] buffer: Add get_nth_bh() Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 07/27] gfs2: Convert gfs2_getbuf() to folios Matthew Wilcox (Oracle)
` (20 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Andreas Gruenbacher
Use the folio APIs, removing numerous hidden calls to compound_head().
Also remove the stale comment about the page being looked up if it's NULL.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/gfs2/bmap.c | 48 +++++++++++++++++++++++-------------------------
1 file changed, 23 insertions(+), 25 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index f1d92e4d1538..f7ea1af9d842 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -43,53 +43,51 @@ struct metapath {
static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length);
/**
- * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page
+ * gfs2_unstuffer_folio - unstuff a stuffed inode into a block cached by a folio
* @ip: the inode
* @dibh: the dinode buffer
* @block: the block number that was allocated
- * @page: The (optional) page. This is looked up if @page is NULL
+ * @folio: The folio.
*
* Returns: errno
*/
-
-static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
- u64 block, struct page *page)
+static int gfs2_unstuffer_folio(struct gfs2_inode *ip, struct buffer_head *dibh,
+ u64 block, struct folio *folio)
{
struct inode *inode = &ip->i_inode;
- if (!PageUptodate(page)) {
- void *kaddr = kmap(page);
+ if (!folio_test_uptodate(folio)) {
+ void *kaddr = kmap_local_folio(folio, 0);
u64 dsize = i_size_read(inode);
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
- memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
- kunmap(page);
+ memset(kaddr + dsize, 0, folio_size(folio) - dsize);
+ kunmap_local(kaddr);
- SetPageUptodate(page);
+ folio_mark_uptodate(folio);
}
if (gfs2_is_jdata(ip)) {
- struct buffer_head *bh;
+ struct buffer_head *bh = folio_buffers(folio);
- if (!page_has_buffers(page))
- create_empty_buffers(page, BIT(inode->i_blkbits),
- BIT(BH_Uptodate));
+ if (!bh)
+ bh = folio_create_empty_buffers(folio,
+ BIT(inode->i_blkbits), BIT(BH_Uptodate));
- bh = page_buffers(page);
if (!buffer_mapped(bh))
map_bh(bh, inode->i_sb, block);
set_buffer_uptodate(bh);
gfs2_trans_add_data(ip->i_gl, bh);
} else {
- set_page_dirty(page);
+ folio_mark_dirty(folio);
gfs2_ordered_add_inode(ip);
}
return 0;
}
-static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct page *page)
+static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio)
{
struct buffer_head *bh, *dibh;
struct gfs2_dinode *di;
@@ -118,7 +116,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct page *page)
dibh, sizeof(struct gfs2_dinode));
brelse(bh);
} else {
- error = gfs2_unstuffer_page(ip, dibh, block, page);
+ error = gfs2_unstuffer_folio(ip, dibh, block, folio);
if (error)
goto out_brelse;
}
@@ -157,17 +155,17 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct page *page)
int gfs2_unstuff_dinode(struct gfs2_inode *ip)
{
struct inode *inode = &ip->i_inode;
- struct page *page;
+ struct folio *folio;
int error;
down_write(&ip->i_rw_mutex);
- page = grab_cache_page(inode->i_mapping, 0);
- error = -ENOMEM;
- if (!page)
+ folio = filemap_grab_folio(inode->i_mapping, 0);
+ error = PTR_ERR(folio);
+ if (IS_ERR(folio))
goto out;
- error = __gfs2_unstuff_inode(ip, page);
- unlock_page(page);
- put_page(page);
+ error = __gfs2_unstuff_inode(ip, folio);
+ folio_unlock(folio);
+ folio_put(folio);
out:
up_write(&ip->i_rw_mutex);
return error;
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 07/27] gfs2: Convert gfs2_getbuf() to folios
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (5 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 06/27] gfs2: Convert inode unstuffing to use a folio Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 08/27] gfs2: Convert gfs2_getjdatabuf to use a folio Matthew Wilcox (Oracle)
` (19 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Andreas Gruenbacher
Remove several folio->page->folio conversions. Also use __GFP_NOFAIL
instead of calling yield() and the new get_nth_bh().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/gfs2/meta_io.c | 39 +++++++++++++++++----------------------
1 file changed, 17 insertions(+), 22 deletions(-)
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 924361fa510b..f1fac1b45059 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -115,7 +115,7 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
{
struct address_space *mapping = gfs2_glock2aspace(gl);
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
unsigned int shift;
unsigned long index;
@@ -129,36 +129,31 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
bufnum = blkno - (index << shift); /* block buf index within page */
if (create) {
- for (;;) {
- page = grab_cache_page(mapping, index);
- if (page)
- break;
- yield();
- }
- if (!page_has_buffers(page))
- create_empty_buffers(page, sdp->sd_sb.sb_bsize, 0);
+ folio = __filemap_get_folio(mapping, index,
+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
+ mapping_gfp_mask(mapping) | __GFP_NOFAIL);
+ bh = folio_buffers(folio);
+ if (!bh)
+ bh = folio_create_empty_buffers(folio,
+ sdp->sd_sb.sb_bsize, 0);
} else {
- page = find_get_page_flags(mapping, index,
- FGP_LOCK|FGP_ACCESSED);
- if (!page)
+ folio = __filemap_get_folio(mapping, index,
+ FGP_LOCK | FGP_ACCESSED, 0);
+ if (IS_ERR(folio))
return NULL;
- if (!page_has_buffers(page)) {
- bh = NULL;
- goto out_unlock;
- }
+ bh = folio_buffers(folio);
}
- /* Locate header for our buffer within our page */
- for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page)
- /* Do nothing */;
- get_bh(bh);
+ if (!bh)
+ goto out_unlock;
+ bh = get_nth_bh(bh, bufnum);
if (!buffer_mapped(bh))
map_bh(bh, sdp->sd_vfs, blkno);
out_unlock:
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return bh;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 08/27] gfs2: Convert gfs2_getjdatabuf to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (6 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 07/27] gfs2: Convert gfs2_getbuf() to folios Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 09/27] gfs2: Convert gfs2_write_buf_to_page() " Matthew Wilcox (Oracle)
` (18 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Andreas Gruenbacher
Use the folio APIs, saving four hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/gfs2/meta_io.c | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index f1fac1b45059..f6d40d51f5ed 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -400,26 +400,20 @@ static struct buffer_head *gfs2_getjdatabuf(struct gfs2_inode *ip, u64 blkno)
{
struct address_space *mapping = ip->i_inode.i_mapping;
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
unsigned int shift = PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift;
unsigned long index = blkno >> shift; /* convert block to page */
unsigned int bufnum = blkno - (index << shift);
- page = find_get_page_flags(mapping, index, FGP_LOCK|FGP_ACCESSED);
- if (!page)
- return NULL;
- if (!page_has_buffers(page)) {
- unlock_page(page);
- put_page(page);
+ folio = __filemap_get_folio(mapping, index, FGP_LOCK | FGP_ACCESSED, 0);
+ if (IS_ERR(folio))
return NULL;
- }
- /* Locate header for our buffer within our page */
- for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page)
- /* Do nothing */;
- get_bh(bh);
- unlock_page(page);
- put_page(page);
+ bh = folio_buffers(folio);
+ if (bh)
+ bh = get_nth_bh(bh, bufnum);
+ folio_unlock(folio);
+ folio_put(folio);
return bh;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 09/27] gfs2: Convert gfs2_write_buf_to_page() to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (7 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 08/27] gfs2: Convert gfs2_getjdatabuf to use a folio Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 10/27] nilfs2: Convert nilfs_mdt_freeze_buffer " Matthew Wilcox (Oracle)
` (17 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Andreas Gruenbacher
Remove several folio->page->folio conversions.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/gfs2/quota.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 6affd261a754..e45654ee4f4d 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -760,7 +760,7 @@ static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index,
struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
struct inode *inode = &ip->i_inode;
struct address_space *mapping = inode->i_mapping;
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
u64 blk;
unsigned bsize = sdp->sd_sb.sb_bsize, bnum = 0, boff = 0;
@@ -769,15 +769,15 @@ static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index,
blk = index << (PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift);
boff = off % bsize;
- page = grab_cache_page(mapping, index);
- if (!page)
- return -ENOMEM;
- if (!page_has_buffers(page))
- create_empty_buffers(page, bsize, 0);
+ folio = filemap_grab_folio(mapping, index);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
+ bh = folio_buffers(folio);
+ if (!bh)
+ bh = folio_create_empty_buffers(folio, bsize, 0);
- bh = page_buffers(page);
- for(;;) {
- /* Find the beginning block within the page */
+ for (;;) {
+ /* Find the beginning block within the folio */
if (pg_off >= ((bnum * bsize) + bsize)) {
bh = bh->b_this_page;
bnum++;
@@ -790,9 +790,10 @@ static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index,
goto unlock_out;
/* If it's a newly allocated disk block, zero it */
if (buffer_new(bh))
- zero_user(page, bnum * bsize, bh->b_size);
+ folio_zero_range(folio, bnum * bsize,
+ bh->b_size);
}
- if (PageUptodate(page))
+ if (folio_test_uptodate(folio))
set_buffer_uptodate(bh);
if (bh_read(bh, REQ_META | REQ_PRIO) < 0)
goto unlock_out;
@@ -808,17 +809,17 @@ static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index,
break;
}
- /* Write to the page, now that we have setup the buffer(s) */
- memcpy_to_page(page, off, buf, bytes);
- flush_dcache_page(page);
- unlock_page(page);
- put_page(page);
+ /* Write to the folio, now that we have setup the buffer(s) */
+ memcpy_to_folio(folio, off, buf, bytes);
+ flush_dcache_folio(folio);
+ folio_unlock(folio);
+ folio_put(folio);
return 0;
unlock_out:
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return -EIO;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 10/27] nilfs2: Convert nilfs_mdt_freeze_buffer to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (8 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 09/27] gfs2: Convert gfs2_write_buf_to_page() " Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 11/27] nilfs2: Convert nilfs_grab_buffer() " Matthew Wilcox (Oracle)
` (16 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
Remove a number of folio->page->folio conversions.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/mdt.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 19c8158605ed..db2260d6e44d 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -560,17 +560,19 @@ int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh)
{
struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow;
struct buffer_head *bh_frozen;
- struct page *page;
+ struct folio *folio;
int blkbits = inode->i_blkbits;
- page = grab_cache_page(shadow->inode->i_mapping, bh->b_folio->index);
- if (!page)
- return -ENOMEM;
+ folio = filemap_grab_folio(shadow->inode->i_mapping,
+ bh->b_folio->index);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
- if (!page_has_buffers(page))
- create_empty_buffers(page, 1 << blkbits, 0);
+ bh_frozen = folio_buffers(folio);
+ if (!bh_frozen)
+ bh_frozen = folio_create_empty_buffers(folio, 1 << blkbits, 0);
- bh_frozen = nilfs_page_get_nth_block(page, bh_offset(bh) >> blkbits);
+ bh_frozen = get_nth_bh(bh_frozen, bh_offset(bh) >> blkbits);
if (!buffer_uptodate(bh_frozen))
nilfs_copy_buffer(bh_frozen, bh);
@@ -582,8 +584,8 @@ int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh)
brelse(bh_frozen); /* already frozen */
}
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return 0;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 11/27] nilfs2: Convert nilfs_grab_buffer() to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (9 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 10/27] nilfs2: Convert nilfs_mdt_freeze_buffer " Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 12/27] nilfs2: Convert nilfs_copy_page() to nilfs_copy_folio() Matthew Wilcox (Oracle)
` (15 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
Remove a number of folio->page->folio conversions.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/page.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index b4e54d079b7d..1c075bd906c9 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -25,19 +25,19 @@
(BIT(BH_Uptodate) | BIT(BH_Mapped) | BIT(BH_NILFS_Node) | \
BIT(BH_NILFS_Volatile) | BIT(BH_NILFS_Checked))
-static struct buffer_head *
-__nilfs_get_page_block(struct page *page, unsigned long block, pgoff_t index,
- int blkbits, unsigned long b_state)
+static struct buffer_head *__nilfs_get_folio_block(struct folio *folio,
+ unsigned long block, pgoff_t index, int blkbits,
+ unsigned long b_state)
{
unsigned long first_block;
- struct buffer_head *bh;
+ struct buffer_head *bh = folio_buffers(folio);
- if (!page_has_buffers(page))
- create_empty_buffers(page, 1 << blkbits, b_state);
+ if (!bh)
+ bh = folio_create_empty_buffers(folio, 1 << blkbits, b_state);
first_block = (unsigned long)index << (PAGE_SHIFT - blkbits);
- bh = nilfs_page_get_nth_block(page, block - first_block);
+ bh = get_nth_bh(bh, block - first_block);
touch_buffer(bh);
wait_on_buffer(bh);
@@ -51,17 +51,17 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,
{
int blkbits = inode->i_blkbits;
pgoff_t index = blkoff >> (PAGE_SHIFT - blkbits);
- struct page *page;
+ struct folio *folio;
struct buffer_head *bh;
- page = grab_cache_page(mapping, index);
- if (unlikely(!page))
+ folio = filemap_grab_folio(mapping, index);
+ if (IS_ERR(folio))
return NULL;
- bh = __nilfs_get_page_block(page, blkoff, index, blkbits, b_state);
+ bh = __nilfs_get_folio_block(folio, blkoff, index, blkbits, b_state);
if (unlikely(!bh)) {
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return NULL;
}
return bh;
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 12/27] nilfs2: Convert nilfs_copy_page() to nilfs_copy_folio()
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (10 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 11/27] nilfs2: Convert nilfs_grab_buffer() " Matthew Wilcox (Oracle)
@ 2023-10-16 20:10 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 13/27] nilfs2: Convert nilfs_mdt_forget_block() to use a folio Matthew Wilcox (Oracle)
` (14 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
Both callers already have a folio, so pass it in and use it directly.
Removes a lot of hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/page.c | 50 +++++++++++++++++++++++++-----------------------
mm/util.c | 1 +
2 files changed, 27 insertions(+), 24 deletions(-)
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 1c075bd906c9..696215d899bf 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -184,30 +184,32 @@ void nilfs_page_bug(struct page *page)
}
/**
- * nilfs_copy_page -- copy the page with buffers
- * @dst: destination page
- * @src: source page
- * @copy_dirty: flag whether to copy dirty states on the page's buffer heads.
+ * nilfs_copy_folio -- copy the folio with buffers
+ * @dst: destination folio
+ * @src: source folio
+ * @copy_dirty: flag whether to copy dirty states on the folio's buffer heads.
*
- * This function is for both data pages and btnode pages. The dirty flag
- * should be treated by caller. The page must not be under i/o.
- * Both src and dst page must be locked
+ * This function is for both data folios and btnode folios. The dirty flag
+ * should be treated by caller. The folio must not be under i/o.
+ * Both src and dst folio must be locked
*/
-static void nilfs_copy_page(struct page *dst, struct page *src, int copy_dirty)
+static void nilfs_copy_folio(struct folio *dst, struct folio *src,
+ bool copy_dirty)
{
struct buffer_head *dbh, *dbufs, *sbh;
unsigned long mask = NILFS_BUFFER_INHERENT_BITS;
- BUG_ON(PageWriteback(dst));
+ BUG_ON(folio_test_writeback(dst));
- sbh = page_buffers(src);
- if (!page_has_buffers(dst))
- create_empty_buffers(dst, sbh->b_size, 0);
+ sbh = folio_buffers(src);
+ dbh = folio_buffers(dst);
+ if (!dbh)
+ dbh = folio_create_empty_buffers(dst, sbh->b_size, 0);
if (copy_dirty)
mask |= BIT(BH_Dirty);
- dbh = dbufs = page_buffers(dst);
+ dbufs = dbh;
do {
lock_buffer(sbh);
lock_buffer(dbh);
@@ -218,16 +220,16 @@ static void nilfs_copy_page(struct page *dst, struct page *src, int copy_dirty)
dbh = dbh->b_this_page;
} while (dbh != dbufs);
- copy_highpage(dst, src);
+ folio_copy(dst, src);
- if (PageUptodate(src) && !PageUptodate(dst))
- SetPageUptodate(dst);
- else if (!PageUptodate(src) && PageUptodate(dst))
- ClearPageUptodate(dst);
- if (PageMappedToDisk(src) && !PageMappedToDisk(dst))
- SetPageMappedToDisk(dst);
- else if (!PageMappedToDisk(src) && PageMappedToDisk(dst))
- ClearPageMappedToDisk(dst);
+ if (folio_test_uptodate(src) && !folio_test_uptodate(dst))
+ folio_mark_uptodate(dst);
+ else if (!folio_test_uptodate(src) && folio_test_uptodate(dst))
+ folio_clear_uptodate(dst);
+ if (folio_test_mappedtodisk(src) && !folio_test_mappedtodisk(dst))
+ folio_set_mappedtodisk(dst);
+ else if (!folio_test_mappedtodisk(src) && folio_test_mappedtodisk(dst))
+ folio_clear_mappedtodisk(dst);
do {
unlock_buffer(sbh);
@@ -269,7 +271,7 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,
NILFS_PAGE_BUG(&folio->page,
"found empty page in dat page cache");
- nilfs_copy_page(&dfolio->page, &folio->page, 1);
+ nilfs_copy_folio(dfolio, folio, true);
filemap_dirty_folio(folio_mapping(dfolio), dfolio);
folio_unlock(dfolio);
@@ -314,7 +316,7 @@ void nilfs_copy_back_pages(struct address_space *dmap,
if (!IS_ERR(dfolio)) {
/* overwrite existing folio in the destination cache */
WARN_ON(folio_test_dirty(dfolio));
- nilfs_copy_page(&dfolio->page, &folio->page, 0);
+ nilfs_copy_folio(dfolio, folio, false);
folio_unlock(dfolio);
folio_put(dfolio);
/* Do we not need to remove folio from smap here? */
diff --git a/mm/util.c b/mm/util.c
index 6eddd891198e..aa01f6ea5a75 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -799,6 +799,7 @@ void folio_copy(struct folio *dst, struct folio *src)
cond_resched();
}
}
+EXPORT_SYMBOL(folio_copy);
int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS;
int sysctl_overcommit_ratio __read_mostly = 50;
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 13/27] nilfs2: Convert nilfs_mdt_forget_block() to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (11 preceding siblings ...)
2023-10-16 20:10 ` [PATCH v2 12/27] nilfs2: Convert nilfs_copy_page() to nilfs_copy_folio() Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 14/27] nilfs2: Convert nilfs_mdt_get_frozen_buffer " Matthew Wilcox (Oracle)
` (13 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
Remove a number of folio->page->folio conversions.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/mdt.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index db2260d6e44d..11b7cf4acc92 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -356,30 +356,28 @@ int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)
*/
int nilfs_mdt_forget_block(struct inode *inode, unsigned long block)
{
- pgoff_t index = (pgoff_t)block >>
- (PAGE_SHIFT - inode->i_blkbits);
- struct page *page;
- unsigned long first_block;
+ pgoff_t index = block >> (PAGE_SHIFT - inode->i_blkbits);
+ struct folio *folio;
+ struct buffer_head *bh;
int ret = 0;
int still_dirty;
- page = find_lock_page(inode->i_mapping, index);
- if (!page)
+ folio = filemap_lock_folio(inode->i_mapping, index);
+ if (IS_ERR(folio))
return -ENOENT;
- wait_on_page_writeback(page);
+ folio_wait_writeback(folio);
- first_block = (unsigned long)index <<
- (PAGE_SHIFT - inode->i_blkbits);
- if (page_has_buffers(page)) {
- struct buffer_head *bh;
-
- bh = nilfs_page_get_nth_block(page, block - first_block);
+ bh = folio_buffers(folio);
+ if (bh) {
+ unsigned long first_block = index <<
+ (PAGE_SHIFT - inode->i_blkbits);
+ bh = get_nth_bh(bh, block - first_block);
nilfs_forget_buffer(bh);
}
- still_dirty = PageDirty(page);
- unlock_page(page);
- put_page(page);
+ still_dirty = folio_test_dirty(folio);
+ folio_unlock(folio);
+ folio_put(folio);
if (still_dirty ||
invalidate_inode_pages2_range(inode->i_mapping, index, index) != 0)
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 14/27] nilfs2: Convert nilfs_mdt_get_frozen_buffer to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (12 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 13/27] nilfs2: Convert nilfs_mdt_forget_block() to use a folio Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 15/27] nilfs2: Remove nilfs_page_get_nth_block Matthew Wilcox (Oracle)
` (12 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
Remove a number of folio->page->folio conversions.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/mdt.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 11b7cf4acc92..7b754e6494d7 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -592,17 +592,19 @@ nilfs_mdt_get_frozen_buffer(struct inode *inode, struct buffer_head *bh)
{
struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow;
struct buffer_head *bh_frozen = NULL;
- struct page *page;
+ struct folio *folio;
int n;
- page = find_lock_page(shadow->inode->i_mapping, bh->b_folio->index);
- if (page) {
- if (page_has_buffers(page)) {
+ folio = filemap_lock_folio(shadow->inode->i_mapping,
+ bh->b_folio->index);
+ if (!IS_ERR(folio)) {
+ bh_frozen = folio_buffers(folio);
+ if (bh_frozen) {
n = bh_offset(bh) >> inode->i_blkbits;
- bh_frozen = nilfs_page_get_nth_block(page, n);
+ bh_frozen = get_nth_bh(bh_frozen, n);
}
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
}
return bh_frozen;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 15/27] nilfs2: Remove nilfs_page_get_nth_block
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (13 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 14/27] nilfs2: Convert nilfs_mdt_get_frozen_buffer " Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 16/27] nilfs2: Convert nilfs_lookup_dirty_data_buffers to use folio_create_empty_buffers Matthew Wilcox (Oracle)
` (11 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
All users have now been converted to get_nth_block().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/page.h | 6 ------
1 file changed, 6 deletions(-)
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h
index 344d71942d36..d249ea1cefff 100644
--- a/fs/nilfs2/page.h
+++ b/fs/nilfs2/page.h
@@ -52,10 +52,4 @@ unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
#define NILFS_PAGE_BUG(page, m, a...) \
do { nilfs_page_bug(page); BUG(); } while (0)
-static inline struct buffer_head *
-nilfs_page_get_nth_block(struct page *page, unsigned int count)
-{
- return get_nth_bh(page_buffers(page), count);
-}
-
#endif /* _NILFS_PAGE_H */
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 16/27] nilfs2: Convert nilfs_lookup_dirty_data_buffers to use folio_create_empty_buffers
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (14 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 15/27] nilfs2: Remove nilfs_page_get_nth_block Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 17/27] ntfs: Convert ntfs_read_block() to use a folio Matthew Wilcox (Oracle)
` (10 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav,
Ryusuke Konishi
This function was already using a folio, so this update to the new API
removes a single folio->page->folio conversion.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/segment.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 7ec16879756e..94388fe83cf8 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -731,10 +731,9 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode,
continue;
}
head = folio_buffers(folio);
- if (!head) {
- create_empty_buffers(&folio->page, i_blocksize(inode), 0);
- head = folio_buffers(folio);
- }
+ if (!head)
+ head = folio_create_empty_buffers(folio,
+ i_blocksize(inode), 0);
folio_unlock(folio);
bh = head;
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 17/27] ntfs: Convert ntfs_read_block() to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (15 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 16/27] nilfs2: Convert nilfs_lookup_dirty_data_buffers to use folio_create_empty_buffers Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 18/27] ntfs: Convert ntfs_writepage " Matthew Wilcox (Oracle)
` (9 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
The caller already has the folio, so pass it in and use the folio API
throughout saving five hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ntfs/aops.c | 44 +++++++++++++++++++-------------------------
1 file changed, 19 insertions(+), 25 deletions(-)
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 4e158bce4192..d66a9f5ffde9 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -145,13 +145,12 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
}
/**
- * ntfs_read_block - fill a @page of an address space with data
- * @page: page cache page to fill with data
+ * ntfs_read_block - fill a @folio of an address space with data
+ * @folio: page cache folio to fill with data
*
- * Fill the page @page of the address space belonging to the @page->host inode.
* We read each buffer asynchronously and when all buffers are read in, our io
* completion handler ntfs_end_buffer_read_async(), if required, automatically
- * applies the mst fixups to the page before finally marking it uptodate and
+ * applies the mst fixups to the folio before finally marking it uptodate and
* unlocking it.
*
* We only enforce allocated_size limit because i_size is checked for in
@@ -161,7 +160,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
*
* Contains an adapted version of fs/buffer.c::block_read_full_folio().
*/
-static int ntfs_read_block(struct page *page)
+static int ntfs_read_block(struct folio *folio)
{
loff_t i_size;
VCN vcn;
@@ -178,7 +177,7 @@ static int ntfs_read_block(struct page *page)
int i, nr;
unsigned char blocksize_bits;
- vi = page->mapping->host;
+ vi = folio->mapping->host;
ni = NTFS_I(vi);
vol = ni->vol;
@@ -188,15 +187,10 @@ static int ntfs_read_block(struct page *page)
blocksize = vol->sb->s_blocksize;
blocksize_bits = vol->sb->s_blocksize_bits;
- if (!page_has_buffers(page)) {
- create_empty_buffers(page, blocksize, 0);
- if (unlikely(!page_has_buffers(page))) {
- unlock_page(page);
- return -ENOMEM;
- }
- }
- bh = head = page_buffers(page);
- BUG_ON(!bh);
+ head = folio_buffers(folio);
+ if (!head)
+ head = folio_create_empty_buffers(folio, blocksize, 0);
+ bh = head;
/*
* We may be racing with truncate. To avoid some of the problems we
@@ -205,11 +199,11 @@ static int ntfs_read_block(struct page *page)
* may leave some buffers unmapped which are now allocated. This is
* not a problem since these buffers will just get mapped when a write
* occurs. In case of a shrinking truncate, we will detect this later
- * on due to the runlist being incomplete and if the page is being
+ * on due to the runlist being incomplete and if the folio is being
* fully truncated, truncate will throw it away as soon as we unlock
* it so no need to worry what we do with it.
*/
- iblock = (s64)page->index << (PAGE_SHIFT - blocksize_bits);
+ iblock = (s64)folio->index << (PAGE_SHIFT - blocksize_bits);
read_lock_irqsave(&ni->size_lock, flags);
lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits;
init_size = ni->initialized_size;
@@ -221,7 +215,7 @@ static int ntfs_read_block(struct page *page)
}
zblock = (init_size + blocksize - 1) >> blocksize_bits;
- /* Loop through all the buffers in the page. */
+ /* Loop through all the buffers in the folio. */
rl = NULL;
nr = i = 0;
do {
@@ -299,7 +293,7 @@ static int ntfs_read_block(struct page *page)
if (!err)
err = -EIO;
bh->b_blocknr = -1;
- SetPageError(page);
+ folio_set_error(folio);
ntfs_error(vol->sb, "Failed to read from inode 0x%lx, "
"attribute type 0x%x, vcn 0x%llx, "
"offset 0x%x because its location on "
@@ -312,13 +306,13 @@ static int ntfs_read_block(struct page *page)
/*
* Either iblock was outside lblock limits or
* ntfs_rl_vcn_to_lcn() returned error. Just zero that portion
- * of the page and set the buffer uptodate.
+ * of the folio and set the buffer uptodate.
*/
handle_hole:
bh->b_blocknr = -1UL;
clear_buffer_mapped(bh);
handle_zblock:
- zero_user(page, i * blocksize, blocksize);
+ folio_zero_range(folio, i * blocksize, blocksize);
if (likely(!err))
set_buffer_uptodate(bh);
} while (i++, iblock++, (bh = bh->b_this_page) != head);
@@ -349,11 +343,11 @@ static int ntfs_read_block(struct page *page)
return 0;
}
/* No i/o was scheduled on any of the buffers. */
- if (likely(!PageError(page)))
- SetPageUptodate(page);
+ if (likely(!folio_test_error(folio)))
+ folio_mark_uptodate(folio);
else /* Signal synchronous i/o error. */
nr = -EIO;
- unlock_page(page);
+ folio_unlock(folio);
return nr;
}
@@ -433,7 +427,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
/* NInoNonResident() == NInoIndexAllocPresent() */
if (NInoNonResident(ni)) {
/* Normal, non-resident data stream. */
- return ntfs_read_block(page);
+ return ntfs_read_block(folio);
}
/*
* Attribute is resident, implying it is not compressed or encrypted.
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 18/27] ntfs: Convert ntfs_writepage to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (16 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 17/27] ntfs: Convert ntfs_read_block() to use a folio Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 19/27] ntfs: Convert ntfs_prepare_pages_for_non_resident_write() to folios Matthew Wilcox (Oracle)
` (8 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
use folio APIs throughout. Saves many hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ntfs/aops.c | 211 +++++++++++++++++++++++--------------------------
1 file changed, 100 insertions(+), 111 deletions(-)
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index d66a9f5ffde9..c4426992a2ee 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -501,28 +501,29 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
#ifdef NTFS_RW
/**
- * ntfs_write_block - write a @page to the backing store
- * @page: page cache page to write out
+ * ntfs_write_block - write a @folio to the backing store
+ * @folio: page cache folio to write out
* @wbc: writeback control structure
*
- * This function is for writing pages belonging to non-resident, non-mst
+ * This function is for writing folios belonging to non-resident, non-mst
* protected attributes to their backing store.
*
- * For a page with buffers, map and write the dirty buffers asynchronously
- * under page writeback. For a page without buffers, create buffers for the
- * page, then proceed as above.
+ * For a folio with buffers, map and write the dirty buffers asynchronously
+ * under folio writeback. For a folio without buffers, create buffers for the
+ * folio, then proceed as above.
*
- * If a page doesn't have buffers the page dirty state is definitive. If a page
- * does have buffers, the page dirty state is just a hint, and the buffer dirty
- * state is definitive. (A hint which has rules: dirty buffers against a clean
- * page is illegal. Other combinations are legal and need to be handled. In
- * particular a dirty page containing clean buffers for example.)
+ * If a folio doesn't have buffers the folio dirty state is definitive. If
+ * a folio does have buffers, the folio dirty state is just a hint,
+ * and the buffer dirty state is definitive. (A hint which has rules:
+ * dirty buffers against a clean folio is illegal. Other combinations are
+ * legal and need to be handled. In particular a dirty folio containing
+ * clean buffers for example.)
*
* Return 0 on success and -errno on error.
*
* Based on ntfs_read_block() and __block_write_full_folio().
*/
-static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
+static int ntfs_write_block(struct folio *folio, struct writeback_control *wbc)
{
VCN vcn;
LCN lcn;
@@ -540,41 +541,29 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
bool need_end_writeback;
unsigned char blocksize_bits;
- vi = page->mapping->host;
+ vi = folio->mapping->host;
ni = NTFS_I(vi);
vol = ni->vol;
ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
- "0x%lx.", ni->mft_no, ni->type, page->index);
+ "0x%lx.", ni->mft_no, ni->type, folio->index);
BUG_ON(!NInoNonResident(ni));
BUG_ON(NInoMstProtected(ni));
blocksize = vol->sb->s_blocksize;
blocksize_bits = vol->sb->s_blocksize_bits;
- if (!page_has_buffers(page)) {
- BUG_ON(!PageUptodate(page));
- create_empty_buffers(page, blocksize,
+ head = folio_buffers(folio);
+ if (!head) {
+ BUG_ON(!folio_test_uptodate(folio));
+ head = folio_create_empty_buffers(folio, blocksize,
(1 << BH_Uptodate) | (1 << BH_Dirty));
- if (unlikely(!page_has_buffers(page))) {
- ntfs_warning(vol->sb, "Error allocating page "
- "buffers. Redirtying page so we try "
- "again later.");
- /*
- * Put the page back on mapping->dirty_pages, but leave
- * its buffers' dirty state as-is.
- */
- redirty_page_for_writepage(wbc, page);
- unlock_page(page);
- return 0;
- }
}
- bh = head = page_buffers(page);
- BUG_ON(!bh);
+ bh = head;
/* NOTE: Different naming scheme to ntfs_read_block()! */
- /* The first block in the page. */
- block = (s64)page->index << (PAGE_SHIFT - blocksize_bits);
+ /* The first block in the folio. */
+ block = (s64)folio->index << (PAGE_SHIFT - blocksize_bits);
read_lock_irqsave(&ni->size_lock, flags);
i_size = i_size_read(vi);
@@ -591,14 +580,14 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
* 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.
*/
/*
- * Loop through all the buffers in the page, mapping all the dirty
+ * Loop through all the buffers in the folio, mapping all the dirty
* buffers to disk addresses and handling any aliases from the
* underlying block device's mapping.
*/
@@ -610,13 +599,13 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
if (unlikely(block >= dblock)) {
/*
* 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. The contents of such buffers
* were zeroed by ntfs_writepage().
*
* FIXME: What about the small race window where
* ntfs_writepage() has not done any clearing because
- * the page was within i_size but before we get here,
+ * the folio was within i_size but before we get here,
* vmtruncate() modifies i_size?
*/
clear_buffer_dirty(bh);
@@ -632,38 +621,38 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
if (unlikely((block >= iblock) &&
(initialized_size < i_size))) {
/*
- * If this page is fully outside initialized
- * size, zero out all pages between the current
- * initialized size and the current page. Just
+ * If this folio is fully outside initialized
+ * size, zero out all folios between the current
+ * initialized size and the current folio. Just
* use ntfs_read_folio() to do the zeroing
* transparently.
*/
if (block > iblock) {
// TODO:
- // For each page do:
- // - read_cache_page()
- // Again for each page do:
- // - wait_on_page_locked()
- // - Check (PageUptodate(page) &&
- // !PageError(page))
+ // For each folio do:
+ // - read_cache_folio()
+ // Again for each folio do:
+ // - wait_on_folio_locked()
+ // - Check (folio_test_uptodate(folio) &&
+ // !folio_test_error(folio))
// Update initialized size in the attribute and
// in the inode.
- // Again, for each page do:
+ // Again, for each folio do:
// block_dirty_folio();
- // put_page()
+ // folio_put()
// We don't need to wait on the writes.
// Update iblock.
}
/*
- * The current page straddles initialized size. Zero
+ * The current folio straddles initialized size. Zero
* all non-uptodate buffers and set them uptodate (and
* dirty?). Note, there aren't any non-uptodate buffers
- * if the page is uptodate.
- * FIXME: For an uptodate page, the buffers may need to
+ * if the folio is uptodate.
+ * FIXME: For an uptodate folio, the buffers may need to
* be written out because they were not initialized on
* disk before.
*/
- if (!PageUptodate(page)) {
+ if (!folio_test_uptodate(folio)) {
// TODO:
// Zero any non-uptodate buffers up to i_size.
// Set them uptodate and dirty.
@@ -721,14 +710,14 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
unsigned long *bpos, *bend;
/* Check if the buffer is zero. */
- kaddr = kmap_atomic(page);
- bpos = (unsigned long *)(kaddr + bh_offset(bh));
- bend = (unsigned long *)((u8*)bpos + blocksize);
+ kaddr = kmap_local_folio(folio, bh_offset(bh));
+ bpos = (unsigned long *)kaddr;
+ bend = (unsigned long *)(kaddr + blocksize);
do {
if (unlikely(*bpos))
break;
} while (likely(++bpos < bend));
- kunmap_atomic(kaddr);
+ kunmap_local(kaddr);
if (bpos == bend) {
/*
* Buffer is zero and sparse, no need to write
@@ -768,7 +757,7 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
if (err == -ENOENT || lcn == LCN_ENOENT) {
bh->b_blocknr = -1;
clear_buffer_dirty(bh);
- zero_user(page, bh_offset(bh), blocksize);
+ folio_zero_range(folio, bh_offset(bh), blocksize);
set_buffer_uptodate(bh);
err = 0;
continue;
@@ -795,7 +784,7 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
bh = head;
/* Just an optimization, so ->read_folio() is not called later. */
- if (unlikely(!PageUptodate(page))) {
+ if (unlikely(!folio_test_uptodate(folio))) {
int uptodate = 1;
do {
if (!buffer_uptodate(bh)) {
@@ -805,7 +794,7 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
}
} while ((bh = bh->b_this_page) != head);
if (uptodate)
- SetPageUptodate(page);
+ folio_mark_uptodate(folio);
}
/* Setup all mapped, dirty buffers for async write i/o. */
@@ -820,7 +809,7 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
} else if (unlikely(err)) {
/*
* For the error case. The buffer may have been set
- * dirty during attachment to a dirty page.
+ * dirty during attachment to a dirty folio.
*/
if (err != -ENOMEM)
clear_buffer_dirty(bh);
@@ -833,20 +822,20 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
err = 0;
else if (err == -ENOMEM) {
ntfs_warning(vol->sb, "Error allocating memory. "
- "Redirtying page so we try again "
+ "Redirtying folio so we try again "
"later.");
/*
- * Put the page back on mapping->dirty_pages, but
+ * Put the folio back on mapping->dirty_pages, but
* leave its buffer's dirty state as-is.
*/
- redirty_page_for_writepage(wbc, page);
+ folio_redirty_for_writepage(wbc, folio);
err = 0;
} else
- SetPageError(page);
+ folio_set_error(folio);
}
- BUG_ON(PageWriteback(page));
- set_page_writeback(page); /* Keeps try_to_free_buffers() away. */
+ BUG_ON(folio_test_writeback(folio));
+ folio_start_writeback(folio); /* Keeps try_to_free_buffers() away. */
/* Submit the prepared buffers for i/o. */
need_end_writeback = true;
@@ -858,11 +847,11 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
}
bh = next;
} while (bh != head);
- unlock_page(page);
+ folio_unlock(folio);
- /* If no i/o was started, need to end_page_writeback(). */
+ /* If no i/o was started, need to end writeback here. */
if (unlikely(need_end_writeback))
- end_page_writeback(page);
+ folio_end_writeback(folio);
ntfs_debug("Done.");
return err;
@@ -1331,8 +1320,9 @@ static int ntfs_write_mst_block(struct page *page,
*/
static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
{
+ struct folio *folio = page_folio(page);
loff_t i_size;
- struct inode *vi = page->mapping->host;
+ struct inode *vi = folio->mapping->host;
ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi);
char *addr;
ntfs_attr_search_ctx *ctx = NULL;
@@ -1341,14 +1331,13 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
int err;
retry_writepage:
- BUG_ON(!PageLocked(page));
+ BUG_ON(!folio_test_locked(folio));
i_size = i_size_read(vi);
- /* Is the page fully outside i_size? (truncate in progress) */
- if (unlikely(page->index >= (i_size + PAGE_SIZE - 1) >>
+ /* Is the folio fully outside i_size? (truncate in progress) */
+ if (unlikely(folio->index >= (i_size + PAGE_SIZE - 1) >>
PAGE_SHIFT)) {
- struct folio *folio = page_folio(page);
/*
- * The page may have dirty, unmapped buffers. Make them
+ * The folio may have dirty, unmapped buffers. Make them
* freeable here, so the page does not leak.
*/
block_invalidate_folio(folio, 0, folio_size(folio));
@@ -1367,7 +1356,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
if (ni->type != AT_INDEX_ALLOCATION) {
/* If file is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
- unlock_page(page);
+ folio_unlock(folio);
BUG_ON(ni->type != AT_DATA);
ntfs_debug("Denying write access to encrypted file.");
return -EACCES;
@@ -1378,14 +1367,14 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
BUG_ON(ni->name_len);
// TODO: Implement and replace this with
// return ntfs_write_compressed_block(page);
- unlock_page(page);
+ folio_unlock(folio);
ntfs_error(vi->i_sb, "Writing to compressed files is "
"not supported yet. Sorry.");
return -EOPNOTSUPP;
}
// TODO: Implement and remove this check.
if (NInoNonResident(ni) && NInoSparse(ni)) {
- unlock_page(page);
+ folio_unlock(folio);
ntfs_error(vi->i_sb, "Writing to sparse files is not "
"supported yet. Sorry.");
return -EOPNOTSUPP;
@@ -1394,34 +1383,34 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
/* NInoNonResident() == NInoIndexAllocPresent() */
if (NInoNonResident(ni)) {
/* We have to zero every time due to mmap-at-end-of-file. */
- if (page->index >= (i_size >> PAGE_SHIFT)) {
- /* The page straddles i_size. */
- unsigned int ofs = i_size & ~PAGE_MASK;
- zero_user_segment(page, ofs, PAGE_SIZE);
+ if (folio->index >= (i_size >> PAGE_SHIFT)) {
+ /* The folio straddles i_size. */
+ unsigned int ofs = i_size & (folio_size(folio) - 1);
+ folio_zero_segment(folio, ofs, folio_size(folio));
}
/* Handle mst protected attributes. */
if (NInoMstProtected(ni))
return ntfs_write_mst_block(page, wbc);
/* Normal, non-resident data stream. */
- return ntfs_write_block(page, wbc);
+ return ntfs_write_block(folio, wbc);
}
/*
* Attribute is resident, implying it is not compressed, encrypted, or
* mst protected. This also means the attribute is smaller than an mft
- * record and hence smaller than a page, so can simply return error on
- * any pages with index above 0. Note the attribute can actually be
+ * record and hence smaller than a folio, so can simply return error on
+ * any folios with index above 0. Note the attribute can actually be
* marked compressed but if it is resident the actual data is not
* compressed so we are ok to ignore the compressed flag here.
*/
- BUG_ON(page_has_buffers(page));
- BUG_ON(!PageUptodate(page));
- if (unlikely(page->index > 0)) {
- ntfs_error(vi->i_sb, "BUG()! page->index (0x%lx) > 0. "
- "Aborting write.", page->index);
- BUG_ON(PageWriteback(page));
- set_page_writeback(page);
- unlock_page(page);
- end_page_writeback(page);
+ BUG_ON(folio_buffers(folio));
+ BUG_ON(!folio_test_uptodate(folio));
+ if (unlikely(folio->index > 0)) {
+ ntfs_error(vi->i_sb, "BUG()! folio->index (0x%lx) > 0. "
+ "Aborting write.", folio->index);
+ BUG_ON(folio_test_writeback(folio));
+ folio_start_writeback(folio);
+ folio_unlock(folio);
+ folio_end_writeback(folio);
return -EIO;
}
if (!NInoAttr(ni))
@@ -1454,12 +1443,12 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
if (unlikely(err))
goto err_out;
/*
- * Keep the VM happy. This must be done otherwise the radix-tree tag
- * PAGECACHE_TAG_DIRTY remains set even though the page is clean.
+ * Keep the VM happy. This must be done otherwise
+ * PAGECACHE_TAG_DIRTY remains set even though the folio is clean.
*/
- BUG_ON(PageWriteback(page));
- set_page_writeback(page);
- unlock_page(page);
+ BUG_ON(folio_test_writeback(folio));
+ folio_start_writeback(folio);
+ folio_unlock(folio);
attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
i_size = i_size_read(vi);
if (unlikely(attr_len > i_size)) {
@@ -1474,18 +1463,18 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
/* Shrinking cannot fail. */
BUG_ON(err);
}
- addr = kmap_atomic(page);
- /* Copy the data from the page to the mft record. */
+ addr = kmap_local_folio(folio, 0);
+ /* Copy the data from the folio to the mft record. */
memcpy((u8*)ctx->attr +
le16_to_cpu(ctx->attr->data.resident.value_offset),
addr, attr_len);
- /* Zero out of bounds area in the page cache page. */
- memset(addr + attr_len, 0, PAGE_SIZE - attr_len);
- kunmap_atomic(addr);
- flush_dcache_page(page);
+ /* Zero out of bounds area in the page cache folio. */
+ memset(addr + attr_len, 0, folio_size(folio) - attr_len);
+ kunmap_local(addr);
+ flush_dcache_folio(folio);
flush_dcache_mft_record_page(ctx->ntfs_ino);
- /* We are done with the page. */
- end_page_writeback(page);
+ /* We are done with the folio. */
+ folio_end_writeback(folio);
/* Finally, mark the mft record dirty, so it gets written back. */
mark_mft_record_dirty(ctx->ntfs_ino);
ntfs_attr_put_search_ctx(ctx);
@@ -1496,18 +1485,18 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
ntfs_warning(vi->i_sb, "Error allocating memory. Redirtying "
"page so we try again later.");
/*
- * Put the page back on mapping->dirty_pages, but leave its
+ * Put the folio back on mapping->dirty_pages, but leave its
* buffers' dirty state as-is.
*/
- redirty_page_for_writepage(wbc, page);
+ folio_redirty_for_writepage(wbc, folio);
err = 0;
} else {
ntfs_error(vi->i_sb, "Resident attribute write failed with "
"error %i.", err);
- SetPageError(page);
+ folio_set_error(folio);
NVolSetErrors(ni->vol);
}
- unlock_page(page);
+ folio_unlock(folio);
if (ctx)
ntfs_attr_put_search_ctx(ctx);
if (m)
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 19/27] ntfs: Convert ntfs_prepare_pages_for_non_resident_write() to folios
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (17 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 18/27] ntfs: Convert ntfs_writepage " Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 20/27] ntfs3: Convert ntfs_zero_range() to use a folio Matthew Wilcox (Oracle)
` (7 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Convert each element of the pages array to a folio before using it.
This in no way renders the function large-folio safe, but it does remove
a lot of hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ntfs/file.c | 89 +++++++++++++++++++++++---------------------------
1 file changed, 41 insertions(+), 48 deletions(-)
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index cbc545999cfe..099141d20db6 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -567,7 +567,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
LCN lcn;
s64 bh_pos, vcn_len, end, initialized_size;
sector_t lcn_block;
- struct page *page;
+ struct folio *folio;
struct inode *vi;
ntfs_inode *ni, *base_ni = NULL;
ntfs_volume *vol;
@@ -601,20 +601,6 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
(long long)pos, bytes);
blocksize = vol->sb->s_blocksize;
blocksize_bits = vol->sb->s_blocksize_bits;
- u = 0;
- do {
- page = pages[u];
- BUG_ON(!page);
- /*
- * create_empty_buffers() will create uptodate/dirty buffers if
- * the page is uptodate/dirty.
- */
- if (!page_has_buffers(page)) {
- create_empty_buffers(page, blocksize, 0);
- if (unlikely(!page_has_buffers(page)))
- return -ENOMEM;
- }
- } while (++u < nr_pages);
rl_write_locked = false;
rl = NULL;
err = 0;
@@ -626,14 +612,21 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
end = pos + bytes;
cend = (end + vol->cluster_size - 1) >> vol->cluster_size_bits;
/*
- * Loop over each page and for each page over each buffer. Use goto to
+ * Loop over each buffer in each folio. Use goto to
* reduce indentation.
*/
u = 0;
-do_next_page:
- page = pages[u];
- bh_pos = (s64)page->index << PAGE_SHIFT;
- bh = head = page_buffers(page);
+do_next_folio:
+ folio = page_folio(pages[u]);
+ bh_pos = folio_pos(folio);
+ head = folio_buffers(folio);
+ if (!head)
+ /*
+ * create_empty_buffers() will create uptodate/dirty
+ * buffers if the folio is uptodate/dirty.
+ */
+ head = folio_create_empty_buffers(folio, blocksize, 0);
+ bh = head;
do {
VCN cdelta;
s64 bh_end;
@@ -653,15 +646,15 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
if (buffer_uptodate(bh))
continue;
/*
- * The buffer is not uptodate. If the page is uptodate
+ * The buffer is not uptodate. If the folio is uptodate
* set the buffer uptodate and otherwise ignore it.
*/
- if (PageUptodate(page)) {
+ if (folio_test_uptodate(folio)) {
set_buffer_uptodate(bh);
continue;
}
/*
- * Neither the page nor the buffer are uptodate. If
+ * Neither the folio nor the buffer are uptodate. If
* the buffer is only partially being written to, we
* need to read it in before the write, i.e. now.
*/
@@ -679,7 +672,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
ntfs_submit_bh_for_read(bh);
*wait_bh++ = bh;
} else {
- zero_user(page, bh_offset(bh),
+ folio_zero_range(folio, bh_offset(bh),
blocksize);
set_buffer_uptodate(bh);
}
@@ -706,7 +699,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
(bh_cofs >> blocksize_bits);
set_buffer_mapped(bh);
/*
- * If the page is uptodate so is the buffer. If the
+ * If the folio is uptodate so is the buffer. If the
* buffer is fully outside the write, we ignore it if
* it was already allocated and we mark it dirty so it
* gets written out if we allocated it. On the other
@@ -714,7 +707,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
* marking it dirty we set buffer_new so we can do
* error recovery.
*/
- if (PageUptodate(page)) {
+ if (folio_test_uptodate(folio)) {
if (!buffer_uptodate(bh))
set_buffer_uptodate(bh);
if (unlikely(was_hole)) {
@@ -754,7 +747,8 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
ntfs_submit_bh_for_read(bh);
*wait_bh++ = bh;
} else {
- zero_user(page, bh_offset(bh),
+ folio_zero_range(folio,
+ bh_offset(bh),
blocksize);
set_buffer_uptodate(bh);
}
@@ -773,7 +767,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
*/
if (bh_end <= pos || bh_pos >= end) {
if (!buffer_uptodate(bh)) {
- zero_user(page, bh_offset(bh),
+ folio_zero_range(folio, bh_offset(bh),
blocksize);
set_buffer_uptodate(bh);
}
@@ -786,7 +780,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
u8 *kaddr;
unsigned pofs;
- kaddr = kmap_atomic(page);
+ kaddr = kmap_local_folio(folio, 0);
if (bh_pos < pos) {
pofs = bh_pos & ~PAGE_MASK;
memset(kaddr + pofs, 0, pos - bh_pos);
@@ -795,8 +789,8 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
pofs = end & ~PAGE_MASK;
memset(kaddr + pofs, 0, bh_end - end);
}
- kunmap_atomic(kaddr);
- flush_dcache_page(page);
+ kunmap_local(kaddr);
+ flush_dcache_folio(folio);
}
continue;
}
@@ -809,11 +803,12 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
initialized_size = ni->allocated_size;
read_unlock_irqrestore(&ni->size_lock, flags);
if (bh_pos > initialized_size) {
- if (PageUptodate(page)) {
+ if (folio_test_uptodate(folio)) {
if (!buffer_uptodate(bh))
set_buffer_uptodate(bh);
} else if (!buffer_uptodate(bh)) {
- zero_user(page, bh_offset(bh), blocksize);
+ folio_zero_range(folio, bh_offset(bh),
+ blocksize);
set_buffer_uptodate(bh);
}
continue;
@@ -927,17 +922,17 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
bh->b_blocknr = -1;
/*
* If the buffer is uptodate we skip it. If it
- * is not but the page is uptodate, we can set
- * the buffer uptodate. If the page is not
+ * is not but the folio is uptodate, we can set
+ * the buffer uptodate. If the folio is not
* uptodate, we can clear the buffer and set it
* uptodate. Whether this is worthwhile is
* debatable and this could be removed.
*/
- if (PageUptodate(page)) {
+ if (folio_test_uptodate(folio)) {
if (!buffer_uptodate(bh))
set_buffer_uptodate(bh);
} else if (!buffer_uptodate(bh)) {
- zero_user(page, bh_offset(bh),
+ folio_zero_range(folio, bh_offset(bh),
blocksize);
set_buffer_uptodate(bh);
}
@@ -1167,7 +1162,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
} while (bh_pos += blocksize, (bh = bh->b_this_page) != head);
/* If there are no errors, do the next page. */
if (likely(!err && ++u < nr_pages))
- goto do_next_page;
+ goto do_next_folio;
/* If there are no errors, release the runlist lock if we took it. */
if (likely(!err)) {
if (unlikely(rl_write_locked)) {
@@ -1185,9 +1180,8 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
bh = *--wait_bh;
wait_on_buffer(bh);
if (likely(buffer_uptodate(bh))) {
- page = bh->b_page;
- bh_pos = ((s64)page->index << PAGE_SHIFT) +
- bh_offset(bh);
+ folio = bh->b_folio;
+ bh_pos = folio_pos(folio) + bh_offset(bh);
/*
* If the buffer overflows the initialized size, need
* to zero the overflowing region.
@@ -1197,7 +1191,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
if (likely(bh_pos < initialized_size))
ofs = initialized_size - bh_pos;
- zero_user_segment(page, bh_offset(bh) + ofs,
+ folio_zero_segment(folio, bh_offset(bh) + ofs,
blocksize);
}
} else /* if (unlikely(!buffer_uptodate(bh))) */
@@ -1324,21 +1318,20 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
u = 0;
end = bh_cpos << vol->cluster_size_bits;
do {
- page = pages[u];
- bh = head = page_buffers(page);
+ folio = page_folio(pages[u]);
+ bh = head = folio_buffers(folio);
do {
if (u == nr_pages &&
- ((s64)page->index << PAGE_SHIFT) +
- bh_offset(bh) >= end)
+ folio_pos(folio) + bh_offset(bh) >= end)
break;
if (!buffer_new(bh))
continue;
clear_buffer_new(bh);
if (!buffer_uptodate(bh)) {
- if (PageUptodate(page))
+ if (folio_test_uptodate(folio))
set_buffer_uptodate(bh);
else {
- zero_user(page, bh_offset(bh),
+ folio_zero_range(folio, bh_offset(bh),
blocksize);
set_buffer_uptodate(bh);
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 20/27] ntfs3: Convert ntfs_zero_range() to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (18 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 19/27] ntfs: Convert ntfs_prepare_pages_for_non_resident_write() to folios Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 21/27] ocfs2: Convert ocfs2_map_page_blocks " Matthew Wilcox (Oracle)
` (6 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Use the folio API throughout, saving six hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ntfs3/file.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index ad4a70b5d432..135af3340a19 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -187,7 +187,7 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
struct buffer_head *head, *bh;
u32 bh_next, bh_off, to;
sector_t iblock;
- struct page *page;
+ struct folio *folio;
for (; idx < idx_end; idx += 1, from = 0) {
page_off = (loff_t)idx << PAGE_SHIFT;
@@ -195,16 +195,17 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
PAGE_SIZE;
iblock = page_off >> inode->i_blkbits;
- page = find_or_create_page(mapping, idx,
- mapping_gfp_constraint(mapping,
- ~__GFP_FS));
- if (!page)
- return -ENOMEM;
+ folio = __filemap_get_folio(mapping, idx,
+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
+ mapping_gfp_constraint(mapping, ~__GFP_FS));
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
- if (!page_has_buffers(page))
- create_empty_buffers(page, blocksize, 0);
+ head = folio_buffers(folio);
+ if (!head)
+ head = folio_create_empty_buffers(folio, blocksize, 0);
- bh = head = page_buffers(page);
+ bh = head;
bh_off = 0;
do {
bh_next = bh_off + blocksize;
@@ -220,14 +221,14 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
}
/* 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)) {
err = bh_read(bh, 0);
if (err < 0) {
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
goto out;
}
}
@@ -237,10 +238,10 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
} while (bh_off = bh_next, iblock += 1,
head != (bh = bh->b_this_page));
- zero_user_segment(page, from, to);
+ folio_zero_segment(folio, from, to);
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
cond_resched();
}
out:
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 21/27] ocfs2: Convert ocfs2_map_page_blocks to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (19 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 20/27] ntfs3: Convert ntfs_zero_range() to use a folio Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 22/27] reiserfs: Convert writepage " Matthew Wilcox (Oracle)
` (5 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Convert the page argument to a folio and then use the folio APIs
throughout. Replaces three hidden calls to compound_head() with one
explicit one.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ocfs2/aops.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 6ab03494fc6e..001ad1d288ec 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -568,10 +568,10 @@ static void ocfs2_clear_page_regions(struct page *page,
* read-in the blocks at the tail of our file. Avoid reading them by
* testing i_size against each block offset.
*/
-static int ocfs2_should_read_blk(struct inode *inode, struct page *page,
+static int ocfs2_should_read_blk(struct inode *inode, struct folio *folio,
unsigned int block_start)
{
- u64 offset = page_offset(page) + block_start;
+ u64 offset = folio_pos(folio) + block_start;
if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
return 1;
@@ -593,15 +593,16 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
struct inode *inode, unsigned int from,
unsigned int to, int new)
{
+ struct folio *folio = page_folio(page);
int ret = 0;
struct buffer_head *head, *bh, *wait[2], **wait_bh = wait;
unsigned int block_end, block_start;
unsigned int bsize = i_blocksize(inode);
- if (!page_has_buffers(page))
- create_empty_buffers(page, bsize, 0);
+ head = folio_buffers(folio);
+ if (!head)
+ head = folio_create_empty_buffers(folio, bsize, 0);
- head = page_buffers(page);
for (bh = head, block_start = 0; bh != head || !block_start;
bh = bh->b_this_page, block_start += bsize) {
block_end = block_start + bsize;
@@ -613,7 +614,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
* they may belong to unallocated clusters.
*/
if (block_start >= to || block_end <= from) {
- if (PageUptodate(page))
+ if (folio_test_uptodate(folio))
set_buffer_uptodate(bh);
continue;
}
@@ -630,11 +631,11 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
clean_bdev_bh_alias(bh);
}
- if (PageUptodate(page)) {
+ if (folio_test_uptodate(folio)) {
set_buffer_uptodate(bh);
} else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
!buffer_new(bh) &&
- ocfs2_should_read_blk(inode, page, block_start) &&
+ ocfs2_should_read_blk(inode, folio, block_start) &&
(block_start < from || block_end > to)) {
bh_read_nowait(bh, 0);
*wait_bh++=bh;
@@ -668,7 +669,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
if (block_start >= to)
break;
- zero_user(page, block_start, bh->b_size);
+ folio_zero_range(folio, block_start, bh->b_size);
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 22/27] reiserfs: Convert writepage to use a folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (20 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 21/27] ocfs2: Convert ocfs2_map_page_blocks " Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 23/27] ufs: Add ufs_get_locked_folio and ufs_put_locked_folio Matthew Wilcox (Oracle)
` (4 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Convert the incoming page to a folio and then use it throughout the
writeback path. This definitely isn't enough to support large folios, but
I don't expect reiserfs to gain support for those before it is removed.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/reiserfs/inode.c | 80 ++++++++++++++++++++++-----------------------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index c8572346556f..d7df556220a4 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2503,10 +2503,10 @@ static int map_block_for_writepage(struct inode *inode,
* 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,
+static int reiserfs_write_full_folio(struct folio *folio,
struct writeback_control *wbc)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = folio->mapping->host;
unsigned long end_index = inode->i_size >> PAGE_SHIFT;
int error = 0;
unsigned long block;
@@ -2514,7 +2514,7 @@ static int reiserfs_write_full_page(struct page *page,
struct buffer_head *head, *bh;
int partial = 0;
int nr = 0;
- int checked = PageChecked(page);
+ int checked = folio_test_checked(folio);
struct reiserfs_transaction_handle th;
struct super_block *s = inode->i_sb;
int bh_per_page = PAGE_SIZE / s->s_blocksize;
@@ -2522,47 +2522,46 @@ static int reiserfs_write_full_page(struct page *page,
/* no logging allowed when nonblocking or from PF_MEMALLOC */
if (checked && (current->flags & PF_MEMALLOC)) {
- redirty_page_for_writepage(wbc, page);
- unlock_page(page);
+ folio_redirty_for_writepage(wbc, folio);
+ folio_unlock(folio);
return 0;
}
/*
- * The page dirty bit is cleared before writepage is called, which
+ * The folio dirty bit is cleared before writepage is called, which
* means we have to tell create_empty_buffers to make dirty buffers
- * The page really should be up to date at this point, so tossing
+ * The folio really should be up to date at this point, so tossing
* in the BH_Uptodate is just a sanity check.
*/
- if (!page_has_buffers(page)) {
- create_empty_buffers(page, s->s_blocksize,
+ head = folio_buffers(folio);
+ if (!head)
+ head = folio_create_empty_buffers(folio, s->s_blocksize,
(1 << BH_Dirty) | (1 << BH_Uptodate));
- }
- head = page_buffers(page);
/*
- * last page in the file, zero out any contents past the
+ * last folio in the file, zero out any contents past the
* last byte in the file
*/
- if (page->index >= end_index) {
+ if (folio->index >= end_index) {
unsigned last_offset;
last_offset = inode->i_size & (PAGE_SIZE - 1);
- /* no file contents in this page */
- if (page->index >= end_index + 1 || !last_offset) {
- unlock_page(page);
+ /* no file contents in this folio */
+ if (folio->index >= end_index + 1 || !last_offset) {
+ folio_unlock(folio);
return 0;
}
- zero_user_segment(page, last_offset, PAGE_SIZE);
+ folio_zero_segment(folio, last_offset, folio_size(folio));
}
bh = head;
- block = page->index << (PAGE_SHIFT - s->s_blocksize_bits);
+ block = folio->index << (PAGE_SHIFT - s->s_blocksize_bits);
last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
/* first map all the buffers, logging any direct items we find */
do {
if (block > last_block) {
/*
* This can happen when the block size is less than
- * the page size. The corresponding bytes in the page
+ * the folio size. The corresponding bytes in the folio
* were zero filled above
*/
clear_buffer_dirty(bh);
@@ -2589,7 +2588,7 @@ static int reiserfs_write_full_page(struct page *page,
* blocks we're going to log
*/
if (checked) {
- ClearPageChecked(page);
+ folio_clear_checked(folio);
reiserfs_write_lock(s);
error = journal_begin(&th, s, bh_per_page + 1);
if (error) {
@@ -2598,7 +2597,7 @@ static int reiserfs_write_full_page(struct page *page,
}
reiserfs_update_inode_transaction(inode);
}
- /* now go through and lock any dirty buffers on the page */
+ /* now go through and lock any dirty buffers on the folio */
do {
get_bh(bh);
if (!buffer_mapped(bh))
@@ -2619,7 +2618,7 @@ static int reiserfs_write_full_page(struct page *page,
lock_buffer(bh);
} else {
if (!trylock_buffer(bh)) {
- redirty_page_for_writepage(wbc, page);
+ folio_redirty_for_writepage(wbc, folio);
continue;
}
}
@@ -2636,13 +2635,13 @@ static int reiserfs_write_full_page(struct page *page,
if (error)
goto fail;
}
- BUG_ON(PageWriteback(page));
- set_page_writeback(page);
- unlock_page(page);
+ BUG_ON(folio_test_writeback(folio));
+ folio_start_writeback(folio);
+ folio_unlock(folio);
/*
- * since any buffer might be the only dirty buffer on the page,
- * the first submit_bh can bring the page out of writeback.
+ * since any buffer might be the only dirty buffer on the folio,
+ * the first submit_bh can bring the folio out of writeback.
* be careful with the buffers.
*/
do {
@@ -2659,10 +2658,10 @@ static int reiserfs_write_full_page(struct page *page,
done:
if (nr == 0) {
/*
- * if this page only had a direct item, it is very possible for
+ * if this folio only had a direct item, it is very possible for
* no io to be required without there being an error. Or,
* someone else could have locked them and sent them down the
- * pipe without locking the page
+ * pipe without locking the folio
*/
bh = head;
do {
@@ -2673,18 +2672,18 @@ static int reiserfs_write_full_page(struct page *page,
bh = bh->b_this_page;
} while (bh != head);
if (!partial)
- SetPageUptodate(page);
- end_page_writeback(page);
+ folio_mark_uptodate(folio);
+ folio_end_writeback(folio);
}
return error;
fail:
/*
* catches various errors, we need to make sure any valid dirty blocks
- * get to the media. The page is currently locked and not marked for
+ * get to the media. The folio is currently locked and not marked for
* writeback
*/
- ClearPageUptodate(page);
+ folio_clear_uptodate(folio);
bh = head;
do {
get_bh(bh);
@@ -2694,16 +2693,16 @@ static int reiserfs_write_full_page(struct page *page,
} else {
/*
* clear any dirty bits that might have come from
- * getting attached to a dirty page
+ * getting attached to a dirty folio
*/
clear_buffer_dirty(bh);
}
bh = bh->b_this_page;
} while (bh != head);
- SetPageError(page);
- BUG_ON(PageWriteback(page));
- set_page_writeback(page);
- unlock_page(page);
+ folio_set_error(folio);
+ BUG_ON(folio_test_writeback(folio));
+ folio_start_writeback(folio);
+ folio_unlock(folio);
do {
struct buffer_head *next = bh->b_this_page;
if (buffer_async_write(bh)) {
@@ -2724,9 +2723,10 @@ static int reiserfs_read_folio(struct file *f, struct folio *folio)
static int reiserfs_writepage(struct page *page, struct writeback_control *wbc)
{
- struct inode *inode = page->mapping->host;
+ struct folio *folio = page_folio(page);
+ struct inode *inode = folio->mapping->host;
reiserfs_wait_on_write_block(inode->i_sb);
- return reiserfs_write_full_page(page, wbc);
+ return reiserfs_write_full_folio(folio, wbc);
}
static void reiserfs_truncate_failed_write(struct inode *inode)
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 23/27] ufs: Add ufs_get_locked_folio and ufs_put_locked_folio
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (21 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 22/27] reiserfs: Convert writepage " Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 24/27] ufs: Use ufs_get_locked_folio() in ufs_alloc_lastblock() Matthew Wilcox (Oracle)
` (3 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Convert the _page variants to call them. Saves a few hidden calls to
compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ufs/util.c | 43 +++++++++++++++++++++++++------------------
fs/ufs/util.h | 13 +++++++++----
2 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 08ddf41eaaad..151b400cb3b6 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -229,43 +229,50 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev
ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);
}
+struct page *ufs_get_locked_page(struct address_space *mapping, pgoff_t index)
+{
+ struct folio *folio = ufs_get_locked_folio(mapping, index);
+
+ if (folio)
+ return folio_file_page(folio, index);
+ return NULL;
+}
+
/**
- * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist
+ * ufs_get_locked_folio() - locate, pin and lock a pagecache folio, if not exist
* read it from disk.
* @mapping: the address_space to search
* @index: the page index
*
- * Locates the desired pagecache page, if not exist we'll read it,
+ * Locates the desired pagecache folio, if not exist we'll read it,
* locks it, increments its reference
* count and returns its address.
*
*/
-
-struct page *ufs_get_locked_page(struct address_space *mapping,
+struct folio *ufs_get_locked_folio(struct address_space *mapping,
pgoff_t index)
{
struct inode *inode = mapping->host;
- struct page *page = find_lock_page(mapping, index);
- if (!page) {
- page = read_mapping_page(mapping, index, NULL);
+ struct folio *folio = filemap_lock_folio(mapping, index);
+ if (!folio) {
+ folio = read_mapping_folio(mapping, index, NULL);
- if (IS_ERR(page)) {
- printk(KERN_ERR "ufs_change_blocknr: "
- "read_mapping_page error: ino %lu, index: %lu\n",
+ if (IS_ERR(folio)) {
+ printk(KERN_ERR "ufs_change_blocknr: read_mapping_folio error: ino %lu, index: %lu\n",
mapping->host->i_ino, index);
- return page;
+ return folio;
}
- lock_page(page);
+ folio_lock(folio);
- if (unlikely(page->mapping == NULL)) {
+ if (unlikely(folio->mapping == NULL)) {
/* Truncate got there first */
- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
return NULL;
}
}
- if (!page_has_buffers(page))
- create_empty_buffers(page, 1 << inode->i_blkbits, 0);
- return page;
+ if (!folio_buffers(folio))
+ folio_create_empty_buffers(folio, 1 << inode->i_blkbits, 0);
+ return folio;
}
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 89247193d96d..62542561d150 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -273,12 +273,17 @@ extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struc
extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned);
/* This functions works with cache pages*/
-extern struct page *ufs_get_locked_page(struct address_space *mapping,
- pgoff_t index);
+struct page *ufs_get_locked_page(struct address_space *mapping, pgoff_t index);
+struct folio *ufs_get_locked_folio(struct address_space *mapping, pgoff_t index);
+static inline void ufs_put_locked_folio(struct folio *folio)
+{
+ folio_unlock(folio);
+ folio_put(folio);
+}
+
static inline void ufs_put_locked_page(struct page *page)
{
- unlock_page(page);
- put_page(page);
+ ufs_put_locked_folio(page_folio(page));
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 24/27] ufs: Use ufs_get_locked_folio() in ufs_alloc_lastblock()
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (22 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 23/27] ufs: Add ufs_get_locked_folio and ufs_put_locked_folio Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 25/27] ufs; Convert ufs_change_blocknr() to use folios Matthew Wilcox (Oracle)
` (2 subsequent siblings)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Switch to the folio APIs, saving one folio->page->folio conversion.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ufs/inode.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 338e4b97312f..ebce93b08281 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -1063,7 +1063,7 @@ static int ufs_alloc_lastblock(struct inode *inode, loff_t size)
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
unsigned i, end;
sector_t lastfrag;
- struct page *lastpage;
+ struct folio *folio;
struct buffer_head *bh;
u64 phys64;
@@ -1074,18 +1074,17 @@ static int ufs_alloc_lastblock(struct inode *inode, loff_t size)
lastfrag--;
- lastpage = ufs_get_locked_page(mapping, lastfrag >>
+ folio = ufs_get_locked_folio(mapping, lastfrag >>
(PAGE_SHIFT - inode->i_blkbits));
- if (IS_ERR(lastpage)) {
- err = -EIO;
- goto out;
- }
-
- end = lastfrag & ((1 << (PAGE_SHIFT - inode->i_blkbits)) - 1);
- bh = page_buffers(lastpage);
- for (i = 0; i < end; ++i)
- bh = bh->b_this_page;
+ if (IS_ERR(folio)) {
+ err = -EIO;
+ goto out;
+ }
+ end = lastfrag & ((1 << (PAGE_SHIFT - inode->i_blkbits)) - 1);
+ bh = folio_buffers(folio);
+ for (i = 0; i < end; ++i)
+ bh = bh->b_this_page;
err = ufs_getfrag_block(inode, lastfrag, bh, 1);
@@ -1101,7 +1100,7 @@ static int ufs_alloc_lastblock(struct inode *inode, loff_t size)
*/
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
- set_page_dirty(lastpage);
+ folio_mark_dirty(folio);
}
if (lastfrag >= UFS_IND_FRAGMENT) {
@@ -1119,7 +1118,7 @@ static int ufs_alloc_lastblock(struct inode *inode, loff_t size)
}
}
out_unlock:
- ufs_put_locked_page(lastpage);
+ ufs_put_locked_folio(folio);
out:
return err;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 25/27] ufs; Convert ufs_change_blocknr() to use folios
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (23 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 24/27] ufs: Use ufs_get_locked_folio() in ufs_alloc_lastblock() Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 26/27] ufs: Remove ufs_get_locked_page() Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 27/27] buffer: Remove folio_create_empty_buffers() Matthew Wilcox (Oracle)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Convert the locked_page argument to a folio, then use folios throughout.
Saves three hidden calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ufs/balloc.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 2436e3f82147..53c11be2b2c1 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -240,6 +240,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
unsigned int count, sector_t oldb,
sector_t newb, struct page *locked_page)
{
+ struct folio *folio, *locked_folio = page_folio(locked_page);
const unsigned blks_per_page =
1 << (PAGE_SHIFT - inode->i_blkbits);
const unsigned mask = blks_per_page - 1;
@@ -247,42 +248,39 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
pgoff_t index, cur_index, last_index;
unsigned pos, j, lblock;
sector_t end, i;
- struct page *page;
struct buffer_head *head, *bh;
UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n",
inode->i_ino, count,
(unsigned long long)oldb, (unsigned long long)newb);
- BUG_ON(!locked_page);
- BUG_ON(!PageLocked(locked_page));
+ BUG_ON(!folio_test_locked(locked_folio));
- cur_index = locked_page->index;
+ cur_index = locked_folio->index;
end = count + beg;
last_index = end >> (PAGE_SHIFT - inode->i_blkbits);
for (i = beg; i < end; i = (i | mask) + 1) {
index = i >> (PAGE_SHIFT - inode->i_blkbits);
if (likely(cur_index != index)) {
- page = ufs_get_locked_page(mapping, index);
- if (!page)/* it was truncated */
+ folio = ufs_get_locked_folio(mapping, index);
+ if (!folio) /* it was truncated */
continue;
- if (IS_ERR(page)) {/* or EIO */
+ if (IS_ERR(folio)) {/* or EIO */
ufs_error(inode->i_sb, __func__,
"read of page %llu failed\n",
(unsigned long long)index);
continue;
}
} else
- page = locked_page;
+ folio = locked_folio;
- head = page_buffers(page);
+ head = folio_buffers(folio);
bh = head;
pos = i & mask;
for (j = 0; j < pos; ++j)
bh = bh->b_this_page;
-
if (unlikely(index == last_index))
lblock = end & mask;
else
@@ -313,7 +311,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
} while (bh != head);
if (likely(cur_index != index))
- ufs_put_locked_page(page);
+ ufs_put_locked_folio(folio);
}
UFSD("EXIT\n");
}
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 26/27] ufs: Remove ufs_get_locked_page()
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (24 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 25/27] ufs; Convert ufs_change_blocknr() to use folios Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 27/27] buffer: Remove folio_create_empty_buffers() Matthew Wilcox (Oracle)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
Both callers are now converted to ufs_get_locked_folio().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/ufs/util.c | 9 ---------
fs/ufs/util.h | 7 -------
2 files changed, 16 deletions(-)
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 151b400cb3b6..d32de30009a0 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -229,15 +229,6 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev
ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);
}
-struct page *ufs_get_locked_page(struct address_space *mapping, pgoff_t index)
-{
- struct folio *folio = ufs_get_locked_folio(mapping, index);
-
- if (folio)
- return folio_file_page(folio, index);
- return NULL;
-}
-
/**
* ufs_get_locked_folio() - locate, pin and lock a pagecache folio, if not exist
* read it from disk.
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 62542561d150..0ecd2ed792f5 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -273,7 +273,6 @@ extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struc
extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned);
/* This functions works with cache pages*/
-struct page *ufs_get_locked_page(struct address_space *mapping, pgoff_t index);
struct folio *ufs_get_locked_folio(struct address_space *mapping, pgoff_t index);
static inline void ufs_put_locked_folio(struct folio *folio)
{
@@ -281,12 +280,6 @@ static inline void ufs_put_locked_folio(struct folio *folio)
folio_put(folio);
}
-static inline void ufs_put_locked_page(struct page *page)
-{
- ufs_put_locked_folio(page_folio(page));
-}
-
-
/*
* macros and inline function to get important structures from ufs_sb_private_info
*/
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 27/27] buffer: Remove folio_create_empty_buffers()
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
` (25 preceding siblings ...)
2023-10-16 20:11 ` [PATCH v2 26/27] ufs: Remove ufs_get_locked_page() Matthew Wilcox (Oracle)
@ 2023-10-16 20:11 ` Matthew Wilcox (Oracle)
26 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox (Oracle) @ 2023-10-16 20:11 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev, ntfs3,
ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
With all users converted, remove the old create_empty_buffers() and
rename folio_create_empty_buffers() to create_empty_buffers().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/buffer.c | 13 +++----------
fs/ext4/inode.c | 6 +++---
fs/ext4/move_extent.c | 4 ++--
fs/gfs2/aops.c | 2 +-
fs/gfs2/bmap.c | 2 +-
fs/gfs2/meta_io.c | 2 +-
fs/gfs2/quota.c | 2 +-
fs/mpage.c | 2 +-
fs/nilfs2/mdt.c | 2 +-
fs/nilfs2/page.c | 4 ++--
fs/nilfs2/segment.c | 2 +-
fs/ntfs/aops.c | 4 ++--
fs/ntfs/file.c | 2 +-
fs/ntfs3/file.c | 2 +-
fs/ocfs2/aops.c | 2 +-
fs/reiserfs/inode.c | 2 +-
fs/ufs/util.c | 2 +-
include/linux/buffer_head.h | 4 +---
18 files changed, 25 insertions(+), 34 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 81cdf36e5196..bf76b7a27bfa 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1646,7 +1646,7 @@ EXPORT_SYMBOL(block_invalidate_folio);
* block_dirty_folio() via private_lock. try_to_free_buffers
* is already excluded via the folio lock.
*/
-struct buffer_head *folio_create_empty_buffers(struct folio *folio,
+struct buffer_head *create_empty_buffers(struct folio *folio,
unsigned long blocksize, unsigned long b_state)
{
struct buffer_head *bh, *head, *tail;
@@ -1677,13 +1677,6 @@ struct buffer_head *folio_create_empty_buffers(struct folio *folio,
return head;
}
-EXPORT_SYMBOL(folio_create_empty_buffers);
-
-void create_empty_buffers(struct page *page,
- unsigned long blocksize, unsigned long b_state)
-{
- folio_create_empty_buffers(page_folio(page), blocksize, b_state);
-}
EXPORT_SYMBOL(create_empty_buffers);
/**
@@ -1783,7 +1776,7 @@ static struct buffer_head *folio_create_buffers(struct folio *folio,
bh = folio_buffers(folio);
if (!bh)
- bh = folio_create_empty_buffers(folio,
+ bh = create_empty_buffers(folio,
1 << READ_ONCE(inode->i_blkbits), b_state);
return bh;
}
@@ -2686,7 +2679,7 @@ int block_truncate_page(struct address_space *mapping,
bh = folio_buffers(folio);
if (!bh)
- bh = folio_create_empty_buffers(folio, blocksize, 0);
+ bh = create_empty_buffers(folio, blocksize, 0);
/* Find the buffer that contains "offset" */
offset = offset_in_folio(folio, from);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 31c8f2641870..61277f7f8722 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1033,7 +1033,7 @@ static int ext4_block_write_begin(struct folio *folio, loff_t pos, unsigned len,
head = folio_buffers(folio);
if (!head)
- head = folio_create_empty_buffers(folio, blocksize, 0);
+ head = create_empty_buffers(folio, blocksize, 0);
bbits = ilog2(blocksize);
block = (sector_t)folio->index << (PAGE_SHIFT - bbits);
@@ -1163,7 +1163,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
* starting the handle.
*/
if (!folio_buffers(folio))
- folio_create_empty_buffers(folio, inode->i_sb->s_blocksize, 0);
+ create_empty_buffers(folio, inode->i_sb->s_blocksize, 0);
folio_unlock(folio);
@@ -3654,7 +3654,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
bh = folio_buffers(folio);
if (!bh)
- bh = folio_create_empty_buffers(folio, blocksize, 0);
+ bh = create_empty_buffers(folio, blocksize, 0);
/* Find the buffer that contains "offset" */
pos = blocksize;
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 7fe448fb948b..3aa57376d9c2 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -184,7 +184,7 @@ mext_page_mkuptodate(struct folio *folio, unsigned from, unsigned to)
blocksize = i_blocksize(inode);
head = folio_buffers(folio);
if (!head)
- head = folio_create_empty_buffers(folio, blocksize, 0);
+ head = create_empty_buffers(folio, blocksize, 0);
block = (sector_t)folio->index << (PAGE_SHIFT - inode->i_blkbits);
for (bh = head, block_start = 0; bh != head || !block_start;
@@ -380,7 +380,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
* but keeping in mind that i_size will not change */
bh = folio_buffers(folio[0]);
if (!bh)
- bh = folio_create_empty_buffers(folio[0],
+ bh = create_empty_buffers(folio[0],
1 << orig_inode->i_blkbits, 0);
for (i = 0; i < data_offset_in_page; i++)
bh = bh->b_this_page;
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 52fad5bcb047..74f3302348a5 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -130,7 +130,7 @@ static int __gfs2_jdata_write_folio(struct folio *folio,
if (folio_test_checked(folio)) {
folio_clear_checked(folio);
if (!folio_buffers(folio)) {
- folio_create_empty_buffers(folio,
+ create_empty_buffers(folio,
inode->i_sb->s_blocksize,
BIT(BH_Dirty)|BIT(BH_Uptodate));
}
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index f7ea1af9d842..398db80cb9c6 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -71,7 +71,7 @@ static int gfs2_unstuffer_folio(struct gfs2_inode *ip, struct buffer_head *dibh,
struct buffer_head *bh = folio_buffers(folio);
if (!bh)
- bh = folio_create_empty_buffers(folio,
+ bh = create_empty_buffers(folio,
BIT(inode->i_blkbits), BIT(BH_Uptodate));
if (!buffer_mapped(bh))
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index f6d40d51f5ed..25ceb0805df2 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -134,7 +134,7 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
mapping_gfp_mask(mapping) | __GFP_NOFAIL);
bh = folio_buffers(folio);
if (!bh)
- bh = folio_create_empty_buffers(folio,
+ bh = create_empty_buffers(folio,
sdp->sd_sb.sb_bsize, 0);
} else {
folio = __filemap_get_folio(mapping, index,
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index e45654ee4f4d..570a60aa3480 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -774,7 +774,7 @@ static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index,
return PTR_ERR(folio);
bh = folio_buffers(folio);
if (!bh)
- bh = folio_create_empty_buffers(folio, bsize, 0);
+ bh = create_empty_buffers(folio, bsize, 0);
for (;;) {
/* Find the beginning block within the folio */
diff --git a/fs/mpage.c b/fs/mpage.c
index 964a6efe594d..ffb064ed9d04 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -119,7 +119,7 @@ static void map_buffer_to_folio(struct folio *folio, struct buffer_head *bh,
folio_mark_uptodate(folio);
return;
}
- head = folio_create_empty_buffers(folio, i_blocksize(inode), 0);
+ head = create_empty_buffers(folio, i_blocksize(inode), 0);
}
page_bh = head;
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 7b754e6494d7..c97c77a39668 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -568,7 +568,7 @@ int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh)
bh_frozen = folio_buffers(folio);
if (!bh_frozen)
- bh_frozen = folio_create_empty_buffers(folio, 1 << blkbits, 0);
+ bh_frozen = create_empty_buffers(folio, 1 << blkbits, 0);
bh_frozen = get_nth_bh(bh_frozen, bh_offset(bh) >> blkbits);
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 696215d899bf..06b04758f289 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -34,7 +34,7 @@ static struct buffer_head *__nilfs_get_folio_block(struct folio *folio,
struct buffer_head *bh = folio_buffers(folio);
if (!bh)
- bh = folio_create_empty_buffers(folio, 1 << blkbits, b_state);
+ bh = create_empty_buffers(folio, 1 << blkbits, b_state);
first_block = (unsigned long)index << (PAGE_SHIFT - blkbits);
bh = get_nth_bh(bh, block - first_block);
@@ -204,7 +204,7 @@ static void nilfs_copy_folio(struct folio *dst, struct folio *src,
sbh = folio_buffers(src);
dbh = folio_buffers(dst);
if (!dbh)
- dbh = folio_create_empty_buffers(dst, sbh->b_size, 0);
+ dbh = create_empty_buffers(dst, sbh->b_size, 0);
if (copy_dirty)
mask |= BIT(BH_Dirty);
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 94388fe83cf8..55e31cc903d1 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -732,7 +732,7 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode,
}
head = folio_buffers(folio);
if (!head)
- head = folio_create_empty_buffers(folio,
+ head = create_empty_buffers(folio,
i_blocksize(inode), 0);
folio_unlock(folio);
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index c4426992a2ee..71e31e789b29 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -189,7 +189,7 @@ static int ntfs_read_block(struct folio *folio)
head = folio_buffers(folio);
if (!head)
- head = folio_create_empty_buffers(folio, blocksize, 0);
+ head = create_empty_buffers(folio, blocksize, 0);
bh = head;
/*
@@ -555,7 +555,7 @@ static int ntfs_write_block(struct folio *folio, struct writeback_control *wbc)
head = folio_buffers(folio);
if (!head) {
BUG_ON(!folio_test_uptodate(folio));
- head = folio_create_empty_buffers(folio, blocksize,
+ head = create_empty_buffers(folio, blocksize,
(1 << BH_Uptodate) | (1 << BH_Dirty));
}
bh = head;
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 099141d20db6..297c0b9db621 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -625,7 +625,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
* create_empty_buffers() will create uptodate/dirty
* buffers if the folio is uptodate/dirty.
*/
- head = folio_create_empty_buffers(folio, blocksize, 0);
+ head = create_empty_buffers(folio, blocksize, 0);
bh = head;
do {
VCN cdelta;
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index 135af3340a19..a5a30a24ce5d 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -203,7 +203,7 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
head = folio_buffers(folio);
if (!head)
- head = folio_create_empty_buffers(folio, blocksize, 0);
+ head = create_empty_buffers(folio, blocksize, 0);
bh = head;
bh_off = 0;
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 001ad1d288ec..ba790219d528 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -601,7 +601,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
head = folio_buffers(folio);
if (!head)
- head = folio_create_empty_buffers(folio, bsize, 0);
+ head = create_empty_buffers(folio, bsize, 0);
for (bh = head, block_start = 0; bh != head || !block_start;
bh = bh->b_this_page, block_start += bsize) {
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index d7df556220a4..1d825459ee6e 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2535,7 +2535,7 @@ static int reiserfs_write_full_folio(struct folio *folio,
*/
head = folio_buffers(folio);
if (!head)
- head = folio_create_empty_buffers(folio, s->s_blocksize,
+ head = create_empty_buffers(folio, s->s_blocksize,
(1 << BH_Dirty) | (1 << BH_Uptodate));
/*
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index d32de30009a0..13ba34e6d64f 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -264,6 +264,6 @@ struct folio *ufs_get_locked_folio(struct address_space *mapping,
}
}
if (!folio_buffers(folio))
- folio_create_empty_buffers(folio, 1 << inode->i_blkbits, 0);
+ create_empty_buffers(folio, 1 << inode->i_blkbits, 0);
return folio;
}
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 3d85a0cf0ca5..5f23ee599889 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -201,9 +201,7 @@ struct buffer_head *folio_alloc_buffers(struct folio *folio, unsigned long size,
gfp_t gfp);
struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
bool retry);
-void create_empty_buffers(struct page *, unsigned long,
- unsigned long b_state);
-struct buffer_head *folio_create_empty_buffers(struct folio *folio,
+struct buffer_head *create_empty_buffers(struct folio *folio,
unsigned long blocksize, unsigned long b_state);
void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
--
2.40.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v2 01/27] buffer: Return bool from grow_dev_folio()
2023-10-16 20:10 ` [PATCH v2 01/27] buffer: Return bool from grow_dev_folio() Matthew Wilcox (Oracle)
@ 2023-10-17 19:41 ` Ryusuke Konishi
2023-10-18 14:19 ` Matthew Wilcox
0 siblings, 1 reply; 30+ messages in thread
From: Ryusuke Konishi @ 2023-10-17 19:41 UTC (permalink / raw)
To: Matthew Wilcox (Oracle)
Cc: Andrew Morton, linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev,
ntfs3, ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
On Tue, Oct 17, 2023 at 5:11 AM Matthew Wilcox (Oracle) wrote:
>
> Rename grow_dev_page() to grow_dev_folio() and make it return a bool.
> Document what that bool means; it's more subtle than it first appears.
> Also rename the 'failed' label to 'unlock' beacuse it's not exactly
> 'failed'. It just hasn't succeeded.
>
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> ---
> fs/buffer.c | 39 ++++++++++++++++++++++-----------------
> 1 file changed, 22 insertions(+), 17 deletions(-)
>
> diff --git a/fs/buffer.c b/fs/buffer.c
> index b33cc74e9649..dec41d84044b 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1024,24 +1024,26 @@ static sector_t folio_init_buffers(struct folio *folio,
> }
>
> /*
> - * Create the page-cache page that contains the requested block.
> + * Create the page-cache folio that contains the requested block.
> *
> * This is used purely for blockdev mappings.
> + *
> + * Returns false if we have a 'permanent' failure. Returns true if
> + * we succeeded, or the caller should retry.
> */
> -static int
> -grow_dev_page(struct block_device *bdev, sector_t block,
> +static bool grow_dev_folio(struct block_device *bdev, sector_t block,
> pgoff_t index, int size, int sizebits, gfp_t gfp)
> {
> struct inode *inode = bdev->bd_inode;
> struct folio *folio;
> struct buffer_head *bh;
> sector_t end_block;
> - int ret = 0;
> + bool ret;
>
> folio = __filemap_get_folio(inode->i_mapping, index,
> FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
> if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + return false;
>
> bh = folio_buffers(folio);
> if (bh) {
> @@ -1050,14 +1052,17 @@ grow_dev_page(struct block_device *bdev, sector_t block,
> (sector_t)index << sizebits, size);
> goto done;
> }
> +
> + /* Caller should retry if this call fails */
> + ret = true;
> if (!try_to_free_buffers(folio))
> - goto failed;
> + goto unlock;
> }
>
> - ret = -ENOMEM;
> + ret = false;
> bh = folio_alloc_buffers(folio, size, gfp | __GFP_ACCOUNT);
> if (!bh)
> - goto failed;
> + goto unlock;
>
> /*
> * Link the folio to the buffers and initialise them. Take the
> @@ -1070,19 +1075,19 @@ grow_dev_page(struct block_device *bdev, sector_t block,
> (sector_t)index << sizebits, size);
> spin_unlock(&inode->i_mapping->private_lock);
> done:
> - ret = (block < end_block) ? 1 : -ENXIO;
> -failed:
> + ret = block < end_block;
> +unlock:
> folio_unlock(folio);
> folio_put(folio);
> return ret;
> }
>
> /*
> - * Create buffers for the specified block device block's page. If
> - * that page was dirty, the buffers are set dirty also.
> + * Create buffers for the specified block device block's folio. If
> + * that folio was dirty, the buffers are set dirty also.
> */
> -static int
> -grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
> +static bool grow_buffers(struct block_device *bdev, sector_t block,
> + int size, gfp_t gfp)
> {
> pgoff_t index;
> int sizebits;
> @@ -1099,11 +1104,11 @@ grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
> "device %pg\n",
> __func__, (unsigned long long)block,
> bdev);
> - return -EIO;
> + return false;
> }
>
> - /* Create a page with the proper size buffers.. */
> - return grow_dev_page(bdev, block, index, size, sizebits, gfp);
> + /* Create a folio with the proper size buffers.. */
> + return grow_dev_folio(bdev, block, index, size, sizebits, gfp);
> }
>
> static struct buffer_head *
> --
> 2.40.1
This changes the return type of grow_buffers() from "int" to "bool".
But, it seems that the caller, __getblk_slow(), has not changed the
type of the variable "ret" that receives its return value:
for (;;) {
struct buffer_head *bh;
int ret;
bh = __find_get_block(bdev, block, size);
if (bh)
return bh;
ret = grow_buffers(bdev, block, size, gfp);
if (ret < 0)
return NULL;
}
So, it looks like the error check immediately after calling
grow_buffers() will not branch like before.
Is this okay ? Or, am I missing some other changes?
Also, there is a typo in the changelog: "beacuse" -> "because".
Regards,
Ryusuke Konishi
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v2 01/27] buffer: Return bool from grow_dev_folio()
2023-10-17 19:41 ` Ryusuke Konishi
@ 2023-10-18 14:19 ` Matthew Wilcox
0 siblings, 0 replies; 30+ messages in thread
From: Matthew Wilcox @ 2023-10-18 14:19 UTC (permalink / raw)
To: Ryusuke Konishi
Cc: Andrew Morton, linux-fsdevel, gfs2, linux-nilfs, linux-ntfs-dev,
ntfs3, ocfs2-devel, reiserfs-devel, linux-ext4, Pankaj Raghav
On Wed, Oct 18, 2023 at 04:41:44AM +0900, Ryusuke Konishi wrote:
> On Tue, Oct 17, 2023 at 5:11 AM Matthew Wilcox (Oracle) wrote:
> >
> > Rename grow_dev_page() to grow_dev_folio() and make it return a bool.
> > Document what that bool means; it's more subtle than it first appears.
> > Also rename the 'failed' label to 'unlock' beacuse it's not exactly
> > 'failed'. It just hasn't succeeded.
>
> This changes the return type of grow_buffers() from "int" to "bool".
> But, it seems that the caller, __getblk_slow(), has not changed the
> type of the variable "ret" that receives its return value:
[...]
>
> So, it looks like the error check immediately after calling
> grow_buffers() will not branch like before.
> Is this okay ? Or, am I missing some other changes?
>
> Also, there is a typo in the changelog: "beacuse" -> "because".
Argh, yes. Andrew, please drop this patch for now. I'll submit
something better next cycle.
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2023-10-18 14:19 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-16 20:10 [PATCH v2 00/27] Finish the create_empty_buffers() transition Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 01/27] buffer: Return bool from grow_dev_folio() Matthew Wilcox (Oracle)
2023-10-17 19:41 ` Ryusuke Konishi
2023-10-18 14:19 ` Matthew Wilcox
2023-10-16 20:10 ` [PATCH v2 02/27] buffer: Make folio_create_empty_buffers() return a buffer_head Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 03/27] mpage: Convert map_buffer_to_folio() to folio_create_empty_buffers() Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 04/27] ext4: Convert to folio_create_empty_buffers Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 05/27] buffer: Add get_nth_bh() Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 06/27] gfs2: Convert inode unstuffing to use a folio Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 07/27] gfs2: Convert gfs2_getbuf() to folios Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 08/27] gfs2: Convert gfs2_getjdatabuf to use a folio Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 09/27] gfs2: Convert gfs2_write_buf_to_page() " Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 10/27] nilfs2: Convert nilfs_mdt_freeze_buffer " Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 11/27] nilfs2: Convert nilfs_grab_buffer() " Matthew Wilcox (Oracle)
2023-10-16 20:10 ` [PATCH v2 12/27] nilfs2: Convert nilfs_copy_page() to nilfs_copy_folio() Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 13/27] nilfs2: Convert nilfs_mdt_forget_block() to use a folio Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 14/27] nilfs2: Convert nilfs_mdt_get_frozen_buffer " Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 15/27] nilfs2: Remove nilfs_page_get_nth_block Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 16/27] nilfs2: Convert nilfs_lookup_dirty_data_buffers to use folio_create_empty_buffers Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 17/27] ntfs: Convert ntfs_read_block() to use a folio Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 18/27] ntfs: Convert ntfs_writepage " Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 19/27] ntfs: Convert ntfs_prepare_pages_for_non_resident_write() to folios Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 20/27] ntfs3: Convert ntfs_zero_range() to use a folio Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 21/27] ocfs2: Convert ocfs2_map_page_blocks " Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 22/27] reiserfs: Convert writepage " Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 23/27] ufs: Add ufs_get_locked_folio and ufs_put_locked_folio Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 24/27] ufs: Use ufs_get_locked_folio() in ufs_alloc_lastblock() Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 25/27] ufs; Convert ufs_change_blocknr() to use folios Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 26/27] ufs: Remove ufs_get_locked_page() Matthew Wilcox (Oracle)
2023-10-16 20:11 ` [PATCH v2 27/27] buffer: Remove folio_create_empty_buffers() Matthew Wilcox (Oracle)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).