* [PATCH 00/17] nilfs2: Folio conversions for directory paths
@ 2023-11-27 14:30 Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 01/17] nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link Ryusuke Konishi
` (16 more replies)
0 siblings, 17 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
Hi Andrew,
please add this series to your queue for the next merge window.
This series applies page->folio conversions to nilfs2 directory
operations. This reduces hidden compound_head() calls and also
converts deprecated kmap calls to kmap_local in the directory code.
Although nilfs2 does not yet support large folios, Matthew has done
his best here to include support for large folios, which will be
needed for devices with large block sizes.
This series corresponds to the second half of the original post [1],
but with two complementary patches inserted at the beginning and some
adjustments, to prevent a kmap_local constraint violation found during
testing with highmem mapping.
[1] https://lkml.kernel.org/r/20231106173903.1734114-1-willy@infradead.org
I have reviewed all changes and tested this for regular and small
block sizes, both on machines with and without highmem mapping. No
issues found.
Thanks,
Ryusuke Konishi
Matthew Wilcox (Oracle) (15):
nilfs2: Remove page_address() from nilfs_set_link
nilfs2: Remove page_address() from nilfs_add_link
nilfs2: Remove page_address() from nilfs_delete_entry
nilfs2: Return the mapped address from nilfs_get_page()
nilfs2: Pass the mapped address to nilfs_check_page()
nilfs2: Switch to kmap_local for directory handling
nilfs2: Add nilfs_get_folio()
nilfs2: Convert nilfs_readdir to use a folio
nilfs2: Convert nilfs_find_entry to use a folio
nilfs2: Convert nilfs_rename() to use folios
nilfs2: Convert nilfs_add_link() to use a folio
nilfs2: Convert nilfs_empty_dir() to use a folio
nilfs2: Convert nilfs_make_empty() to use a folio
nilfs2: Convert nilfs_prepare_chunk() and nilfs_commit_chunk() to
folios
nilfs2: Convert nilfs_page_bug() to nilfs_folio_bug()
Ryusuke Konishi (2):
nilfs2: move page release outside of nilfs_delete_entry and
nilfs_set_link
nilfs2: eliminate staggered calls to kunmap in nilfs_rename
fs/nilfs2/btnode.c | 4 +-
fs/nilfs2/dir.c | 244 +++++++++++++++++++++------------------------
fs/nilfs2/namei.c | 38 +++----
fs/nilfs2/nilfs.h | 20 ++--
fs/nilfs2/page.c | 25 ++---
fs/nilfs2/page.h | 6 +-
6 files changed, 159 insertions(+), 178 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 01/17] nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 17:08 ` Matthew Wilcox
2023-11-27 14:30 ` [PATCH 02/17] nilfs2: eliminate staggered calls to kunmap in nilfs_rename Ryusuke Konishi
` (15 subsequent siblings)
16 siblings, 1 reply; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
In a few directory operations, the call to nilfs_put_page() for a page
obtained using nilfs_find_entry() or nilfs_dotdot() is hidden in
nilfs_set_link() and nilfs_delete_entry(), making it difficult to track
page release and preventing change of its call position.
By moving nilfs_put_page() out of these functions, this makes the page
get/put correspondence clearer and makes it easier to swap
nilfs_put_page() calls (and kunmap calls within them) when modifying
multiple directory entries simultaneously in nilfs_rename().
Also, update comments for nilfs_set_link() and nilfs_delete_entry() to
reflect changes in their behavior.
To make nilfs_put_page() visible from namei.c, this moves its definition
to nilfs.h and replaces existing equivalents to use it, but the exposure
of that definition is temporary and will be removed on a later
kmap -> kmap_local conversion.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/nilfs2/dir.c | 11 +----------
fs/nilfs2/namei.c | 13 +++++++------
fs/nilfs2/nilfs.h | 6 ++++++
3 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index de2073c47651..b9f13bdf8fba 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -64,12 +64,6 @@ static inline unsigned int nilfs_chunk_size(struct inode *inode)
return inode->i_sb->s_blocksize;
}
-static inline void nilfs_put_page(struct page *page)
-{
- kunmap(page);
- put_page(page);
-}
-
/*
* Return the offset into page `page_nr' of the last valid
* byte in that page, plus one.
@@ -413,7 +407,6 @@ ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
return res;
}
-/* Releases the page */
void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
struct page *page, struct inode *inode)
{
@@ -428,7 +421,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
de->inode = cpu_to_le64(inode->i_ino);
nilfs_set_de_type(de, inode);
nilfs_commit_chunk(page, mapping, from, to);
- nilfs_put_page(page);
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
}
@@ -533,7 +525,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
/*
* nilfs_delete_entry deletes a directory entry by merging it with the
- * previous entry. Page is up-to-date. Releases the page.
+ * previous entry. Page is up-to-date.
*/
int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
{
@@ -569,7 +561,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
nilfs_commit_chunk(page, mapping, from, to);
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
out:
- nilfs_put_page(page);
return err;
}
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 2a4e7f4a8102..99255694cbe9 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -280,6 +280,7 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
set_nlink(inode, 1);
}
err = nilfs_delete_entry(de, page);
+ nilfs_put_page(page);
if (err)
goto out;
@@ -386,6 +387,7 @@ static int nilfs_rename(struct mnt_idmap *idmap,
if (!new_de)
goto out_dir;
nilfs_set_link(new_dir, new_de, new_page, old_inode);
+ nilfs_put_page(new_page);
nilfs_mark_inode_dirty(new_dir);
inode_set_ctime_current(new_inode);
if (dir_de)
@@ -409,9 +411,11 @@ static int nilfs_rename(struct mnt_idmap *idmap,
inode_set_ctime_current(old_inode);
nilfs_delete_entry(old_de, old_page);
+ nilfs_put_page(old_page);
if (dir_de) {
nilfs_set_link(old_inode, dir_de, dir_page, new_dir);
+ nilfs_put_page(dir_page);
drop_nlink(old_dir);
}
nilfs_mark_inode_dirty(old_dir);
@@ -421,13 +425,10 @@ static int nilfs_rename(struct mnt_idmap *idmap,
return err;
out_dir:
- if (dir_de) {
- kunmap(dir_page);
- put_page(dir_page);
- }
+ if (dir_de)
+ nilfs_put_page(dir_page);
out_old:
- kunmap(old_page);
- put_page(old_page);
+ nilfs_put_page(old_page);
out:
nilfs_transaction_abort(old_dir->i_sb);
return err;
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 8046490cd7fe..afd700f5dc4e 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -237,6 +237,12 @@ extern struct nilfs_dir_entry *nilfs_dotdot(struct inode *, struct page **);
extern void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
struct page *, struct inode *);
+static inline void nilfs_put_page(struct page *page)
+{
+ kunmap(page);
+ put_page(page);
+}
+
/* file.c */
extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 02/17] nilfs2: eliminate staggered calls to kunmap in nilfs_rename
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 01/17] nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 17:08 ` Matthew Wilcox
2023-11-27 14:30 ` [PATCH 03/17] nilfs2: Remove page_address() from nilfs_set_link Ryusuke Konishi
` (14 subsequent siblings)
16 siblings, 1 reply; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
In nilfs_rename(), calls to nilfs_put_page() to release pages obtained
with nilfs_find_entry() or nilfs_dotdot() are alternated in the normal
path.
When replacing the kernel memory mapping method from kmap to
kmap_local_{page,folio}, this violates the constraint on the calling
order of kunmap_local().
Swap the order of nilfs_put_page calls where the kmap sections of
multiple pages overlap so that they are nested, allowing direct
replacement of nilfs_put_page() -> unmap_and_put_page().
Without this reordering, that replacement will cause a kernel WARNING
in kunmap_local_indexed() on architectures with high memory mapping.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
---
fs/nilfs2/namei.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 99255694cbe9..d179db8074c2 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -411,13 +411,14 @@ static int nilfs_rename(struct mnt_idmap *idmap,
inode_set_ctime_current(old_inode);
nilfs_delete_entry(old_de, old_page);
- nilfs_put_page(old_page);
if (dir_de) {
nilfs_set_link(old_inode, dir_de, dir_page, new_dir);
nilfs_put_page(dir_page);
drop_nlink(old_dir);
}
+ nilfs_put_page(old_page);
+
nilfs_mark_inode_dirty(old_dir);
nilfs_mark_inode_dirty(old_inode);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 03/17] nilfs2: Remove page_address() from nilfs_set_link
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 01/17] nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 02/17] nilfs2: eliminate staggered calls to kunmap in nilfs_rename Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 04/17] nilfs2: Remove page_address() from nilfs_add_link Ryusuke Konishi
` (13 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
In preparation for removing kmap from directory handling, use
offset_in_page() to calculate 'from'. Matches ext2.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index b9f13bdf8fba..9c0513245a3b 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -410,7 +410,7 @@ ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
struct page *page, struct inode *inode)
{
- unsigned int from = (char *)de - (char *)page_address(page);
+ unsigned int from = offset_in_page(de);
unsigned int to = from + nilfs_rec_len_from_disk(de->rec_len);
struct address_space *mapping = page->mapping;
int err;
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 04/17] nilfs2: Remove page_address() from nilfs_add_link
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (2 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 03/17] nilfs2: Remove page_address() from nilfs_set_link Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 05/17] nilfs2: Remove page_address() from nilfs_delete_entry Ryusuke Konishi
` (12 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
In preparation for removing kmap from directory handling, use
offset_in_page() to calculate 'from'. Matches ext2.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 9c0513245a3b..73f135290288 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -493,7 +493,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
return -EINVAL;
got_it:
- from = (char *)de - (char *)page_address(page);
+ from = offset_in_page(de);
to = from + rec_len;
err = nilfs_prepare_chunk(page, from, to);
if (err)
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 05/17] nilfs2: Remove page_address() from nilfs_delete_entry
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (3 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 04/17] nilfs2: Remove page_address() from nilfs_add_link Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 06/17] nilfs2: Return the mapped address from nilfs_get_page() Ryusuke Konishi
` (11 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
In preparation for removing kmap from directory handling, mask
the directory entry pointer to discover the start address of the
page. Matches ext2.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 73f135290288..385e47eda99f 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -531,7 +531,7 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
{
struct address_space *mapping = page->mapping;
struct inode *inode = mapping->host;
- char *kaddr = page_address(page);
+ char *kaddr = (char *)((unsigned long)dir & PAGE_MASK);
unsigned int from, to;
struct nilfs_dir_entry *de, *pde = NULL;
int err;
@@ -551,7 +551,7 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
de = nilfs_next_entry(de);
}
if (pde)
- from = (char *)pde - (char *)page_address(page);
+ from = (char *)pde - kaddr;
lock_page(page);
err = nilfs_prepare_chunk(page, from, to);
BUG_ON(err);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 06/17] nilfs2: Return the mapped address from nilfs_get_page()
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (4 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 05/17] nilfs2: Remove page_address() from nilfs_delete_entry Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 07/17] nilfs2: Pass the mapped address to nilfs_check_page() Ryusuke Konishi
` (10 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
In prepartion for switching from kmap() to kmap_local(), return
the kmap address from nilfs_get_page() instead of having the caller
look up page_address().
[ konishi.ryusuke: fixed a missing blank line after declaration ]
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 57 +++++++++++++++++++++++--------------------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 385e47eda99f..45f75d4c4522 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -180,19 +180,24 @@ static bool nilfs_check_page(struct page *page)
return false;
}
-static struct page *nilfs_get_page(struct inode *dir, unsigned long n)
+static void *nilfs_get_page(struct inode *dir, unsigned long n,
+ struct page **pagep)
{
struct address_space *mapping = dir->i_mapping;
struct page *page = read_mapping_page(mapping, n, NULL);
+ void *kaddr;
- if (!IS_ERR(page)) {
- kmap(page);
- if (unlikely(!PageChecked(page))) {
- if (!nilfs_check_page(page))
- goto fail;
- }
+ if (IS_ERR(page))
+ return page;
+
+ kaddr = kmap(page);
+ if (unlikely(!PageChecked(page))) {
+ if (!nilfs_check_page(page))
+ goto fail;
}
- return page;
+
+ *pagep = page;
+ return kaddr;
fail:
nilfs_put_page(page);
@@ -269,14 +274,14 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
for ( ; n < npages; n++, offset = 0) {
char *kaddr, *limit;
struct nilfs_dir_entry *de;
- struct page *page = nilfs_get_page(inode, n);
+ struct page *page;
- if (IS_ERR(page)) {
+ kaddr = nilfs_get_page(inode, n, &page);
+ if (IS_ERR(kaddr)) {
nilfs_error(sb, "bad page in #%lu", inode->i_ino);
ctx->pos += PAGE_SIZE - offset;
return -EIO;
}
- kaddr = page_address(page);
de = (struct nilfs_dir_entry *)(kaddr + offset);
limit = kaddr + nilfs_last_byte(inode, n) -
NILFS_DIR_REC_LEN(1);
@@ -339,11 +344,9 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
start = 0;
n = start;
do {
- char *kaddr;
+ char *kaddr = nilfs_get_page(dir, n, &page);
- page = nilfs_get_page(dir, n);
- if (!IS_ERR(page)) {
- kaddr = page_address(page);
+ if (!IS_ERR(kaddr)) {
de = (struct nilfs_dir_entry *)kaddr;
kaddr += nilfs_last_byte(dir, n) - reclen;
while ((char *) de <= kaddr) {
@@ -381,15 +384,11 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct page **p)
{
- struct page *page = nilfs_get_page(dir, 0);
- struct nilfs_dir_entry *de = NULL;
+ struct nilfs_dir_entry *de = nilfs_get_page(dir, 0, p);
- if (!IS_ERR(page)) {
- de = nilfs_next_entry(
- (struct nilfs_dir_entry *)page_address(page));
- *p = page;
- }
- return de;
+ if (IS_ERR(de))
+ return NULL;
+ return nilfs_next_entry(de);
}
ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
@@ -451,12 +450,11 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
for (n = 0; n <= npages; n++) {
char *dir_end;
- page = nilfs_get_page(dir, n);
- err = PTR_ERR(page);
- if (IS_ERR(page))
+ kaddr = nilfs_get_page(dir, n, &page);
+ err = PTR_ERR(kaddr);
+ if (IS_ERR(kaddr))
goto out;
lock_page(page);
- kaddr = page_address(page);
dir_end = kaddr + nilfs_last_byte(dir, n);
de = (struct nilfs_dir_entry *)kaddr;
kaddr += PAGE_SIZE - reclen;
@@ -618,11 +616,10 @@ int nilfs_empty_dir(struct inode *inode)
char *kaddr;
struct nilfs_dir_entry *de;
- page = nilfs_get_page(inode, i);
- if (IS_ERR(page))
+ kaddr = nilfs_get_page(inode, i, &page);
+ if (IS_ERR(kaddr))
continue;
- kaddr = page_address(page);
de = (struct nilfs_dir_entry *)kaddr;
kaddr += nilfs_last_byte(inode, i) - NILFS_DIR_REC_LEN(1);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 07/17] nilfs2: Pass the mapped address to nilfs_check_page()
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (5 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 06/17] nilfs2: Return the mapped address from nilfs_get_page() Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 08/17] nilfs2: Switch to kmap_local for directory handling Ryusuke Konishi
` (9 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Remove another use of page_address() as part of preparing for
the kmap to kmap_local transition.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 45f75d4c4522..01900e84bddf 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -107,12 +107,11 @@ static void nilfs_commit_chunk(struct page *page,
unlock_page(page);
}
-static bool nilfs_check_page(struct page *page)
+static bool nilfs_check_page(struct page *page, char *kaddr)
{
struct inode *dir = page->mapping->host;
struct super_block *sb = dir->i_sb;
unsigned int chunk_size = nilfs_chunk_size(dir);
- char *kaddr = page_address(page);
unsigned int offs, rec_len;
unsigned int limit = PAGE_SIZE;
struct nilfs_dir_entry *p;
@@ -192,7 +191,7 @@ static void *nilfs_get_page(struct inode *dir, unsigned long n,
kaddr = kmap(page);
if (unlikely(!PageChecked(page))) {
- if (!nilfs_check_page(page))
+ if (!nilfs_check_page(page, kaddr))
goto fail;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 08/17] nilfs2: Switch to kmap_local for directory handling
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (6 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 07/17] nilfs2: Pass the mapped address to nilfs_check_page() Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 09/17] nilfs2: Add nilfs_get_folio() Ryusuke Konishi
` (8 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Match ext2 by using kmap_local() instead of kmap(). This is more
efficient. Also use unmap_and_put_page() instead of duplicating
it as a nilfs function.
[ konishi.ryusuke: followed the change of page release helper call sites ]
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 27 +++++++++++++--------------
fs/nilfs2/namei.c | 12 ++++++------
fs/nilfs2/nilfs.h | 6 ------
3 files changed, 19 insertions(+), 26 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 01900e84bddf..89e8a248e571 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -189,7 +189,7 @@ static void *nilfs_get_page(struct inode *dir, unsigned long n,
if (IS_ERR(page))
return page;
- kaddr = kmap(page);
+ kaddr = kmap_local_page(page);
if (unlikely(!PageChecked(page))) {
if (!nilfs_check_page(page, kaddr))
goto fail;
@@ -199,7 +199,7 @@ static void *nilfs_get_page(struct inode *dir, unsigned long n,
return kaddr;
fail:
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
return ERR_PTR(-EIO);
}
@@ -287,7 +287,7 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
for ( ; (char *)de <= limit; de = nilfs_next_entry(de)) {
if (de->rec_len == 0) {
nilfs_error(sb, "zero-length directory entry");
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
return -EIO;
}
if (de->inode) {
@@ -300,13 +300,13 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
if (!dir_emit(ctx, de->name, de->name_len,
le64_to_cpu(de->inode), t)) {
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
return 0;
}
}
ctx->pos += nilfs_rec_len_from_disk(de->rec_len);
}
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
}
return 0;
}
@@ -352,14 +352,14 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
if (de->rec_len == 0) {
nilfs_error(dir->i_sb,
"zero-length directory entry");
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
goto out;
}
if (nilfs_match(namelen, name, de))
goto found;
de = nilfs_next_entry(de);
}
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
}
if (++n >= npages)
n = 0;
@@ -399,8 +399,7 @@ ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
de = nilfs_find_entry(dir, qstr, &page);
if (de) {
res = le64_to_cpu(de->inode);
- kunmap(page);
- put_page(page);
+ unmap_and_put_page(page, de);
}
return res;
}
@@ -484,7 +483,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
de = (struct nilfs_dir_entry *)((char *)de + rec_len);
}
unlock_page(page);
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
}
BUG();
return -EINVAL;
@@ -512,7 +511,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
nilfs_mark_inode_dirty(dir);
/* OFFSET_CACHE */
out_put:
- nilfs_put_page(page);
+ unmap_and_put_page(page, de);
out:
return err;
out_unlock:
@@ -609,10 +608,10 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent)
int nilfs_empty_dir(struct inode *inode)
{
struct page *page = NULL;
+ char *kaddr;
unsigned long i, npages = dir_pages(inode);
for (i = 0; i < npages; i++) {
- char *kaddr;
struct nilfs_dir_entry *de;
kaddr = nilfs_get_page(inode, i, &page);
@@ -644,12 +643,12 @@ int nilfs_empty_dir(struct inode *inode)
}
de = nilfs_next_entry(de);
}
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
}
return 1;
not_empty:
- nilfs_put_page(page);
+ unmap_and_put_page(page, kaddr);
return 0;
}
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index d179db8074c2..c08b1bf9fa7b 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -280,7 +280,7 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
set_nlink(inode, 1);
}
err = nilfs_delete_entry(de, page);
- nilfs_put_page(page);
+ unmap_and_put_page(page, de);
if (err)
goto out;
@@ -387,7 +387,7 @@ static int nilfs_rename(struct mnt_idmap *idmap,
if (!new_de)
goto out_dir;
nilfs_set_link(new_dir, new_de, new_page, old_inode);
- nilfs_put_page(new_page);
+ unmap_and_put_page(new_page, new_de);
nilfs_mark_inode_dirty(new_dir);
inode_set_ctime_current(new_inode);
if (dir_de)
@@ -414,10 +414,10 @@ static int nilfs_rename(struct mnt_idmap *idmap,
if (dir_de) {
nilfs_set_link(old_inode, dir_de, dir_page, new_dir);
- nilfs_put_page(dir_page);
+ unmap_and_put_page(dir_page, dir_de);
drop_nlink(old_dir);
}
- nilfs_put_page(old_page);
+ unmap_and_put_page(old_page, old_de);
nilfs_mark_inode_dirty(old_dir);
nilfs_mark_inode_dirty(old_inode);
@@ -427,9 +427,9 @@ static int nilfs_rename(struct mnt_idmap *idmap,
out_dir:
if (dir_de)
- nilfs_put_page(dir_page);
+ unmap_and_put_page(dir_page, dir_de);
out_old:
- nilfs_put_page(old_page);
+ unmap_and_put_page(old_page, old_de);
out:
nilfs_transaction_abort(old_dir->i_sb);
return err;
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index afd700f5dc4e..8046490cd7fe 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -237,12 +237,6 @@ extern struct nilfs_dir_entry *nilfs_dotdot(struct inode *, struct page **);
extern void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
struct page *, struct inode *);
-static inline void nilfs_put_page(struct page *page)
-{
- kunmap(page);
- put_page(page);
-}
-
/* file.c */
extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 09/17] nilfs2: Add nilfs_get_folio()
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (7 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 08/17] nilfs2: Switch to kmap_local for directory handling Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 10/17] nilfs2: Convert nilfs_readdir to use a folio Ryusuke Konishi
` (7 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Convert nilfs_get_page() to be a wrapper.
Also convert nilfs_check_page() to nilfs_check_folio().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 53 +++++++++++++++++++++++++++++--------------------
1 file changed, 32 insertions(+), 21 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 89e8a248e571..5c9ca3f0d7f4 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -107,18 +107,18 @@ static void nilfs_commit_chunk(struct page *page,
unlock_page(page);
}
-static bool nilfs_check_page(struct page *page, char *kaddr)
+static bool nilfs_check_folio(struct folio *folio, char *kaddr)
{
- struct inode *dir = page->mapping->host;
+ struct inode *dir = folio->mapping->host;
struct super_block *sb = dir->i_sb;
unsigned int chunk_size = nilfs_chunk_size(dir);
- unsigned int offs, rec_len;
- unsigned int limit = PAGE_SIZE;
+ size_t offs, rec_len;
+ size_t limit = folio_size(folio);
struct nilfs_dir_entry *p;
char *error;
- if ((dir->i_size >> PAGE_SHIFT) == page->index) {
- limit = dir->i_size & ~PAGE_MASK;
+ if (dir->i_size < folio_pos(folio) + limit) {
+ limit = dir->i_size - folio_pos(folio);
if (limit & (chunk_size - 1))
goto Ebadsize;
if (!limit)
@@ -140,7 +140,7 @@ static bool nilfs_check_page(struct page *page, char *kaddr)
if (offs != limit)
goto Eend;
out:
- SetPageChecked(page);
+ folio_set_checked(folio);
return true;
/* Too bad, we had an error */
@@ -163,8 +163,8 @@ static bool nilfs_check_page(struct page *page, char *kaddr)
error = "directory entry across blocks";
bad_entry:
nilfs_error(sb,
- "bad entry in directory #%lu: %s - offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
- dir->i_ino, error, (page->index << PAGE_SHIFT) + offs,
+ "bad entry in directory #%lu: %s - offset=%lu, inode=%lu, rec_len=%zd, name_len=%d",
+ dir->i_ino, error, (folio->index << PAGE_SHIFT) + offs,
(unsigned long)le64_to_cpu(p->inode),
rec_len, p->name_len);
goto fail;
@@ -172,37 +172,48 @@ static bool nilfs_check_page(struct page *page, char *kaddr)
p = (struct nilfs_dir_entry *)(kaddr + offs);
nilfs_error(sb,
"entry in directory #%lu spans the page boundary offset=%lu, inode=%lu",
- dir->i_ino, (page->index << PAGE_SHIFT) + offs,
+ dir->i_ino, (folio->index << PAGE_SHIFT) + offs,
(unsigned long)le64_to_cpu(p->inode));
fail:
- SetPageError(page);
+ folio_set_error(folio);
return false;
}
-static void *nilfs_get_page(struct inode *dir, unsigned long n,
- struct page **pagep)
+static void *nilfs_get_folio(struct inode *dir, unsigned long n,
+ struct folio **foliop)
{
struct address_space *mapping = dir->i_mapping;
- struct page *page = read_mapping_page(mapping, n, NULL);
+ struct folio *folio = read_mapping_folio(mapping, n, NULL);
void *kaddr;
- if (IS_ERR(page))
- return page;
+ if (IS_ERR(folio))
+ return folio;
- kaddr = kmap_local_page(page);
- if (unlikely(!PageChecked(page))) {
- if (!nilfs_check_page(page, kaddr))
+ kaddr = kmap_local_folio(folio, 0);
+ if (unlikely(!folio_test_checked(folio))) {
+ if (!nilfs_check_folio(folio, kaddr))
goto fail;
}
- *pagep = page;
+ *foliop = folio;
return kaddr;
fail:
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
return ERR_PTR(-EIO);
}
+static void *nilfs_get_page(struct inode *dir, unsigned long n,
+ struct page **pagep)
+{
+ struct folio *folio;
+ void *kaddr = nilfs_get_folio(dir, n, &folio);
+
+ if (!IS_ERR(kaddr))
+ *pagep = &folio->page;
+ return kaddr;
+}
+
/*
* NOTE! unlike strncmp, nilfs_match returns 1 for success, 0 for failure.
*
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 10/17] nilfs2: Convert nilfs_readdir to use a folio
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (8 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 09/17] nilfs2: Add nilfs_get_folio() Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 11/17] nilfs2: Convert nilfs_find_entry " Ryusuke Konishi
` (6 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Use the new folio APIs to remove calls to compound_head().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 5c9ca3f0d7f4..c7b046589877 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -284,9 +284,9 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
for ( ; n < npages; n++, offset = 0) {
char *kaddr, *limit;
struct nilfs_dir_entry *de;
- struct page *page;
+ struct folio *folio;
- kaddr = nilfs_get_page(inode, n, &page);
+ kaddr = nilfs_get_folio(inode, n, &folio);
if (IS_ERR(kaddr)) {
nilfs_error(sb, "bad page in #%lu", inode->i_ino);
ctx->pos += PAGE_SIZE - offset;
@@ -298,7 +298,7 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
for ( ; (char *)de <= limit; de = nilfs_next_entry(de)) {
if (de->rec_len == 0) {
nilfs_error(sb, "zero-length directory entry");
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
return -EIO;
}
if (de->inode) {
@@ -311,13 +311,13 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
if (!dir_emit(ctx, de->name, de->name_len,
le64_to_cpu(de->inode), t)) {
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
return 0;
}
}
ctx->pos += nilfs_rec_len_from_disk(de->rec_len);
}
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
}
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 11/17] nilfs2: Convert nilfs_find_entry to use a folio
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (9 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 10/17] nilfs2: Convert nilfs_readdir to use a folio Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 12/17] nilfs2: Convert nilfs_rename() to use folios Ryusuke Konishi
` (5 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Use the new folio APIs to remove calls to compound_head().
[ konishi.ryusuke: resolved a conflict due to style warning correction ]
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index c7b046589877..a79726182867 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -339,7 +339,7 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
unsigned int reclen = NILFS_DIR_REC_LEN(namelen);
unsigned long start, n;
unsigned long npages = dir_pages(dir);
- struct page *page = NULL;
+ struct folio *folio = NULL;
struct nilfs_inode_info *ei = NILFS_I(dir);
struct nilfs_dir_entry *de;
@@ -354,7 +354,7 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
start = 0;
n = start;
do {
- char *kaddr = nilfs_get_page(dir, n, &page);
+ char *kaddr = nilfs_get_folio(dir, n, &folio);
if (!IS_ERR(kaddr)) {
de = (struct nilfs_dir_entry *)kaddr;
@@ -363,18 +363,18 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
if (de->rec_len == 0) {
nilfs_error(dir->i_sb,
"zero-length directory entry");
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
goto out;
}
if (nilfs_match(namelen, name, de))
goto found;
de = nilfs_next_entry(de);
}
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
}
if (++n >= npages)
n = 0;
- /* next page is past the blocks we've got */
+ /* next folio is past the blocks we've got */
if (unlikely(n > (dir->i_blocks >> (PAGE_SHIFT - 9)))) {
nilfs_error(dir->i_sb,
"dir %lu size %lld exceeds block count %llu",
@@ -387,7 +387,7 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
return NULL;
found:
- *res_page = page;
+ *res_page = &folio->page;
ei->i_dir_start_lookup = n;
return de;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 12/17] nilfs2: Convert nilfs_rename() to use folios
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (10 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 11/17] nilfs2: Convert nilfs_find_entry " Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 13/17] nilfs2: Convert nilfs_add_link() to use a folio Ryusuke Konishi
` (4 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
This involves converting nilfs_find_entry(), nilfs_dotdot(),
nilfs_set_link(), nilfs_delete_entry() and nilfs_do_unlink()
to use folios as well.
[ konishi.ryusuke: followed the change of page release helper call sites ]
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 68 ++++++++++++++++++++++-------------------------
fs/nilfs2/namei.c | 36 ++++++++++++-------------
fs/nilfs2/nilfs.h | 20 +++++++-------
3 files changed, 60 insertions(+), 64 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index a79726182867..2a759598801b 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -323,38 +323,35 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
}
/*
- * nilfs_find_entry()
+ * nilfs_find_entry()
*
- * finds an entry in the specified directory with the wanted name. It
- * returns the page in which the entry was found, and the entry itself
- * (as a parameter - res_dir). Page is returned mapped and unlocked.
- * Entry is guaranteed to be valid.
+ * Finds an entry in the specified directory with the wanted name. It
+ * returns the folio in which the entry was found, and the entry itself.
+ * The folio is mapped and unlocked. When the caller is finished with
+ * the entry, it should call folio_release_kmap().
+ *
+ * On failure, returns NULL and the caller should ignore foliop.
*/
-struct nilfs_dir_entry *
-nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
- struct page **res_page)
+struct nilfs_dir_entry *nilfs_find_entry(struct inode *dir,
+ const struct qstr *qstr, struct folio **foliop)
{
const unsigned char *name = qstr->name;
int namelen = qstr->len;
unsigned int reclen = NILFS_DIR_REC_LEN(namelen);
unsigned long start, n;
unsigned long npages = dir_pages(dir);
- struct folio *folio = NULL;
struct nilfs_inode_info *ei = NILFS_I(dir);
struct nilfs_dir_entry *de;
if (npages == 0)
goto out;
- /* OFFSET_CACHE */
- *res_page = NULL;
-
start = ei->i_dir_start_lookup;
if (start >= npages)
start = 0;
n = start;
do {
- char *kaddr = nilfs_get_folio(dir, n, &folio);
+ char *kaddr = nilfs_get_folio(dir, n, foliop);
if (!IS_ERR(kaddr)) {
de = (struct nilfs_dir_entry *)kaddr;
@@ -363,14 +360,14 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
if (de->rec_len == 0) {
nilfs_error(dir->i_sb,
"zero-length directory entry");
- folio_release_kmap(folio, kaddr);
+ folio_release_kmap(*foliop, kaddr);
goto out;
}
if (nilfs_match(namelen, name, de))
goto found;
de = nilfs_next_entry(de);
}
- folio_release_kmap(folio, kaddr);
+ folio_release_kmap(*foliop, kaddr);
}
if (++n >= npages)
n = 0;
@@ -387,14 +384,13 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
return NULL;
found:
- *res_page = &folio->page;
ei->i_dir_start_lookup = n;
return de;
}
-struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct page **p)
+struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct folio **foliop)
{
- struct nilfs_dir_entry *de = nilfs_get_page(dir, 0, p);
+ struct nilfs_dir_entry *de = nilfs_get_folio(dir, 0, foliop);
if (IS_ERR(de))
return NULL;
@@ -405,30 +401,30 @@ ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
{
ino_t res = 0;
struct nilfs_dir_entry *de;
- struct page *page;
+ struct folio *folio;
- de = nilfs_find_entry(dir, qstr, &page);
+ de = nilfs_find_entry(dir, qstr, &folio);
if (de) {
res = le64_to_cpu(de->inode);
- unmap_and_put_page(page, de);
+ folio_release_kmap(folio, de);
}
return res;
}
void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
- struct page *page, struct inode *inode)
+ struct folio *folio, struct inode *inode)
{
- unsigned int from = offset_in_page(de);
- unsigned int to = from + nilfs_rec_len_from_disk(de->rec_len);
- struct address_space *mapping = page->mapping;
+ size_t from = offset_in_folio(folio, de);
+ size_t to = from + nilfs_rec_len_from_disk(de->rec_len);
+ struct address_space *mapping = folio->mapping;
int err;
- lock_page(page);
- err = nilfs_prepare_chunk(page, from, to);
+ folio_lock(folio);
+ err = nilfs_prepare_chunk(&folio->page, from, to);
BUG_ON(err);
de->inode = cpu_to_le64(inode->i_ino);
nilfs_set_de_type(de, inode);
- nilfs_commit_chunk(page, mapping, from, to);
+ nilfs_commit_chunk(&folio->page, mapping, from, to);
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
}
@@ -532,14 +528,14 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
/*
* nilfs_delete_entry deletes a directory entry by merging it with the
- * previous entry. Page is up-to-date.
+ * previous entry. Folio is up-to-date.
*/
-int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
+int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct folio *folio)
{
- struct address_space *mapping = page->mapping;
+ struct address_space *mapping = folio->mapping;
struct inode *inode = mapping->host;
- char *kaddr = (char *)((unsigned long)dir & PAGE_MASK);
- unsigned int from, to;
+ char *kaddr = (char *)((unsigned long)dir & ~(folio_size(folio) - 1));
+ size_t from, to;
struct nilfs_dir_entry *de, *pde = NULL;
int err;
@@ -559,13 +555,13 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
}
if (pde)
from = (char *)pde - kaddr;
- lock_page(page);
- err = nilfs_prepare_chunk(page, from, to);
+ folio_lock(folio);
+ err = nilfs_prepare_chunk(&folio->page, from, to);
BUG_ON(err);
if (pde)
pde->rec_len = nilfs_rec_len_to_disk(to - from);
dir->inode = 0;
- nilfs_commit_chunk(page, mapping, from, to);
+ nilfs_commit_chunk(&folio->page, mapping, from, to);
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
out:
return err;
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index c08b1bf9fa7b..959bd9fb3d81 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -260,11 +260,11 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode;
struct nilfs_dir_entry *de;
- struct page *page;
+ struct folio *folio;
int err;
err = -ENOENT;
- de = nilfs_find_entry(dir, &dentry->d_name, &page);
+ de = nilfs_find_entry(dir, &dentry->d_name, &folio);
if (!de)
goto out;
@@ -279,8 +279,8 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
inode->i_ino, inode->i_nlink);
set_nlink(inode, 1);
}
- err = nilfs_delete_entry(de, page);
- unmap_and_put_page(page, de);
+ err = nilfs_delete_entry(de, folio);
+ folio_release_kmap(folio, de);
if (err)
goto out;
@@ -348,9 +348,9 @@ static int nilfs_rename(struct mnt_idmap *idmap,
{
struct inode *old_inode = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
- struct page *dir_page = NULL;
+ struct folio *dir_folio = NULL;
struct nilfs_dir_entry *dir_de = NULL;
- struct page *old_page;
+ struct folio *old_folio;
struct nilfs_dir_entry *old_de;
struct nilfs_transaction_info ti;
int err;
@@ -363,19 +363,19 @@ static int nilfs_rename(struct mnt_idmap *idmap,
return err;
err = -ENOENT;
- old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_page);
+ old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_folio);
if (!old_de)
goto out;
if (S_ISDIR(old_inode->i_mode)) {
err = -EIO;
- dir_de = nilfs_dotdot(old_inode, &dir_page);
+ dir_de = nilfs_dotdot(old_inode, &dir_folio);
if (!dir_de)
goto out_old;
}
if (new_inode) {
- struct page *new_page;
+ struct folio *new_folio;
struct nilfs_dir_entry *new_de;
err = -ENOTEMPTY;
@@ -383,11 +383,11 @@ static int nilfs_rename(struct mnt_idmap *idmap,
goto out_dir;
err = -ENOENT;
- new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, &new_page);
+ new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, &new_folio);
if (!new_de)
goto out_dir;
- nilfs_set_link(new_dir, new_de, new_page, old_inode);
- unmap_and_put_page(new_page, new_de);
+ nilfs_set_link(new_dir, new_de, new_folio, old_inode);
+ folio_release_kmap(new_folio, new_de);
nilfs_mark_inode_dirty(new_dir);
inode_set_ctime_current(new_inode);
if (dir_de)
@@ -410,14 +410,14 @@ static int nilfs_rename(struct mnt_idmap *idmap,
*/
inode_set_ctime_current(old_inode);
- nilfs_delete_entry(old_de, old_page);
+ nilfs_delete_entry(old_de, old_folio);
if (dir_de) {
- nilfs_set_link(old_inode, dir_de, dir_page, new_dir);
- unmap_and_put_page(dir_page, dir_de);
+ nilfs_set_link(old_inode, dir_de, dir_folio, new_dir);
+ folio_release_kmap(dir_folio, dir_de);
drop_nlink(old_dir);
}
- unmap_and_put_page(old_page, old_de);
+ folio_release_kmap(old_folio, old_de);
nilfs_mark_inode_dirty(old_dir);
nilfs_mark_inode_dirty(old_inode);
@@ -427,9 +427,9 @@ static int nilfs_rename(struct mnt_idmap *idmap,
out_dir:
if (dir_de)
- unmap_and_put_page(dir_page, dir_de);
+ folio_release_kmap(dir_folio, dir_de);
out_old:
- unmap_and_put_page(old_page, old_de);
+ folio_release_kmap(old_folio, old_de);
out:
nilfs_transaction_abort(old_dir->i_sb);
return err;
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 8046490cd7fe..98cffaf0ac12 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -226,16 +226,16 @@ static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags)
}
/* dir.c */
-extern int nilfs_add_link(struct dentry *, struct inode *);
-extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
-extern int nilfs_make_empty(struct inode *, struct inode *);
-extern struct nilfs_dir_entry *
-nilfs_find_entry(struct inode *, const struct qstr *, struct page **);
-extern int nilfs_delete_entry(struct nilfs_dir_entry *, struct page *);
-extern int nilfs_empty_dir(struct inode *);
-extern struct nilfs_dir_entry *nilfs_dotdot(struct inode *, struct page **);
-extern void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
- struct page *, struct inode *);
+int nilfs_add_link(struct dentry *, struct inode *);
+ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
+int nilfs_make_empty(struct inode *, struct inode *);
+struct nilfs_dir_entry *nilfs_find_entry(struct inode *, const struct qstr *,
+ struct folio **);
+int nilfs_delete_entry(struct nilfs_dir_entry *, struct folio *);
+int nilfs_empty_dir(struct inode *);
+struct nilfs_dir_entry *nilfs_dotdot(struct inode *, struct folio **);
+void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
+ struct folio *, struct inode *);
/* file.c */
extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 13/17] nilfs2: Convert nilfs_add_link() to use a folio
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (11 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 12/17] nilfs2: Convert nilfs_rename() to use folios Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 14/17] nilfs2: Convert nilfs_empty_dir() " Ryusuke Konishi
` (3 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Remove six calls to compound_head() by using the folio API.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 31 ++++++++++++++-----------------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 2a759598801b..8d8c42e34148 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -439,30 +439,28 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
unsigned int chunk_size = nilfs_chunk_size(dir);
unsigned int reclen = NILFS_DIR_REC_LEN(namelen);
unsigned short rec_len, name_len;
- struct page *page = NULL;
+ struct folio *folio = NULL;
struct nilfs_dir_entry *de;
unsigned long npages = dir_pages(dir);
unsigned long n;
- char *kaddr;
- unsigned int from, to;
+ size_t from, to;
int err;
/*
* We take care of directory expansion in the same loop.
- * This code plays outside i_size, so it locks the page
+ * This code plays outside i_size, so it locks the folio
* to protect that region.
*/
for (n = 0; n <= npages; n++) {
+ char *kaddr = nilfs_get_folio(dir, n, &folio);
char *dir_end;
- kaddr = nilfs_get_page(dir, n, &page);
- err = PTR_ERR(kaddr);
if (IS_ERR(kaddr))
- goto out;
- lock_page(page);
+ return PTR_ERR(kaddr);
+ folio_lock(folio);
dir_end = kaddr + nilfs_last_byte(dir, n);
de = (struct nilfs_dir_entry *)kaddr;
- kaddr += PAGE_SIZE - reclen;
+ kaddr += folio_size(folio) - reclen;
while ((char *)de <= kaddr) {
if ((char *)de == dir_end) {
/* We hit i_size */
@@ -489,16 +487,16 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
goto got_it;
de = (struct nilfs_dir_entry *)((char *)de + rec_len);
}
- unlock_page(page);
- unmap_and_put_page(page, kaddr);
+ folio_unlock(folio);
+ folio_release_kmap(folio, kaddr);
}
BUG();
return -EINVAL;
got_it:
- from = offset_in_page(de);
+ from = offset_in_folio(folio, de);
to = from + rec_len;
- err = nilfs_prepare_chunk(page, from, to);
+ err = nilfs_prepare_chunk(&folio->page, from, to);
if (err)
goto out_unlock;
if (de->inode) {
@@ -513,16 +511,15 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
memcpy(de->name, name, namelen);
de->inode = cpu_to_le64(inode->i_ino);
nilfs_set_de_type(de, inode);
- nilfs_commit_chunk(page, page->mapping, from, to);
+ nilfs_commit_chunk(&folio->page, folio->mapping, from, to);
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
nilfs_mark_inode_dirty(dir);
/* OFFSET_CACHE */
out_put:
- unmap_and_put_page(page, de);
-out:
+ folio_release_kmap(folio, de);
return err;
out_unlock:
- unlock_page(page);
+ folio_unlock(folio);
goto out_put;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 14/17] nilfs2: Convert nilfs_empty_dir() to use a folio
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (12 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 13/17] nilfs2: Convert nilfs_add_link() to use a folio Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 15/17] nilfs2: Convert nilfs_make_empty() " Ryusuke Konishi
` (2 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Remove three calls to compound_head() by using the folio API.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 8d8c42e34148..919936d9ec27 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -203,17 +203,6 @@ static void *nilfs_get_folio(struct inode *dir, unsigned long n,
return ERR_PTR(-EIO);
}
-static void *nilfs_get_page(struct inode *dir, unsigned long n,
- struct page **pagep)
-{
- struct folio *folio;
- void *kaddr = nilfs_get_folio(dir, n, &folio);
-
- if (!IS_ERR(kaddr))
- *pagep = &folio->page;
- return kaddr;
-}
-
/*
* NOTE! unlike strncmp, nilfs_match returns 1 for success, 0 for failure.
*
@@ -611,14 +600,14 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent)
*/
int nilfs_empty_dir(struct inode *inode)
{
- struct page *page = NULL;
+ struct folio *folio = NULL;
char *kaddr;
unsigned long i, npages = dir_pages(inode);
for (i = 0; i < npages; i++) {
struct nilfs_dir_entry *de;
- kaddr = nilfs_get_page(inode, i, &page);
+ kaddr = nilfs_get_folio(inode, i, &folio);
if (IS_ERR(kaddr))
continue;
@@ -647,12 +636,12 @@ int nilfs_empty_dir(struct inode *inode)
}
de = nilfs_next_entry(de);
}
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
}
return 1;
not_empty:
- unmap_and_put_page(page, kaddr);
+ folio_release_kmap(folio, kaddr);
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 15/17] nilfs2: Convert nilfs_make_empty() to use a folio
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (13 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 14/17] nilfs2: Convert nilfs_empty_dir() " Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 16/17] nilfs2: Convert nilfs_prepare_chunk() and nilfs_commit_chunk() to folios Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 17/17] nilfs2: Convert nilfs_page_bug() to nilfs_folio_bug() Ryusuke Konishi
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Remove two calls to compound_head() and switch from kmap_atomic to
kmap_local.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 919936d9ec27..ff0a009a292f 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -559,21 +559,21 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct folio *folio)
int nilfs_make_empty(struct inode *inode, struct inode *parent)
{
struct address_space *mapping = inode->i_mapping;
- struct page *page = grab_cache_page(mapping, 0);
+ struct folio *folio = filemap_grab_folio(mapping, 0);
unsigned int chunk_size = nilfs_chunk_size(inode);
struct nilfs_dir_entry *de;
int err;
void *kaddr;
- if (!page)
- return -ENOMEM;
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
- err = nilfs_prepare_chunk(page, 0, chunk_size);
+ err = nilfs_prepare_chunk(&folio->page, 0, chunk_size);
if (unlikely(err)) {
- unlock_page(page);
+ folio_unlock(folio);
goto fail;
}
- kaddr = kmap_atomic(page);
+ kaddr = kmap_local_folio(folio, 0);
memset(kaddr, 0, chunk_size);
de = (struct nilfs_dir_entry *)kaddr;
de->name_len = 1;
@@ -588,10 +588,10 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent)
de->inode = cpu_to_le64(parent->i_ino);
memcpy(de->name, "..\0", 4);
nilfs_set_de_type(de, inode);
- kunmap_atomic(kaddr);
- nilfs_commit_chunk(page, mapping, 0, chunk_size);
+ kunmap_local(kaddr);
+ nilfs_commit_chunk(&folio->page, mapping, 0, chunk_size);
fail:
- put_page(page);
+ folio_put(folio);
return err;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 16/17] nilfs2: Convert nilfs_prepare_chunk() and nilfs_commit_chunk() to folios
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (14 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 15/17] nilfs2: Convert nilfs_make_empty() " Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 17/17] nilfs2: Convert nilfs_page_bug() to nilfs_folio_bug() Ryusuke Konishi
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
All callers now have a folio, so convert these two functions.
Saves one call to compound_head() in unlock_page().
[ konishi.ryusuke: resolved conflicts in nilfs_{set_link,delete_entry} ]
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/dir.c | 39 +++++++++++++++++++--------------------
1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index ff0a009a292f..bc846b904b68 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -78,33 +78,32 @@ static unsigned int nilfs_last_byte(struct inode *inode, unsigned long page_nr)
return last_byte;
}
-static int nilfs_prepare_chunk(struct page *page, unsigned int from,
+static int nilfs_prepare_chunk(struct folio *folio, unsigned int from,
unsigned int to)
{
- loff_t pos = page_offset(page) + from;
+ loff_t pos = folio_pos(folio) + from;
- return __block_write_begin(page, pos, to - from, nilfs_get_block);
+ return __block_write_begin(&folio->page, pos, to - from, nilfs_get_block);
}
-static void nilfs_commit_chunk(struct page *page,
- struct address_space *mapping,
- unsigned int from, unsigned int to)
+static void nilfs_commit_chunk(struct folio *folio,
+ struct address_space *mapping, size_t from, size_t to)
{
struct inode *dir = mapping->host;
- loff_t pos = page_offset(page) + from;
- unsigned int len = to - from;
- unsigned int nr_dirty, copied;
+ loff_t pos = folio_pos(folio) + from;
+ size_t copied, len = to - from;
+ unsigned int nr_dirty;
int err;
- nr_dirty = nilfs_page_count_clean_buffers(page, from, to);
- copied = block_write_end(NULL, mapping, pos, len, len, page, NULL);
+ nr_dirty = nilfs_page_count_clean_buffers(&folio->page, from, to);
+ copied = block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL);
if (pos + copied > dir->i_size)
i_size_write(dir, pos + copied);
if (IS_DIRSYNC(dir))
nilfs_set_transaction_flag(NILFS_TI_SYNC);
err = nilfs_set_file_dirty(dir, nr_dirty);
WARN_ON(err); /* do not happen */
- unlock_page(page);
+ folio_unlock(folio);
}
static bool nilfs_check_folio(struct folio *folio, char *kaddr)
@@ -409,11 +408,11 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
int err;
folio_lock(folio);
- err = nilfs_prepare_chunk(&folio->page, from, to);
+ err = nilfs_prepare_chunk(folio, from, to);
BUG_ON(err);
de->inode = cpu_to_le64(inode->i_ino);
nilfs_set_de_type(de, inode);
- nilfs_commit_chunk(&folio->page, mapping, from, to);
+ nilfs_commit_chunk(folio, mapping, from, to);
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
}
@@ -485,7 +484,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
got_it:
from = offset_in_folio(folio, de);
to = from + rec_len;
- err = nilfs_prepare_chunk(&folio->page, from, to);
+ err = nilfs_prepare_chunk(folio, from, to);
if (err)
goto out_unlock;
if (de->inode) {
@@ -500,7 +499,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
memcpy(de->name, name, namelen);
de->inode = cpu_to_le64(inode->i_ino);
nilfs_set_de_type(de, inode);
- nilfs_commit_chunk(&folio->page, folio->mapping, from, to);
+ nilfs_commit_chunk(folio, folio->mapping, from, to);
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
nilfs_mark_inode_dirty(dir);
/* OFFSET_CACHE */
@@ -542,12 +541,12 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct folio *folio)
if (pde)
from = (char *)pde - kaddr;
folio_lock(folio);
- err = nilfs_prepare_chunk(&folio->page, from, to);
+ err = nilfs_prepare_chunk(folio, from, to);
BUG_ON(err);
if (pde)
pde->rec_len = nilfs_rec_len_to_disk(to - from);
dir->inode = 0;
- nilfs_commit_chunk(&folio->page, mapping, from, to);
+ nilfs_commit_chunk(folio, mapping, from, to);
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
out:
return err;
@@ -568,7 +567,7 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent)
if (IS_ERR(folio))
return PTR_ERR(folio);
- err = nilfs_prepare_chunk(&folio->page, 0, chunk_size);
+ err = nilfs_prepare_chunk(folio, 0, chunk_size);
if (unlikely(err)) {
folio_unlock(folio);
goto fail;
@@ -589,7 +588,7 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent)
memcpy(de->name, "..\0", 4);
nilfs_set_de_type(de, inode);
kunmap_local(kaddr);
- nilfs_commit_chunk(&folio->page, mapping, 0, chunk_size);
+ nilfs_commit_chunk(folio, mapping, 0, chunk_size);
fail:
folio_put(folio);
return err;
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 17/17] nilfs2: Convert nilfs_page_bug() to nilfs_folio_bug()
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
` (15 preceding siblings ...)
2023-11-27 14:30 ` [PATCH 16/17] nilfs2: Convert nilfs_prepare_chunk() and nilfs_commit_chunk() to folios Ryusuke Konishi
@ 2023-11-27 14:30 ` Ryusuke Konishi
16 siblings, 0 replies; 20+ messages in thread
From: Ryusuke Konishi @ 2023-11-27 14:30 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-nilfs, Matthew Wilcox, linux-kernel
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
All callers have a folio now, so convert it.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
---
fs/nilfs2/btnode.c | 4 ++--
fs/nilfs2/page.c | 25 +++++++++++++------------
fs/nilfs2/page.h | 6 +++---
3 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
index 1204dd06ead8..0131d83b912d 100644
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -190,7 +190,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
retry:
/* BUG_ON(oldkey != obh->b_folio->index); */
if (unlikely(oldkey != ofolio->index))
- NILFS_PAGE_BUG(&ofolio->page,
+ NILFS_FOLIO_BUG(ofolio,
"invalid oldkey %lld (newkey=%lld)",
(unsigned long long)oldkey,
(unsigned long long)newkey);
@@ -246,7 +246,7 @@ void nilfs_btnode_commit_change_key(struct address_space *btnc,
if (nbh == NULL) { /* blocksize == pagesize */
ofolio = obh->b_folio;
if (unlikely(oldkey != ofolio->index))
- NILFS_PAGE_BUG(&ofolio->page,
+ NILFS_FOLIO_BUG(ofolio,
"invalid oldkey %lld (newkey=%lld)",
(unsigned long long)oldkey,
(unsigned long long)newkey);
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 94e11bcee05b..5c2eba1987bd 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -150,29 +150,30 @@ bool nilfs_folio_buffers_clean(struct folio *folio)
return true;
}
-void nilfs_page_bug(struct page *page)
+void nilfs_folio_bug(struct folio *folio)
{
+ struct buffer_head *bh, *head;
struct address_space *m;
unsigned long ino;
- if (unlikely(!page)) {
- printk(KERN_CRIT "NILFS_PAGE_BUG(NULL)\n");
+ if (unlikely(!folio)) {
+ printk(KERN_CRIT "NILFS_FOLIO_BUG(NULL)\n");
return;
}
- m = page->mapping;
+ m = folio->mapping;
ino = m ? m->host->i_ino : 0;
- printk(KERN_CRIT "NILFS_PAGE_BUG(%p): cnt=%d index#=%llu flags=0x%lx "
+ printk(KERN_CRIT "NILFS_FOLIO_BUG(%p): cnt=%d index#=%llu flags=0x%lx "
"mapping=%p ino=%lu\n",
- page, page_ref_count(page),
- (unsigned long long)page->index, page->flags, m, ino);
+ folio, folio_ref_count(folio),
+ (unsigned long long)folio->index, folio->flags, m, ino);
- if (page_has_buffers(page)) {
- struct buffer_head *bh, *head;
+ head = folio_buffers(folio);
+ if (head) {
int i = 0;
- bh = head = page_buffers(page);
+ bh = head;
do {
printk(KERN_CRIT
" BH[%d] %p: cnt=%d block#=%llu state=0x%lx\n",
@@ -258,7 +259,7 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,
folio_lock(folio);
if (unlikely(!folio_test_dirty(folio)))
- NILFS_PAGE_BUG(&folio->page, "inconsistent dirty state");
+ NILFS_FOLIO_BUG(folio, "inconsistent dirty state");
dfolio = filemap_grab_folio(dmap, folio->index);
if (unlikely(IS_ERR(dfolio))) {
@@ -268,7 +269,7 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,
break;
}
if (unlikely(!folio_buffers(folio)))
- NILFS_PAGE_BUG(&folio->page,
+ NILFS_FOLIO_BUG(folio,
"found empty page in dat page cache");
nilfs_copy_folio(dfolio, folio, true);
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h
index 968b311d265b..7e1a2c455a10 100644
--- a/fs/nilfs2/page.h
+++ b/fs/nilfs2/page.h
@@ -37,7 +37,7 @@ struct buffer_head *nilfs_grab_buffer(struct inode *, struct address_space *,
void nilfs_forget_buffer(struct buffer_head *);
void nilfs_copy_buffer(struct buffer_head *, struct buffer_head *);
bool nilfs_folio_buffers_clean(struct folio *);
-void nilfs_page_bug(struct page *);
+void nilfs_folio_bug(struct folio *);
int nilfs_copy_dirty_pages(struct address_space *, struct address_space *);
void nilfs_copy_back_pages(struct address_space *, struct address_space *);
@@ -49,7 +49,7 @@ unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
sector_t start_blk,
sector_t *blkoff);
-#define NILFS_PAGE_BUG(page, m, a...) \
- do { nilfs_page_bug(page); BUG(); } while (0)
+#define NILFS_FOLIO_BUG(folio, m, a...) \
+ do { nilfs_folio_bug(folio); BUG(); } while (0)
#endif /* _NILFS_PAGE_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 01/17] nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link
2023-11-27 14:30 ` [PATCH 01/17] nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link Ryusuke Konishi
@ 2023-11-27 17:08 ` Matthew Wilcox
0 siblings, 0 replies; 20+ messages in thread
From: Matthew Wilcox @ 2023-11-27 17:08 UTC (permalink / raw)
To: Ryusuke Konishi; +Cc: Andrew Morton, linux-nilfs, linux-kernel
On Mon, Nov 27, 2023 at 11:30:20PM +0900, Ryusuke Konishi wrote:
> In a few directory operations, the call to nilfs_put_page() for a page
> obtained using nilfs_find_entry() or nilfs_dotdot() is hidden in
> nilfs_set_link() and nilfs_delete_entry(), making it difficult to track
> page release and preventing change of its call position.
>
> By moving nilfs_put_page() out of these functions, this makes the page
> get/put correspondence clearer and makes it easier to swap
> nilfs_put_page() calls (and kunmap calls within them) when modifying
> multiple directory entries simultaneously in nilfs_rename().
>
> Also, update comments for nilfs_set_link() and nilfs_delete_entry() to
> reflect changes in their behavior.
>
> To make nilfs_put_page() visible from namei.c, this moves its definition
> to nilfs.h and replaces existing equivalents to use it, but the exposure
> of that definition is temporary and will be removed on a later
> kmap -> kmap_local conversion.
>
> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
> Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Ah; I see. This makes it more like ext2, so I approve!
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 02/17] nilfs2: eliminate staggered calls to kunmap in nilfs_rename
2023-11-27 14:30 ` [PATCH 02/17] nilfs2: eliminate staggered calls to kunmap in nilfs_rename Ryusuke Konishi
@ 2023-11-27 17:08 ` Matthew Wilcox
0 siblings, 0 replies; 20+ messages in thread
From: Matthew Wilcox @ 2023-11-27 17:08 UTC (permalink / raw)
To: Ryusuke Konishi; +Cc: Andrew Morton, linux-nilfs, linux-kernel
On Mon, Nov 27, 2023 at 11:30:21PM +0900, Ryusuke Konishi wrote:
> In nilfs_rename(), calls to nilfs_put_page() to release pages obtained
> with nilfs_find_entry() or nilfs_dotdot() are alternated in the normal
> path.
>
> When replacing the kernel memory mapping method from kmap to
> kmap_local_{page,folio}, this violates the constraint on the calling
> order of kunmap_local().
>
> Swap the order of nilfs_put_page calls where the kmap sections of
> multiple pages overlap so that they are nested, allowing direct
> replacement of nilfs_put_page() -> unmap_and_put_page().
>
> Without this reordering, that replacement will cause a kernel WARNING
> in kunmap_local_indexed() on architectures with high memory mapping.
>
> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
> Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Thanks for catching this!
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2023-11-27 17:09 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-27 14:30 [PATCH 00/17] nilfs2: Folio conversions for directory paths Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 01/17] nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link Ryusuke Konishi
2023-11-27 17:08 ` Matthew Wilcox
2023-11-27 14:30 ` [PATCH 02/17] nilfs2: eliminate staggered calls to kunmap in nilfs_rename Ryusuke Konishi
2023-11-27 17:08 ` Matthew Wilcox
2023-11-27 14:30 ` [PATCH 03/17] nilfs2: Remove page_address() from nilfs_set_link Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 04/17] nilfs2: Remove page_address() from nilfs_add_link Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 05/17] nilfs2: Remove page_address() from nilfs_delete_entry Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 06/17] nilfs2: Return the mapped address from nilfs_get_page() Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 07/17] nilfs2: Pass the mapped address to nilfs_check_page() Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 08/17] nilfs2: Switch to kmap_local for directory handling Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 09/17] nilfs2: Add nilfs_get_folio() Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 10/17] nilfs2: Convert nilfs_readdir to use a folio Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 11/17] nilfs2: Convert nilfs_find_entry " Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 12/17] nilfs2: Convert nilfs_rename() to use folios Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 13/17] nilfs2: Convert nilfs_add_link() to use a folio Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 14/17] nilfs2: Convert nilfs_empty_dir() " Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 15/17] nilfs2: Convert nilfs_make_empty() " Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 16/17] nilfs2: Convert nilfs_prepare_chunk() and nilfs_commit_chunk() to folios Ryusuke Konishi
2023-11-27 14:30 ` [PATCH 17/17] nilfs2: Convert nilfs_page_bug() to nilfs_folio_bug() Ryusuke Konishi
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).