Please apply this series to the 6.6-stable tree.
This series makes it possible to backport the fix for the BUG_ON check failure on rename operations reported by syzbot.
The first two patches are for dependency resolution. Patch 3/3 is the target patch, and it has been tailored to avoid extensive page/folio conversion.
This patch set has been tested against the latest 6.6.y.
Thanks, Ryusuke Konishi
Ryusuke Konishi (3): nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link nilfs2: eliminate staggered calls to kunmap in nilfs_rename nilfs2: handle errors that nilfs_prepare_chunk() may return
fs/nilfs2/dir.c | 24 +++++++++++------------- fs/nilfs2/namei.c | 37 ++++++++++++++++++++----------------- fs/nilfs2/nilfs.h | 10 ++++++++-- 3 files changed, 39 insertions(+), 32 deletions(-)
commit 584db20c181f5e28c0386d7987406ace7fbd3e49 upstream.
Patch series "nilfs2: Folio conversions for directory paths".
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.
This patch (of 17):
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.
Link: https://lkml.kernel.org/r/20231127143036.2425-1-konishi.ryusuke@gmail.com Link: https://lkml.kernel.org/r/20231127143036.2425-2-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi konishi.ryusuke@gmail.com Reviewed-by: Matthew Wilcox (Oracle) willy@infradead.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Stable-dep-of: ee70999a988b ("nilfs2: handle errors that nilfs_prepare_chunk() may return") --- 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 652279c8b168..c6dd8ef7d284 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. @@ -450,7 +444,6 @@ int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino) return 0; }
-/* Releases the page */ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, struct page *page, struct inode *inode) { @@ -465,7 +458,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); dir->i_mtime = inode_set_ctime_current(dir); }
@@ -569,7 +561,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) { @@ -605,7 +597,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) nilfs_commit_chunk(page, mapping, from, to); inode->i_mtime = 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 ac0adeb58e41..819ce16c793e 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -297,6 +297,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;
@@ -406,6 +407,7 @@ static int nilfs_rename(struct mnt_idmap *idmap, 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) @@ -429,9 +431,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); @@ -441,13 +445,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 e2c5376b56cd..fbf74c1cfd1d 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -243,6 +243,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);
[ Sasha's backport helper bot ]
Hi,
Summary of potential issues and notes:
The upstream commit SHA1 provided is correct: 584db20c181f5e28c0386d7987406ace7fbd3e49
Note: The patch differs from the upstream commit: --- 1: 584db20c181f5 ! 1: 670766cc49f85 nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link @@ Metadata ## Commit message ## nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link
+ commit 584db20c181f5e28c0386d7987406ace7fbd3e49 upstream. + Patch series "nilfs2: Folio conversions for directory paths".
This series applies page->folio conversions to nilfs2 directory @@ Commit message sizes, both on machines with and without highmem mapping. No issues found.
- This patch (of 17):
In a few directory operations, the call to nilfs_put_page() for a page @@ Commit message Signed-off-by: Ryusuke Konishi konishi.ryusuke@gmail.com Reviewed-by: Matthew Wilcox (Oracle) willy@infradead.org Signed-off-by: Andrew Morton akpm@linux-foundation.org + Stable-dep-of: ee70999a988b ("nilfs2: handle errors that nilfs_prepare_chunk() may return")
## fs/nilfs2/dir.c ## @@ fs/nilfs2/dir.c: static inline unsigned int nilfs_chunk_size(struct inode *inode) @@ fs/nilfs2/dir.c: static inline unsigned int nilfs_chunk_size(struct inode *inode /* * Return the offset into page `page_nr' of the last valid * byte in that page, plus one. -@@ fs/nilfs2/dir.c: ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr) - return res; +@@ fs/nilfs2/dir.c: int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino) + return 0; }
-/* Releases the page */ @@ fs/nilfs2/dir.c: void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry * 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)); + dir->i_mtime = inode_set_ctime_current(dir); }
@@ fs/nilfs2/dir.c: int nilfs_add_link(struct dentry *dentry, struct inode *inode) @@ fs/nilfs2/dir.c: int nilfs_add_link(struct dentry *dentry, struct inode *inode) { @@ fs/nilfs2/dir.c: 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)); + inode->i_mtime = inode_set_ctime_current(inode); out: - nilfs_put_page(page); return err; @@ fs/nilfs2/namei.c: static int nilfs_do_unlink(struct inode *dir, struct dentry * goto out;
@@ fs/nilfs2/namei.c: 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); ---
Results of testing on various branches:
| Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-6.6.y | Success | Success |
commit 8cf57c6df818f58fdad16a909506be213623a88e upstream.
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.
Link: https://lkml.kernel.org/r/20231127143036.2425-3-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi konishi.ryusuke@gmail.com Reviewed-by: Matthew Wilcox (Oracle) willy@infradead.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Stable-dep-of: ee70999a988b ("nilfs2: handle errors that nilfs_prepare_chunk() may return") --- 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 819ce16c793e..4d60ccdd85f3 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -431,13 +431,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);
[ Sasha's backport helper bot ]
Hi,
Summary of potential issues and notes: ℹ️ This is part 2/3 of a series
The upstream commit SHA1 provided is correct: 8cf57c6df818f58fdad16a909506be213623a88e
Note: The patch differs from the upstream commit: --- 1: 8cf57c6df818f ! 1: 810716ff8329b nilfs2: eliminate staggered calls to kunmap in nilfs_rename @@ Metadata ## Commit message ## nilfs2: eliminate staggered calls to kunmap in nilfs_rename
+ commit 8cf57c6df818f58fdad16a909506be213623a88e upstream. + 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. @@ Commit message Signed-off-by: Ryusuke Konishi konishi.ryusuke@gmail.com Reviewed-by: Matthew Wilcox (Oracle) willy@infradead.org Signed-off-by: Andrew Morton akpm@linux-foundation.org + Stable-dep-of: ee70999a988b ("nilfs2: handle errors that nilfs_prepare_chunk() may return")
## fs/nilfs2/namei.c ## @@ fs/nilfs2/namei.c: static int nilfs_rename(struct mnt_idmap *idmap, ---
NOTE: These results are for this patch alone. Full series testing will be performed when all parts are received.
Results of testing on various branches:
| Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-6.6.y | Success | Success |
commit ee70999a988b8abc3490609142f50ebaa8344432 upstream.
Patch series "nilfs2: fix issues with rename operations".
This series fixes BUG_ON check failures reported by syzbot around rename operations, and a minor behavioral issue where the mtime of a child directory changes when it is renamed instead of moved.
This patch (of 2):
The directory manipulation routines nilfs_set_link() and nilfs_delete_entry() rewrite the directory entry in the folio/page previously read by nilfs_find_entry(), so error handling is omitted on the assumption that nilfs_prepare_chunk(), which prepares the buffer for rewriting, will always succeed for these. And if an error is returned, it triggers the legacy BUG_ON() checks in each routine.
This assumption is wrong, as proven by syzbot: the buffer layer called by nilfs_prepare_chunk() may call nilfs_get_block() if necessary, which may fail due to metadata corruption or other reasons. This has been there all along, but improved sanity checks and error handling may have made it more reproducible in fuzzing tests.
Fix this issue by adding missing error paths in nilfs_set_link(), nilfs_delete_entry(), and their caller nilfs_rename().
[konishi.ryusuke@gmail.com: adjusted for page/folio conversion] Link: https://lkml.kernel.org/r/20250111143518.7901-1-konishi.ryusuke@gmail.com Link: https://lkml.kernel.org/r/20250111143518.7901-2-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi konishi.ryusuke@gmail.com Reported-by: syzbot+32c3706ebf5d95046ea1@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=32c3706ebf5d95046ea1 Reported-by: syzbot+1097e95f134f37d9395c@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=1097e95f134f37d9395c Fixes: 2ba466d74ed7 ("nilfs2: directory entry operations") Signed-off-by: Andrew Morton akpm@linux-foundation.org --- fs/nilfs2/dir.c | 13 ++++++++++--- fs/nilfs2/namei.c | 29 +++++++++++++++-------------- fs/nilfs2/nilfs.h | 4 ++-- 3 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index c6dd8ef7d284..49ca762baa8f 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -444,7 +444,7 @@ int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino) return 0; }
-void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, +int 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); @@ -454,11 +454,15 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
lock_page(page); err = nilfs_prepare_chunk(page, from, to); - BUG_ON(err); + if (unlikely(err)) { + unlock_page(page); + return err; + } de->inode = cpu_to_le64(inode->i_ino); nilfs_set_de_type(de, inode); nilfs_commit_chunk(page, mapping, from, to); dir->i_mtime = inode_set_ctime_current(dir); + return 0; }
/* @@ -590,7 +594,10 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) from = (char *)pde - (char *)page_address(page); lock_page(page); err = nilfs_prepare_chunk(page, from, to); - BUG_ON(err); + if (unlikely(err)) { + unlock_page(page); + goto out; + } if (pde) pde->rec_len = nilfs_rec_len_to_disk(to - from); dir->inode = 0; diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 4d60ccdd85f3..43f01fe556fe 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -406,8 +406,10 @@ static int nilfs_rename(struct mnt_idmap *idmap, err = PTR_ERR(new_de); goto out_dir; } - nilfs_set_link(new_dir, new_de, new_page, old_inode); + err = nilfs_set_link(new_dir, new_de, new_page, old_inode); nilfs_put_page(new_page); + if (unlikely(err)) + goto out_dir; nilfs_mark_inode_dirty(new_dir); inode_set_ctime_current(new_inode); if (dir_de) @@ -430,28 +432,27 @@ static int nilfs_rename(struct mnt_idmap *idmap, */ inode_set_ctime_current(old_inode);
- nilfs_delete_entry(old_de, 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); + err = nilfs_delete_entry(old_de, old_page); + if (likely(!err)) { + if (dir_de) { + err = nilfs_set_link(old_inode, dir_de, dir_page, + new_dir); + drop_nlink(old_dir); + } + nilfs_mark_inode_dirty(old_dir); } - nilfs_put_page(old_page); - - nilfs_mark_inode_dirty(old_dir); nilfs_mark_inode_dirty(old_inode);
- err = nilfs_transaction_commit(old_dir->i_sb); - return err; - out_dir: if (dir_de) nilfs_put_page(dir_page); out_old: nilfs_put_page(old_page); out: - nilfs_transaction_abort(old_dir->i_sb); + if (likely(!err)) + err = nilfs_transaction_commit(old_dir->i_sb); + else + nilfs_transaction_abort(old_dir->i_sb); return err; }
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index fbf74c1cfd1d..4c4b76865484 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -240,8 +240,8 @@ 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_set_link(struct inode *dir, struct nilfs_dir_entry *de, + struct page *page, struct inode *inode);
static inline void nilfs_put_page(struct page *page) {
[ Sasha's backport helper bot ]
Hi,
Summary of potential issues and notes: ℹ️ This is part 3/3 of a series
The upstream commit SHA1 provided is correct: ee70999a988b8abc3490609142f50ebaa8344432
Note: The patch differs from the upstream commit: --- 1: ee70999a988b8 ! 1: 1d6894c5f5775 nilfs2: handle errors that nilfs_prepare_chunk() may return @@ Metadata ## Commit message ## nilfs2: handle errors that nilfs_prepare_chunk() may return
+ commit ee70999a988b8abc3490609142f50ebaa8344432 upstream. + Patch series "nilfs2: fix issues with rename operations".
This series fixes BUG_ON check failures reported by syzbot around rename operations, and a minor behavioral issue where the mtime of a child directory changes when it is renamed instead of moved.
- This patch (of 2):
The directory manipulation routines nilfs_set_link() and @@ Commit message Fix this issue by adding missing error paths in nilfs_set_link(), nilfs_delete_entry(), and their caller nilfs_rename().
+ [konishi.ryusuke@gmail.com: adjusted for page/folio conversion] Link: https://lkml.kernel.org/r/20250111143518.7901-1-konishi.ryusuke@gmail.com Link: https://lkml.kernel.org/r/20250111143518.7901-2-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi konishi.ryusuke@gmail.com @@ fs/nilfs2/dir.c: int nilfs_inode_by_name(struct inode *dir, const struct qstr *q
-void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, +int nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, - struct folio *folio, struct inode *inode) + struct page *page, struct inode *inode) { - size_t from = offset_in_folio(folio, de); + unsigned int from = (char *)de - (char *)page_address(page); @@ fs/nilfs2/dir.c: void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
- folio_lock(folio); - err = nilfs_prepare_chunk(folio, from, to); + lock_page(page); + err = nilfs_prepare_chunk(page, from, to); - BUG_ON(err); + if (unlikely(err)) { -+ folio_unlock(folio); ++ unlock_page(page); + return err; + } de->inode = cpu_to_le64(inode->i_ino); - de->file_type = fs_umode_to_ftype(inode->i_mode); - nilfs_commit_chunk(folio, mapping, from, to); - inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); + nilfs_set_de_type(de, inode); + nilfs_commit_chunk(page, mapping, from, to); + dir->i_mtime = inode_set_ctime_current(dir); + return 0; }
/* -@@ fs/nilfs2/dir.c: int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct folio *folio) - from = (char *)pde - kaddr; - folio_lock(folio); - err = nilfs_prepare_chunk(folio, from, to); +@@ fs/nilfs2/dir.c: int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) + from = (char *)pde - (char *)page_address(page); + lock_page(page); + err = nilfs_prepare_chunk(page, from, to); - BUG_ON(err); + if (unlikely(err)) { -+ folio_unlock(folio); ++ unlock_page(page); + goto out; + } if (pde) @@ fs/nilfs2/namei.c: static int nilfs_rename(struct mnt_idmap *idmap, err = PTR_ERR(new_de); goto out_dir; } -- nilfs_set_link(new_dir, new_de, new_folio, old_inode); -+ err = nilfs_set_link(new_dir, new_de, new_folio, old_inode); - folio_release_kmap(new_folio, new_de); +- nilfs_set_link(new_dir, new_de, new_page, old_inode); ++ err = nilfs_set_link(new_dir, new_de, new_page, old_inode); + nilfs_put_page(new_page); + if (unlikely(err)) + goto out_dir; nilfs_mark_inode_dirty(new_dir); @@ fs/nilfs2/namei.c: static int nilfs_rename(struct mnt_idmap *idmap, */ inode_set_ctime_current(old_inode);
-- nilfs_delete_entry(old_de, old_folio); +- nilfs_delete_entry(old_de, old_page); - - if (dir_de) { -- nilfs_set_link(old_inode, dir_de, dir_folio, new_dir); -- folio_release_kmap(dir_folio, dir_de); +- nilfs_set_link(old_inode, dir_de, dir_page, new_dir); +- nilfs_put_page(dir_page); - drop_nlink(old_dir); -+ err = nilfs_delete_entry(old_de, old_folio); ++ err = nilfs_delete_entry(old_de, old_page); + if (likely(!err)) { + if (dir_de) { -+ err = nilfs_set_link(old_inode, dir_de, dir_folio, ++ err = nilfs_set_link(old_inode, dir_de, dir_page, + new_dir); + drop_nlink(old_dir); + } + nilfs_mark_inode_dirty(old_dir); } -- folio_release_kmap(old_folio, old_de); +- nilfs_put_page(old_page); - - nilfs_mark_inode_dirty(old_dir); nilfs_mark_inode_dirty(old_inode); @@ fs/nilfs2/namei.c: static int nilfs_rename(struct mnt_idmap *idmap, - out_dir: if (dir_de) - folio_release_kmap(dir_folio, dir_de); + nilfs_put_page(dir_page); out_old: - folio_release_kmap(old_folio, old_de); + nilfs_put_page(old_page); out: - nilfs_transaction_abort(old_dir->i_sb); + if (likely(!err)) @@ fs/nilfs2/namei.c: static int nilfs_rename(struct mnt_idmap *idmap,
## fs/nilfs2/nilfs.h ## -@@ fs/nilfs2/nilfs.h: struct nilfs_dir_entry *nilfs_find_entry(struct inode *, const struct qstr *, - 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 *); +@@ fs/nilfs2/nilfs.h: 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_set_link(struct inode *dir, struct nilfs_dir_entry *de, -+ struct folio *folio, struct inode *inode); ++ struct page *page, struct inode *inode);
- /* file.c */ - extern int nilfs_sync_file(struct file *, loff_t, loff_t, int); + static inline void nilfs_put_page(struct page *page) + { ---
NOTE: These results are for this patch alone. Full series testing will be performed when all parts are received.
Results of testing on various branches:
| Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-6.6.y | Success | Success |
linux-stable-mirror@lists.linaro.org