* [PATCH 1/7] mm: don't look at xarray value entries in split_huge_pages_in_file
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
@ 2023-01-21 6:57 ` Christoph Hellwig
2023-01-21 6:57 ` [PATCH 2/7] mm: make mapping_get_entry available outside of filemap.c Christoph Hellwig
` (7 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 6:57 UTC (permalink / raw)
To: Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs
split_huge_pages_in_file never wants to do anything with the special
value enties. Switch to using filemap_get_folio to not even see them.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
mm/huge_memory.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 1d6977dc6b31ba..a2830019aaa017 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3100,11 +3100,10 @@ static int split_huge_pages_in_file(const char *file_path, pgoff_t off_start,
mapping = candidate->f_mapping;
for (index = off_start; index < off_end; index += nr_pages) {
- struct folio *folio = __filemap_get_folio(mapping, index,
- FGP_ENTRY, 0);
+ struct folio *folio = filemap_get_folio(mapping, index);
nr_pages = 1;
- if (xa_is_value(folio) || !folio)
+ if (!folio)
continue;
if (!folio_test_large(folio))
--
2.39.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 2/7] mm: make mapping_get_entry available outside of filemap.c
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
2023-01-21 6:57 ` [PATCH 1/7] mm: don't look at xarray value entries in split_huge_pages_in_file Christoph Hellwig
@ 2023-01-21 6:57 ` Christoph Hellwig
2023-01-21 6:57 ` [PATCH 3/7] mm: use filemap_get_entry in filemap_get_incore_folio Christoph Hellwig
` (6 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 6:57 UTC (permalink / raw)
To: Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs
mapping_get_entry is useful for page cache API users that need to know
about xa_value internals. Rename it and make it available in pagemap.h.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
include/linux/pagemap.h | 1 +
mm/filemap.c | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 9f108168377195..24dedf6b12be49 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -507,6 +507,7 @@ pgoff_t page_cache_prev_miss(struct address_space *mapping,
#define FGP_ENTRY 0x00000080
#define FGP_STABLE 0x00000100
+void *filemap_get_entry(struct address_space *mapping, pgoff_t index);
struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
int fgp_flags, gfp_t gfp);
struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
diff --git a/mm/filemap.c b/mm/filemap.c
index c915ded191f03f..ed0583f9e27512 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1834,7 +1834,7 @@ EXPORT_SYMBOL(page_cache_prev_miss);
*/
/*
- * mapping_get_entry - Get a page cache entry.
+ * filemap_get_entry - Get a page cache entry.
* @mapping: the address_space to search
* @index: The page cache index.
*
@@ -1845,7 +1845,7 @@ EXPORT_SYMBOL(page_cache_prev_miss);
*
* Return: The folio, swap or shadow entry, %NULL if nothing is found.
*/
-static void *mapping_get_entry(struct address_space *mapping, pgoff_t index)
+void *filemap_get_entry(struct address_space *mapping, pgoff_t index)
{
XA_STATE(xas, &mapping->i_pages, index);
struct folio *folio;
@@ -1915,7 +1915,7 @@ struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
struct folio *folio;
repeat:
- folio = mapping_get_entry(mapping, index);
+ folio = filemap_get_entry(mapping, index);
if (xa_is_value(folio)) {
if (fgp_flags & FGP_ENTRY)
return folio;
--
2.39.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 3/7] mm: use filemap_get_entry in filemap_get_incore_folio
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
2023-01-21 6:57 ` [PATCH 1/7] mm: don't look at xarray value entries in split_huge_pages_in_file Christoph Hellwig
2023-01-21 6:57 ` [PATCH 2/7] mm: make mapping_get_entry available outside of filemap.c Christoph Hellwig
@ 2023-01-21 6:57 ` Christoph Hellwig
2023-01-21 6:57 ` [PATCH 4/7] shmem: remove shmem_get_partial_folio Christoph Hellwig
` (5 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 6:57 UTC (permalink / raw)
To: Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs
filemap_get_incore_folio wants to look at the details of xa_is_value
entries, but doesn't need any of the other logic in filemap_get_folio.
Switch it to use the lower-level filemap_get_entry interface.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
mm/swap_state.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 7a003d8abb37bc..92234f4b51d29a 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -386,7 +386,7 @@ struct folio *filemap_get_incore_folio(struct address_space *mapping,
{
swp_entry_t swp;
struct swap_info_struct *si;
- struct folio *folio = __filemap_get_folio(mapping, index, FGP_ENTRY, 0);
+ struct folio *folio = filemap_get_entry(mapping, index);
if (!xa_is_value(folio))
goto out;
--
2.39.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 4/7] shmem: remove shmem_get_partial_folio
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
` (2 preceding siblings ...)
2023-01-21 6:57 ` [PATCH 3/7] mm: use filemap_get_entry in filemap_get_incore_folio Christoph Hellwig
@ 2023-01-21 6:57 ` Christoph Hellwig
2023-01-21 6:57 ` [PATCH 5/7] shmem: open code the page cache lookup in shmem_get_folio_gfp Christoph Hellwig
` (4 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 6:57 UTC (permalink / raw)
To: Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs
Add a new SGP_FIND mode for shmem_get_partial_folio that works like
SGP_READ, but does not check i_size. Use that instead of open coding
the page cache lookup in shmem_get_partial_folio. Note that this is
a behavior change in that it reads in swap cache entries for offsets
outside i_size, possibly causing a little bit of extra work.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/shmem_fs.h | 1 +
mm/shmem.c | 46 ++++++++++++----------------------------
2 files changed, 15 insertions(+), 32 deletions(-)
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index d09d54be4ffd99..7ba160ac066e5e 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -105,6 +105,7 @@ enum sgp_type {
SGP_CACHE, /* don't exceed i_size, may allocate page */
SGP_WRITE, /* may exceed i_size, may allocate !Uptodate page */
SGP_FALLOC, /* like SGP_WRITE, but make existing page Uptodate */
+ SGP_FIND, /* like SGP_READ, but also read outside i_size */
};
int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
diff --git a/mm/shmem.c b/mm/shmem.c
index de6fa3980c7d6b..a8371ffeeee54a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -877,27 +877,6 @@ void shmem_unlock_mapping(struct address_space *mapping)
}
}
-static struct folio *shmem_get_partial_folio(struct inode *inode, pgoff_t index)
-{
- struct folio *folio;
-
- /*
- * At first avoid shmem_get_folio(,,,SGP_READ): that fails
- * beyond i_size, and reports fallocated pages as holes.
- */
- folio = __filemap_get_folio(inode->i_mapping, index,
- FGP_ENTRY | FGP_LOCK, 0);
- if (!xa_is_value(folio))
- return folio;
- /*
- * But read a page back from swap if any of it is within i_size
- * (although in some cases this is just a waste of time).
- */
- folio = NULL;
- shmem_get_folio(inode, index, &folio, SGP_READ);
- return folio;
-}
-
/*
* Remove range of pages and swap entries from page cache, and free them.
* If !unfalloc, truncate or punch hole; if unfalloc, undo failed fallocate.
@@ -957,7 +936,8 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
goto whole_folios;
same_folio = (lstart >> PAGE_SHIFT) == (lend >> PAGE_SHIFT);
- folio = shmem_get_partial_folio(inode, lstart >> PAGE_SHIFT);
+ folio = NULL;
+ shmem_get_folio(inode, lstart >> PAGE_SHIFT, &folio, SGP_FIND);
if (folio) {
same_folio = lend < folio_pos(folio) + folio_size(folio);
folio_mark_dirty(folio);
@@ -971,14 +951,16 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
folio = NULL;
}
- if (!same_folio)
- folio = shmem_get_partial_folio(inode, lend >> PAGE_SHIFT);
- if (folio) {
- folio_mark_dirty(folio);
- if (!truncate_inode_partial_folio(folio, lstart, lend))
- end = folio->index;
- folio_unlock(folio);
- folio_put(folio);
+ if (!same_folio) {
+ folio = NULL;
+ shmem_get_folio(inode, lend >> PAGE_SHIFT, &folio, SGP_FIND);
+ if (folio) {
+ folio_mark_dirty(folio);
+ if (!truncate_inode_partial_folio(folio, lstart, lend))
+ end = folio->index;
+ folio_unlock(folio);
+ folio_put(folio);
+ }
}
whole_folios:
@@ -1900,7 +1882,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
if (folio_test_uptodate(folio))
goto out;
/* fallocated folio */
- if (sgp != SGP_READ)
+ if (sgp != SGP_READ && sgp != SGP_FIND)
goto clear;
folio_unlock(folio);
folio_put(folio);
@@ -1911,7 +1893,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
* SGP_NOALLOC: fail on hole, with NULL folio, letting caller fail.
*/
*foliop = NULL;
- if (sgp == SGP_READ)
+ if (sgp == SGP_READ || sgp == SGP_FIND)
return 0;
if (sgp == SGP_NOALLOC)
return -ENOENT;
--
2.39.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 5/7] shmem: open code the page cache lookup in shmem_get_folio_gfp
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
` (3 preceding siblings ...)
2023-01-21 6:57 ` [PATCH 4/7] shmem: remove shmem_get_partial_folio Christoph Hellwig
@ 2023-01-21 6:57 ` Christoph Hellwig
2023-01-21 6:57 ` [PATCH 6/7] mm: remove FGP_ENTRY Christoph Hellwig
` (3 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 6:57 UTC (permalink / raw)
To: Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs
Use the very low level filemap_get_entry helper to look up the
entry in the xarray, and then:
- don't bother locking the folio if only doing a userfault notification
- open code locking the page and checking for truncation in a related
code block
This will allow to eventually remove the FGP_ENTRY flag.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/shmem.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index a8371ffeeee54a..23d5cf8182cb1f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1856,12 +1856,10 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
sbinfo = SHMEM_SB(inode->i_sb);
charge_mm = vma ? vma->vm_mm : NULL;
- folio = __filemap_get_folio(mapping, index, FGP_ENTRY | FGP_LOCK, 0);
+ folio = filemap_get_entry(mapping, index);
if (folio && vma && userfaultfd_minor(vma)) {
- if (!xa_is_value(folio)) {
- folio_unlock(folio);
+ if (!xa_is_value(folio))
folio_put(folio);
- }
*fault_type = handle_userfault(vmf, VM_UFFD_MINOR);
return 0;
}
@@ -1877,6 +1875,14 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
}
if (folio) {
+ folio_lock(folio);
+
+ /* Has the page been truncated? */
+ if (unlikely(folio->mapping != mapping)) {
+ folio_unlock(folio);
+ folio_put(folio);
+ goto repeat;
+ }
if (sgp == SGP_WRITE)
folio_mark_accessed(folio);
if (folio_test_uptodate(folio))
--
2.39.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 6/7] mm: remove FGP_ENTRY
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
` (4 preceding siblings ...)
2023-01-21 6:57 ` [PATCH 5/7] shmem: open code the page cache lookup in shmem_get_folio_gfp Christoph Hellwig
@ 2023-01-21 6:57 ` Christoph Hellwig
2023-01-21 6:57 ` [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio Christoph Hellwig
` (2 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 6:57 UTC (permalink / raw)
To: Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs
FGP_ENTRY is unused now, so remove it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/pagemap.h | 3 +--
mm/filemap.c | 7 +------
mm/folio-compat.c | 4 ++--
3 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 24dedf6b12be49..e2208ee36966ea 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -504,8 +504,7 @@ pgoff_t page_cache_prev_miss(struct address_space *mapping,
#define FGP_NOFS 0x00000010
#define FGP_NOWAIT 0x00000020
#define FGP_FOR_MMAP 0x00000040
-#define FGP_ENTRY 0x00000080
-#define FGP_STABLE 0x00000100
+#define FGP_STABLE 0x00000080
void *filemap_get_entry(struct address_space *mapping, pgoff_t index);
struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
diff --git a/mm/filemap.c b/mm/filemap.c
index ed0583f9e27512..35baadd130795c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1889,8 +1889,6 @@ void *filemap_get_entry(struct address_space *mapping, pgoff_t index)
*
* * %FGP_ACCESSED - The folio will be marked accessed.
* * %FGP_LOCK - The folio is returned locked.
- * * %FGP_ENTRY - If there is a shadow / swap / DAX entry, return it
- * instead of allocating a new folio to replace it.
* * %FGP_CREAT - If no page is present then a new page is allocated using
* @gfp and added to the page cache and the VM's LRU list.
* The page is returned locked and with an increased refcount.
@@ -1916,11 +1914,8 @@ struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
repeat:
folio = filemap_get_entry(mapping, index);
- if (xa_is_value(folio)) {
- if (fgp_flags & FGP_ENTRY)
- return folio;
+ if (xa_is_value(folio))
folio = NULL;
- }
if (!folio)
goto no_page;
diff --git a/mm/folio-compat.c b/mm/folio-compat.c
index 18c48b55792635..f3841b4977b68e 100644
--- a/mm/folio-compat.c
+++ b/mm/folio-compat.c
@@ -97,8 +97,8 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
struct folio *folio;
folio = __filemap_get_folio(mapping, index, fgp_flags, gfp);
- if (!folio || xa_is_value(folio))
- return &folio->page;
+ if (!folio)
+ return NULL;
return folio_file_page(folio, index);
}
EXPORT_SYMBOL(pagecache_get_page);
--
2.39.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
` (5 preceding siblings ...)
2023-01-21 6:57 ` [PATCH 6/7] mm: remove FGP_ENTRY Christoph Hellwig
@ 2023-01-21 6:57 ` Christoph Hellwig
2023-01-21 11:52 ` kernel test robot
` (3 more replies)
2023-01-22 1:06 ` return an ERR_PTR from __filemap_get_folio v2 Andrew Morton
2023-03-28 23:04 ` Andrew Morton
8 siblings, 4 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 6:57 UTC (permalink / raw)
To: Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs
Instead of returning NULL for all errors, distinguish between:
- no entry found and not asked to allocated (-ENOENT)
- failed to allocate memory (-ENOMEM)
- would block (-EAGAIN)
so that callers don't have to guess the error based on the passed
in flags.
Also pass through the error through the direct callers:
filemap_get_folio, filemap_lock_folio filemap_grab_folio
and filemap_get_incore_folio.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/afs/dir.c | 10 +++++-----
fs/afs/dir_edit.c | 2 +-
fs/afs/write.c | 4 ++--
fs/btrfs/disk-io.c | 2 +-
fs/ext4/inode.c | 2 +-
fs/ext4/move_extent.c | 8 ++++----
fs/hugetlbfs/inode.c | 2 +-
fs/iomap/buffered-io.c | 15 ++-------------
fs/netfs/buffered_read.c | 4 ++--
fs/nilfs2/page.c | 6 +++---
include/linux/pagemap.h | 11 ++++++-----
mm/filemap.c | 14 ++++++++------
mm/folio-compat.c | 2 +-
mm/huge_memory.c | 2 +-
mm/memcontrol.c | 2 +-
mm/mincore.c | 2 +-
mm/shmem.c | 4 ++--
mm/swap_state.c | 15 ++++++++-------
mm/swapfile.c | 4 ++--
mm/truncate.c | 15 ++++++++-------
20 files changed, 60 insertions(+), 66 deletions(-)
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 82690d1dd49a02..f92b9e62d567b9 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -319,16 +319,16 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
struct folio *folio;
folio = filemap_get_folio(mapping, i);
- if (!folio) {
+ if (IS_ERR(folio)) {
if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
afs_stat_v(dvnode, n_inval);
-
- ret = -ENOMEM;
folio = __filemap_get_folio(mapping,
i, FGP_LOCK | FGP_CREAT,
mapping->gfp_mask);
- if (!folio)
+ if (IS_ERR(folio)) {
+ ret = PTR_ERR(folio);
goto error;
+ }
folio_attach_private(folio, (void *)1);
folio_unlock(folio);
}
@@ -524,7 +524,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
*/
folio = __filemap_get_folio(dir->i_mapping, ctx->pos / PAGE_SIZE,
FGP_ACCESSED, 0);
- if (!folio) {
+ if (IS_ERR(folio)) {
ret = afs_bad(dvnode, afs_file_error_dir_missing_page);
break;
}
diff --git a/fs/afs/dir_edit.c b/fs/afs/dir_edit.c
index 0ab7752d1b758e..f0eddccbdd9541 100644
--- a/fs/afs/dir_edit.c
+++ b/fs/afs/dir_edit.c
@@ -115,7 +115,7 @@ static struct folio *afs_dir_get_folio(struct afs_vnode *vnode, pgoff_t index)
folio = __filemap_get_folio(mapping, index,
FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
mapping->gfp_mask);
- if (!folio)
+ if (IS_ERR(folio))
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
else if (folio && !folio_test_private(folio))
folio_attach_private(folio, (void *)1);
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 2d3b08b7406ca7..cf1eb0d122c275 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -232,7 +232,7 @@ static void afs_kill_pages(struct address_space *mapping,
_debug("kill %lx (to %lx)", index, last);
folio = filemap_get_folio(mapping, index);
- if (!folio) {
+ if (IS_ERR(folio)) {
next = index + 1;
continue;
}
@@ -270,7 +270,7 @@ static void afs_redirty_pages(struct writeback_control *wbc,
_debug("redirty %llx @%llx", len, start);
folio = filemap_get_folio(mapping, index);
- if (!folio) {
+ if (IS_ERR(folio)) {
next = index + 1;
continue;
}
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 27abe8fdfd92b3..e888abee119fd6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4037,7 +4037,7 @@ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
folio = filemap_get_folio(device->bdev->bd_inode->i_mapping,
bytenr >> PAGE_SHIFT);
- if (!folio) {
+ if (IS_ERR(folio)) {
errors++;
if (i == 0)
primary_failed = true;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0f6f24bb8e8fba..b4c65e6aa360d2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5391,7 +5391,7 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode)
while (1) {
struct folio *folio = filemap_lock_folio(inode->i_mapping,
inode->i_size >> PAGE_SHIFT);
- if (!folio)
+ if (IS_ERR(folio))
return;
ret = __ext4_journalled_invalidate_folio(folio, offset,
folio_size(folio) - offset);
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 2de9829aed63bf..7bf6d069199cbb 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -141,18 +141,18 @@ mext_folio_double_lock(struct inode *inode1, struct inode *inode2,
flags = memalloc_nofs_save();
folio[0] = __filemap_get_folio(mapping[0], index1, fgp_flags,
mapping_gfp_mask(mapping[0]));
- if (!folio[0]) {
+ if (IS_ERR(folio[0])) {
memalloc_nofs_restore(flags);
- return -ENOMEM;
+ return PTR_ERR(folio[0]);
}
folio[1] = __filemap_get_folio(mapping[1], index2, fgp_flags,
mapping_gfp_mask(mapping[1]));
memalloc_nofs_restore(flags);
- if (!folio[1]) {
+ if (IS_ERR(folio[1])) {
folio_unlock(folio[0]);
folio_put(folio[0]);
- return -ENOMEM;
+ return PTR_ERR(folio[1]);
}
/*
* __filemap_get_folio() may not wait on folio's writeback if
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index fb810664448787..6cac1b92520af1 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -697,7 +697,7 @@ static void hugetlbfs_zero_partial_page(struct hstate *h,
struct folio *folio;
folio = filemap_lock_folio(mapping, idx);
- if (!folio)
+ if (IS_ERR(folio))
return;
start = start & ~huge_page_mask(h);
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index d3c300563eb8ff..94a4d2e66ac66d 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -468,19 +468,12 @@ EXPORT_SYMBOL_GPL(iomap_is_partially_uptodate);
struct folio *iomap_get_folio(struct iomap_iter *iter, loff_t pos)
{
unsigned fgp = FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE | FGP_NOFS;
- struct folio *folio;
if (iter->flags & IOMAP_NOWAIT)
fgp |= FGP_NOWAIT;
- folio = __filemap_get_folio(iter->inode->i_mapping, pos >> PAGE_SHIFT,
+ return __filemap_get_folio(iter->inode->i_mapping, pos >> PAGE_SHIFT,
fgp, mapping_gfp_mask(iter->inode->i_mapping));
- if (folio)
- return folio;
-
- if (iter->flags & IOMAP_NOWAIT)
- return ERR_PTR(-EAGAIN);
- return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL_GPL(iomap_get_folio);
@@ -653,10 +646,6 @@ static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
if (!mapping_large_folio_support(iter->inode->i_mapping))
len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
- folio = __iomap_get_folio(iter, pos, len);
- if (IS_ERR(folio))
- return PTR_ERR(folio);
-
/*
* Now we have a locked folio, before we do anything with it we need to
* check that the iomap we have cached is not stale. The inode extent
@@ -911,7 +900,7 @@ static int iomap_write_delalloc_scan(struct inode *inode,
/* grab locked page */
folio = filemap_lock_folio(inode->i_mapping,
start_byte >> PAGE_SHIFT);
- if (!folio) {
+ if (IS_ERR(folio)) {
start_byte = ALIGN_DOWN(start_byte, PAGE_SIZE) +
PAGE_SIZE;
continue;
diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c
index 7679a68e819307..209726a9cfdb9c 100644
--- a/fs/netfs/buffered_read.c
+++ b/fs/netfs/buffered_read.c
@@ -350,8 +350,8 @@ int netfs_write_begin(struct netfs_inode *ctx,
retry:
folio = __filemap_get_folio(mapping, index, fgp_flags,
mapping_gfp_mask(mapping));
- if (!folio)
- return -ENOMEM;
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
if (ctx->ops->check_write_begin) {
/* Allow the netfs (eg. ceph) to flush conflicts. */
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 41ccd43cd9797f..5cf30827f244c4 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -259,10 +259,10 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,
NILFS_PAGE_BUG(&folio->page, "inconsistent dirty state");
dfolio = filemap_grab_folio(dmap, folio->index);
- if (unlikely(!dfolio)) {
+ if (unlikely(IS_ERR(dfolio))) {
/* No empty page is added to the page cache */
- err = -ENOMEM;
folio_unlock(folio);
+ err = PTR_ERR(dfolio);
break;
}
if (unlikely(!folio_buffers(folio)))
@@ -311,7 +311,7 @@ void nilfs_copy_back_pages(struct address_space *dmap,
folio_lock(folio);
dfolio = filemap_lock_folio(dmap, index);
- if (dfolio) {
+ if (!IS_ERR(dfolio)) {
/* overwrite existing folio in the destination cache */
WARN_ON(folio_test_dirty(dfolio));
nilfs_copy_page(&dfolio->page, &folio->page, 0);
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index e2208ee36966ea..6e07ba2ef18327 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -520,7 +520,8 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
* Looks up the page cache entry at @mapping & @index. If a folio is
* present, it is returned with an increased refcount.
*
- * Otherwise, %NULL is returned.
+ * Return: A folio or ERR_PTR(-ENOENT) if there is no folio in the cache for
+ * this index. Will not return a shadow, swap or DAX entry.
*/
static inline struct folio *filemap_get_folio(struct address_space *mapping,
pgoff_t index)
@@ -537,8 +538,8 @@ static inline struct folio *filemap_get_folio(struct address_space *mapping,
* present, it is returned locked with an increased refcount.
*
* Context: May sleep.
- * Return: A folio or %NULL if there is no folio in the cache for this
- * index. Will not return a shadow, swap or DAX entry.
+ * Return: A folio or ERR_PTR(-ENOENT) if there is no folio in the cache for
+ * this index. Will not return a shadow, swap or DAX entry.
*/
static inline struct folio *filemap_lock_folio(struct address_space *mapping,
pgoff_t index)
@@ -555,8 +556,8 @@ static inline struct folio *filemap_lock_folio(struct address_space *mapping,
* a new folio is created. The folio is locked, marked as accessed, and
* returned.
*
- * Return: A found or created folio. NULL if no folio is found and failed to
- * create a folio.
+ * Return: A found or created folio. ERR_PTR(-ENOMEM) if no folio is found
+ * and failed to create a folio.
*/
static inline struct folio *filemap_grab_folio(struct address_space *mapping,
pgoff_t index)
diff --git a/mm/filemap.c b/mm/filemap.c
index 35baadd130795c..4037a132f7adcc 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1905,7 +1905,7 @@ void *filemap_get_entry(struct address_space *mapping, pgoff_t index)
*
* If there is a page cache page, it is returned with an increased refcount.
*
- * Return: The found folio or %NULL otherwise.
+ * Return: The found folio or an ERR_PTR() otherwise.
*/
struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
int fgp_flags, gfp_t gfp)
@@ -1923,7 +1923,7 @@ struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
if (fgp_flags & FGP_NOWAIT) {
if (!folio_trylock(folio)) {
folio_put(folio);
- return NULL;
+ return ERR_PTR(-EAGAIN);
}
} else {
folio_lock(folio);
@@ -1962,7 +1962,7 @@ struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
folio = filemap_alloc_folio(gfp, 0);
if (!folio)
- return NULL;
+ return ERR_PTR(-ENOMEM);
if (WARN_ON_ONCE(!(fgp_flags & (FGP_LOCK | FGP_FOR_MMAP))))
fgp_flags |= FGP_LOCK;
@@ -1987,6 +1987,8 @@ struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
folio_unlock(folio);
}
+ if (!folio)
+ return ERR_PTR(-ENOENT);
return folio;
}
EXPORT_SYMBOL(__filemap_get_folio);
@@ -3126,7 +3128,7 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
* Do we have something in the page cache already?
*/
folio = filemap_get_folio(mapping, index);
- if (likely(folio)) {
+ if (likely(!IS_ERR(folio))) {
/*
* We found the page, so try async readahead before waiting for
* the lock.
@@ -3155,7 +3157,7 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
folio = __filemap_get_folio(mapping, index,
FGP_CREAT|FGP_FOR_MMAP,
vmf->gfp_mask);
- if (!folio) {
+ if (IS_ERR(folio)) {
if (fpin)
goto out_retry;
filemap_invalidate_unlock_shared(mapping);
@@ -3506,7 +3508,7 @@ static struct folio *do_read_cache_folio(struct address_space *mapping,
filler = mapping->a_ops->read_folio;
repeat:
folio = filemap_get_folio(mapping, index);
- if (!folio) {
+ if (IS_ERR(folio)) {
folio = filemap_alloc_folio(gfp, 0);
if (!folio)
return ERR_PTR(-ENOMEM);
diff --git a/mm/folio-compat.c b/mm/folio-compat.c
index f3841b4977b68e..4cd173336d8589 100644
--- a/mm/folio-compat.c
+++ b/mm/folio-compat.c
@@ -97,7 +97,7 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
struct folio *folio;
folio = __filemap_get_folio(mapping, index, fgp_flags, gfp);
- if (!folio)
+ if (IS_ERR(folio))
return NULL;
return folio_file_page(folio, index);
}
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index a2830019aaa017..b0c9170632e37c 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3103,7 +3103,7 @@ static int split_huge_pages_in_file(const char *file_path, pgoff_t off_start,
struct folio *folio = filemap_get_folio(mapping, index);
nr_pages = 1;
- if (!folio)
+ if (IS_ERR(folio))
continue;
if (!folio_test_large(folio))
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 17335459d8dc72..7ecebdd2c23391 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5689,7 +5689,7 @@ static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
/* shmem/tmpfs may report page out on swap: account for that too. */
index = linear_page_index(vma, addr);
folio = filemap_get_incore_folio(vma->vm_file->f_mapping, index);
- if (!folio)
+ if (IS_ERR(folio))
return NULL;
return folio_file_page(folio, index);
}
diff --git a/mm/mincore.c b/mm/mincore.c
index cd69b9db008126..5437e584b208bf 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -61,7 +61,7 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t index)
* tmpfs's .fault). So swapped out tmpfs mappings are tested here.
*/
folio = filemap_get_incore_folio(mapping, index);
- if (folio) {
+ if (!IS_ERR(folio)) {
present = folio_test_uptodate(folio);
folio_put(folio);
}
diff --git a/mm/shmem.c b/mm/shmem.c
index 23d5cf8182cb1f..8589ab4abd2b11 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -603,7 +603,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
index = (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT;
folio = filemap_get_folio(inode->i_mapping, index);
- if (!folio)
+ if (IS_ERR(folio))
goto drop;
/* No huge page at the end of the file: nothing to split */
@@ -3187,7 +3187,7 @@ static const char *shmem_get_link(struct dentry *dentry,
if (!dentry) {
folio = filemap_get_folio(inode->i_mapping, 0);
- if (!folio)
+ if (IS_ERR(folio))
return ERR_PTR(-ECHILD);
if (PageHWPoison(folio_page(folio, 0)) ||
!folio_test_uptodate(folio)) {
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 92234f4b51d29a..c7160070b9daa9 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -336,7 +336,7 @@ struct folio *swap_cache_get_folio(swp_entry_t entry,
struct folio *folio;
folio = filemap_get_folio(swap_address_space(entry), swp_offset(entry));
- if (folio) {
+ if (!IS_ERR(folio)) {
bool vma_ra = swap_use_vma_readahead();
bool readahead;
@@ -366,6 +366,8 @@ struct folio *swap_cache_get_folio(swp_entry_t entry,
if (!vma || !vma_ra)
atomic_inc(&swapin_readahead_hits);
}
+ } else {
+ folio = NULL;
}
return folio;
@@ -389,22 +391,21 @@ struct folio *filemap_get_incore_folio(struct address_space *mapping,
struct folio *folio = filemap_get_entry(mapping, index);
if (!xa_is_value(folio))
- goto out;
+ return folio;
if (!shmem_mapping(mapping))
- return NULL;
+ return ERR_PTR(-ENOENT);
swp = radix_to_swp_entry(folio);
/* There might be swapin error entries in shmem mapping. */
if (non_swap_entry(swp))
- return NULL;
+ return ERR_PTR(-ENOENT);
/* Prevent swapoff from happening to us */
si = get_swap_device(swp);
if (!si)
- return NULL;
+ return ERR_PTR(-ENOENT);
index = swp_offset(swp);
folio = filemap_get_folio(swap_address_space(swp), index);
put_swap_device(si);
-out:
return folio;
}
@@ -431,7 +432,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
folio = filemap_get_folio(swap_address_space(entry),
swp_offset(entry));
put_swap_device(si);
- if (folio)
+ if (!IS_ERR(folio))
return folio_file_page(folio, swp_offset(entry));
/*
diff --git a/mm/swapfile.c b/mm/swapfile.c
index a5729273480e07..a128b61b6b8c91 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -136,7 +136,7 @@ static int __try_to_reclaim_swap(struct swap_info_struct *si,
int ret = 0;
folio = filemap_get_folio(swap_address_space(entry), offset);
- if (!folio)
+ if (IS_ERR(folio))
return 0;
/*
* When this function is called from scan_swap_map_slots() and it's
@@ -2096,7 +2096,7 @@ static int try_to_unuse(unsigned int type)
entry = swp_entry(type, i);
folio = filemap_get_folio(swap_address_space(entry), i);
- if (!folio)
+ if (IS_ERR(folio))
continue;
/*
diff --git a/mm/truncate.c b/mm/truncate.c
index 7b4ea4c4a46b20..86de31ed4d3238 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -375,7 +375,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
same_folio = (lstart >> PAGE_SHIFT) == (lend >> PAGE_SHIFT);
folio = __filemap_get_folio(mapping, lstart >> PAGE_SHIFT, FGP_LOCK, 0);
- if (folio) {
+ if (!IS_ERR(folio)) {
same_folio = lend < folio_pos(folio) + folio_size(folio);
if (!truncate_inode_partial_folio(folio, lstart, lend)) {
start = folio->index + folio_nr_pages(folio);
@@ -387,14 +387,15 @@ void truncate_inode_pages_range(struct address_space *mapping,
folio = NULL;
}
- if (!same_folio)
+ if (!same_folio) {
folio = __filemap_get_folio(mapping, lend >> PAGE_SHIFT,
FGP_LOCK, 0);
- if (folio) {
- if (!truncate_inode_partial_folio(folio, lstart, lend))
- end = folio->index;
- folio_unlock(folio);
- folio_put(folio);
+ if (!IS_ERR(folio)) {
+ if (!truncate_inode_partial_folio(folio, lstart, lend))
+ end = folio->index;
+ folio_unlock(folio);
+ folio_put(folio);
+ }
}
index = start;
--
2.39.0
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-01-21 6:57 ` [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio Christoph Hellwig
@ 2023-01-21 11:52 ` kernel test robot
2023-01-21 14:28 ` Christoph Hellwig
2023-01-23 15:44 ` David Sterba
` (2 subsequent siblings)
3 siblings, 1 reply; 21+ messages in thread
From: kernel test robot @ 2023-01-21 11:52 UTC (permalink / raw)
To: Christoph Hellwig, Andrew Morton, Matthew Wilcox, Hugh Dickins
Cc: llvm, oe-kbuild-all, Linux Memory Management List, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-xfs, linux-fsdevel,
linux-nilfs
Hi Christoph,
I love your patch! Perhaps something to improve:
[auto build test WARNING on next-20230120]
[cannot apply to akpm-mm/mm-everything tytso-ext4/dev kdave/for-next xfs-linux/for-next konis-nilfs2/upstream linus/master v6.2-rc4 v6.2-rc3 v6.2-rc2 v6.2-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Christoph-Hellwig/mm-make-mapping_get_entry-available-outside-of-filemap-c/20230121-155847
patch link: https://lore.kernel.org/r/20230121065755.1140136-8-hch%40lst.de
patch subject: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
config: riscv-randconfig-r013-20230119 (https://download.01.org/0day-ci/archive/20230121/202301211944.5T9l1RgA-lkp@intel.com/config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 4196ca3278f78c6e19246e54ab0ecb364e37d66a)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/3c8a98fd03b82ace84668b3f8bb48d48e9f34af2
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Christoph-Hellwig/mm-make-mapping_get_entry-available-outside-of-filemap-c/20230121-155847
git checkout 3c8a98fd03b82ace84668b3f8bb48d48e9f34af2
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash fs/iomap/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> fs/iomap/buffered-io.c:669:28: warning: variable 'folio' is uninitialized when used here [-Wuninitialized]
if (pos + len > folio_pos(folio) + folio_size(folio))
^~~~~
fs/iomap/buffered-io.c:636:21: note: initialize the variable 'folio' to silence this warning
struct folio *folio;
^
= NULL
fs/iomap/buffered-io.c:598:22: warning: unused function '__iomap_get_folio' [-Wunused-function]
static struct folio *__iomap_get_folio(struct iomap_iter *iter, loff_t pos,
^
2 warnings generated.
vim +/folio +669 fs/iomap/buffered-io.c
69f4a26c1e0c7c Gao Xiang 2021-08-03 630
d7b64041164ca1 Dave Chinner 2022-11-29 631 static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
bc6123a84a71b5 Matthew Wilcox (Oracle 2021-05-02 632) size_t len, struct folio **foliop)
afc51aaa22f26c Darrick J. Wong 2019-07-15 633 {
471859f57d4253 Andreas Gruenbacher 2023-01-15 634 const struct iomap_folio_ops *folio_ops = iter->iomap.folio_ops;
fad0a1ab34f777 Christoph Hellwig 2021-08-10 635 const struct iomap *srcmap = iomap_iter_srcmap(iter);
d1bd0b4ebfe052 Matthew Wilcox (Oracle 2021-11-03 636) struct folio *folio;
afc51aaa22f26c Darrick J. Wong 2019-07-15 637 int status = 0;
afc51aaa22f26c Darrick J. Wong 2019-07-15 638
1b5c1e36dc0e0f Christoph Hellwig 2021-08-10 639 BUG_ON(pos + len > iter->iomap.offset + iter->iomap.length);
1b5c1e36dc0e0f Christoph Hellwig 2021-08-10 640 if (srcmap != &iter->iomap)
c039b997927263 Goldwyn Rodrigues 2019-10-18 641 BUG_ON(pos + len > srcmap->offset + srcmap->length);
afc51aaa22f26c Darrick J. Wong 2019-07-15 642
afc51aaa22f26c Darrick J. Wong 2019-07-15 643 if (fatal_signal_pending(current))
afc51aaa22f26c Darrick J. Wong 2019-07-15 644 return -EINTR;
afc51aaa22f26c Darrick J. Wong 2019-07-15 645
d454ab82bc7f4a Matthew Wilcox (Oracle 2021-12-09 646) if (!mapping_large_folio_support(iter->inode->i_mapping))
d454ab82bc7f4a Matthew Wilcox (Oracle 2021-12-09 647) len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
d454ab82bc7f4a Matthew Wilcox (Oracle 2021-12-09 648)
d7b64041164ca1 Dave Chinner 2022-11-29 649 /*
d7b64041164ca1 Dave Chinner 2022-11-29 650 * Now we have a locked folio, before we do anything with it we need to
d7b64041164ca1 Dave Chinner 2022-11-29 651 * check that the iomap we have cached is not stale. The inode extent
d7b64041164ca1 Dave Chinner 2022-11-29 652 * mapping can change due to concurrent IO in flight (e.g.
d7b64041164ca1 Dave Chinner 2022-11-29 653 * IOMAP_UNWRITTEN state can change and memory reclaim could have
d7b64041164ca1 Dave Chinner 2022-11-29 654 * reclaimed a previously partially written page at this index after IO
d7b64041164ca1 Dave Chinner 2022-11-29 655 * completion before this write reaches this file offset) and hence we
d7b64041164ca1 Dave Chinner 2022-11-29 656 * could do the wrong thing here (zero a page range incorrectly or fail
d7b64041164ca1 Dave Chinner 2022-11-29 657 * to zero) and corrupt data.
d7b64041164ca1 Dave Chinner 2022-11-29 658 */
471859f57d4253 Andreas Gruenbacher 2023-01-15 659 if (folio_ops && folio_ops->iomap_valid) {
471859f57d4253 Andreas Gruenbacher 2023-01-15 660 bool iomap_valid = folio_ops->iomap_valid(iter->inode,
d7b64041164ca1 Dave Chinner 2022-11-29 661 &iter->iomap);
d7b64041164ca1 Dave Chinner 2022-11-29 662 if (!iomap_valid) {
d7b64041164ca1 Dave Chinner 2022-11-29 663 iter->iomap.flags |= IOMAP_F_STALE;
d7b64041164ca1 Dave Chinner 2022-11-29 664 status = 0;
d7b64041164ca1 Dave Chinner 2022-11-29 665 goto out_unlock;
d7b64041164ca1 Dave Chinner 2022-11-29 666 }
d7b64041164ca1 Dave Chinner 2022-11-29 667 }
d7b64041164ca1 Dave Chinner 2022-11-29 668
d454ab82bc7f4a Matthew Wilcox (Oracle 2021-12-09 @669) if (pos + len > folio_pos(folio) + folio_size(folio))
d454ab82bc7f4a Matthew Wilcox (Oracle 2021-12-09 670) len = folio_pos(folio) + folio_size(folio) - pos;
afc51aaa22f26c Darrick J. Wong 2019-07-15 671
c039b997927263 Goldwyn Rodrigues 2019-10-18 672 if (srcmap->type == IOMAP_INLINE)
bc6123a84a71b5 Matthew Wilcox (Oracle 2021-05-02 673) status = iomap_write_begin_inline(iter, folio);
1b5c1e36dc0e0f Christoph Hellwig 2021-08-10 674 else if (srcmap->flags & IOMAP_F_BUFFER_HEAD)
d1bd0b4ebfe052 Matthew Wilcox (Oracle 2021-11-03 675) status = __block_write_begin_int(folio, pos, len, NULL, srcmap);
afc51aaa22f26c Darrick J. Wong 2019-07-15 676 else
bc6123a84a71b5 Matthew Wilcox (Oracle 2021-05-02 677) status = __iomap_write_begin(iter, pos, len, folio);
afc51aaa22f26c Darrick J. Wong 2019-07-15 678
afc51aaa22f26c Darrick J. Wong 2019-07-15 679 if (unlikely(status))
afc51aaa22f26c Darrick J. Wong 2019-07-15 680 goto out_unlock;
afc51aaa22f26c Darrick J. Wong 2019-07-15 681
bc6123a84a71b5 Matthew Wilcox (Oracle 2021-05-02 682) *foliop = folio;
afc51aaa22f26c Darrick J. Wong 2019-07-15 683 return 0;
afc51aaa22f26c Darrick J. Wong 2019-07-15 684
afc51aaa22f26c Darrick J. Wong 2019-07-15 685 out_unlock:
7a70a5085ed028 Andreas Gruenbacher 2023-01-15 686 __iomap_put_folio(iter, pos, 0, folio);
1b5c1e36dc0e0f Christoph Hellwig 2021-08-10 687 iomap_write_failed(iter->inode, pos, len);
afc51aaa22f26c Darrick J. Wong 2019-07-15 688
afc51aaa22f26c Darrick J. Wong 2019-07-15 689 return status;
afc51aaa22f26c Darrick J. Wong 2019-07-15 690 }
afc51aaa22f26c Darrick J. Wong 2019-07-15 691
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-01-21 11:52 ` kernel test robot
@ 2023-01-21 14:28 ` Christoph Hellwig
0 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-21 14:28 UTC (permalink / raw)
To: kernel test robot
Cc: Christoph Hellwig, Andrew Morton, Matthew Wilcox, Hugh Dickins,
llvm, oe-kbuild-all, Linux Memory Management List, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-xfs, linux-fsdevel,
linux-nilfs
On Sat, Jan 21, 2023 at 07:52:54PM +0800, kernel test robot wrote:
> Hi Christoph,
>
> I love your patch! Perhaps something to improve:
And I don't love all this hugging when something doesn't work. It feels
passive aggressive.
That being said, in this case the error is becaue the series is against
linux-next, so applying it to mainline won't work.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-01-21 6:57 ` [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio Christoph Hellwig
2023-01-21 11:52 ` kernel test robot
@ 2023-01-23 15:44 ` David Sterba
2023-01-26 17:24 ` Ryusuke Konishi
2023-03-10 4:31 ` Naoya Horiguchi
3 siblings, 0 replies; 21+ messages in thread
From: David Sterba @ 2023-01-23 15:44 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrew Morton, Matthew Wilcox, Hugh Dickins, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-mm, linux-xfs,
linux-fsdevel, linux-nilfs
On Sat, Jan 21, 2023 at 07:57:55AM +0100, Christoph Hellwig wrote:
> Instead of returning NULL for all errors, distinguish between:
>
> - no entry found and not asked to allocated (-ENOENT)
> - failed to allocate memory (-ENOMEM)
> - would block (-EAGAIN)
>
> so that callers don't have to guess the error based on the passed
> in flags.
>
> Also pass through the error through the direct callers:
> filemap_get_folio, filemap_lock_folio filemap_grab_folio
> and filemap_get_incore_folio.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/afs/dir.c | 10 +++++-----
> fs/afs/dir_edit.c | 2 +-
> fs/afs/write.c | 4 ++--
For
> fs/btrfs/disk-io.c | 2 +-
Acked-by: David Sterba <dsterba@suse.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-01-21 6:57 ` [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio Christoph Hellwig
2023-01-21 11:52 ` kernel test robot
2023-01-23 15:44 ` David Sterba
@ 2023-01-26 17:24 ` Ryusuke Konishi
2023-03-10 4:31 ` Naoya Horiguchi
3 siblings, 0 replies; 21+ messages in thread
From: Ryusuke Konishi @ 2023-01-26 17:24 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrew Morton, Matthew Wilcox, Hugh Dickins, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-mm, linux-xfs,
linux-fsdevel, linux-nilfs
On Sat, Jan 21, 2023 at 3:59 PM Christoph Hellwig wrote:
>
> Instead of returning NULL for all errors, distinguish between:
>
> - no entry found and not asked to allocated (-ENOENT)
> - failed to allocate memory (-ENOMEM)
> - would block (-EAGAIN)
>
> so that callers don't have to guess the error based on the passed
> in flags.
>
> Also pass through the error through the direct callers:
> filemap_get_folio, filemap_lock_folio filemap_grab_folio
> and filemap_get_incore_folio.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
For
> fs/nilfs2/page.c | 6 +++---
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Thanks,
Ryusuke Konishi
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-01-21 6:57 ` [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio Christoph Hellwig
` (2 preceding siblings ...)
2023-01-26 17:24 ` Ryusuke Konishi
@ 2023-03-10 4:31 ` Naoya Horiguchi
2023-03-10 7:00 ` Christoph Hellwig
3 siblings, 1 reply; 21+ messages in thread
From: Naoya Horiguchi @ 2023-03-10 4:31 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrew Morton, Matthew Wilcox, Hugh Dickins, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-mm, linux-xfs,
linux-fsdevel, linux-nilfs, naoya.horiguchi
On Sat, Jan 21, 2023 at 07:57:55AM +0100, Christoph Hellwig wrote:
> Instead of returning NULL for all errors, distinguish between:
>
> - no entry found and not asked to allocated (-ENOENT)
> - failed to allocate memory (-ENOMEM)
> - would block (-EAGAIN)
>
> so that callers don't have to guess the error based on the passed
> in flags.
>
> Also pass through the error through the direct callers:
> filemap_get_folio, filemap_lock_folio filemap_grab_folio
> and filemap_get_incore_folio.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Hello,
I found a NULL pointer dereference issue related to this patch,
so let me share it.
Here is the bug message (I used akpm/mm-unstable on Mar 9):
[ 2871.648659] BUG: kernel NULL pointer dereference, address: 0000000000000000
[ 2871.651286] #PF: supervisor read access in kernel mode
[ 2871.653231] #PF: error_code(0x0000) - not-present page
[ 2871.655170] PGD 80000001517dd067 P4D 80000001517dd067 PUD 1491d1067 PMD 0
[ 2871.657739] Oops: 0000 [#1] PREEMPT SMP PTI
[ 2871.659329] CPU: 4 PID: 1599 Comm: page-types Tainted: G E N 6.3.0-rc1-v6.3-rc1-230309-1629-189-ga71a7+ #36
[ 2871.663362] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014
[ 2871.666507] RIP: 0010:mincore_page+0x19/0x90
[ 2871.668086] Code: cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 41 54 55 53 e8 92 2b 03 00 48 3d 00 f0 ff ff 77 54 48 89 c3 <48> 8b 00 48 c1 e8 02 89 c5 83 e5 01 75 21 8b 43 34 85 c0 74 47 f0
[ 2871.678313] RSP: 0018:ffffbe57c203fd00 EFLAGS: 00010207
[ 2871.681422] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 2871.685609] RDX: 0000000000000000 RSI: ffff9f59ca1506d8 RDI: ffff9f59ce7c2880
[ 2871.689599] RBP: 0000000000000000 R08: 00007f9f14200000 R09: ffff9f59c9078508
[ 2871.693295] R10: 00007f9ed4400000 R11: 0000000000000000 R12: 0000000000000200
[ 2871.695969] R13: 0000000000000001 R14: ffff9f59c9ef4450 R15: ffff9f59c4ac9000
[ 2871.699927] FS: 00007f9ed47ee740(0000) GS:ffff9f5abbc00000(0000) knlGS:0000000000000000
[ 2871.703969] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2871.706689] CR2: 0000000000000000 CR3: 0000000149ffe006 CR4: 0000000000170ee0
[ 2871.709923] DR0: ffffffff91531760 DR1: ffffffff91531761 DR2: ffffffff91531762
[ 2871.713424] DR3: ffffffff91531763 DR6: 00000000ffff0ff0 DR7: 0000000000000600
[ 2871.716758] Call Trace:
[ 2871.717998] <TASK>
[ 2871.719008] __mincore_unmapped_range+0x6e/0xd0
[ 2871.721220] mincore_unmapped_range+0x16/0x30
[ 2871.723288] walk_pgd_range+0x485/0x9e0
[ 2871.725128] __walk_page_range+0x195/0x1b0
[ 2871.727224] walk_page_range+0x151/0x180
[ 2871.728883] __do_sys_mincore+0xec/0x2b0
[ 2871.730707] do_syscall_64+0x3a/0x90
[ 2871.732179] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[ 2871.734148] RIP: 0033:0x7f9ed443f4ab
[ 2871.735548] Code: 73 01 c3 48 8b 0d 75 99 1b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 1b 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 45 99 1b 00 f7 d8 64 89 01 48
[ 2871.742194] RSP: 002b:00007ffe924d72b8 EFLAGS: 00000206 ORIG_RAX: 000000000000001b
[ 2871.744787] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f9ed443f4ab
[ 2871.747186] RDX: 00007ffe92557300 RSI: 0000000000200000 RDI: 00007f9ed4200000
[ 2871.749404] RBP: 00007ffe92567330 R08: 0000000000000005 R09: 0000000000000000
[ 2871.751683] R10: 00007f9ed4405d68 R11: 0000000000000206 R12: 00007ffe925674b8
[ 2871.753925] R13: 0000000000404af1 R14: 000000000040ad78 R15: 00007f9ed4833000
[ 2871.756493] </TASK>
The precedure to reproduce this is (1) punch hole some page in a shmem
file, then (2) call mincore() over the punch-holed address range.
I confirmed that filemap_get_incore_folio() (actually filemap_get_entry()
inside it) returns NULL in that case, so we unexpectedly enter the following
if-block for the "not found" case.
> diff --git a/mm/mincore.c b/mm/mincore.c
> index cd69b9db008126..5437e584b208bf 100644
> --- a/mm/mincore.c
> +++ b/mm/mincore.c
> @@ -61,7 +61,7 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t index)
> * tmpfs's .fault). So swapped out tmpfs mappings are tested here.
> */
> folio = filemap_get_incore_folio(mapping, index);
> - if (folio) {
> + if (!IS_ERR(folio)) {
> present = folio_test_uptodate(folio);
> folio_put(folio);
> }
I guess that this patch intends to make filemap_get_incore_folio() return
non-NULL error code, so replacing the check with "if (!IS_ERR_OR_NULL(folio))"
cannot be a solution. But I have no idea about the fix, so could you help me?
Thanks,
Naoya Horiguchi
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-03-10 4:31 ` Naoya Horiguchi
@ 2023-03-10 7:00 ` Christoph Hellwig
2023-03-10 8:02 ` Naoya Horiguchi
0 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2023-03-10 7:00 UTC (permalink / raw)
To: Naoya Horiguchi
Cc: Christoph Hellwig, Andrew Morton, Matthew Wilcox, Hugh Dickins,
linux-afs, linux-btrfs, linux-ext4, cluster-devel, linux-mm,
linux-xfs, linux-fsdevel, linux-nilfs, naoya.horiguchi
On Fri, Mar 10, 2023 at 01:31:37PM +0900, Naoya Horiguchi wrote:
> On Sat, Jan 21, 2023 at 07:57:55AM +0100, Christoph Hellwig wrote:
> > Instead of returning NULL for all errors, distinguish between:
> >
> > - no entry found and not asked to allocated (-ENOENT)
> > - failed to allocate memory (-ENOMEM)
> > - would block (-EAGAIN)
> >
> > so that callers don't have to guess the error based on the passed
> > in flags.
> >
> > Also pass through the error through the direct callers:
> > filemap_get_folio, filemap_lock_folio filemap_grab_folio
> > and filemap_get_incore_folio.
> >
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> Hello,
>
> I found a NULL pointer dereference issue related to this patch,
> so let me share it.
>
> Here is the bug message (I used akpm/mm-unstable on Mar 9):
>
> [ 2871.648659] BUG: kernel NULL pointer dereference, address: 0000000000000000
> [ 2871.651286] #PF: supervisor read access in kernel mode
> [ 2871.653231] #PF: error_code(0x0000) - not-present page
> [ 2871.655170] PGD 80000001517dd067 P4D 80000001517dd067 PUD 1491d1067 PMD 0
> [ 2871.657739] Oops: 0000 [#1] PREEMPT SMP PTI
> [ 2871.659329] CPU: 4 PID: 1599 Comm: page-types Tainted: G E N 6.3.0-rc1-v6.3-rc1-230309-1629-189-ga71a7+ #36
> [ 2871.663362] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014
> [ 2871.666507] RIP: 0010:mincore_page+0x19/0x90
> [ 2871.668086] Code: cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 41 54 55 53 e8 92 2b 03 00 48 3d 00 f0 ff ff 77 54 48 89 c3 <48> 8b 00 48 c1 e8 02 89 c5 83 e5 01 75 21 8b 43 34 85 c0 74 47 f0
> [ 2871.678313] RSP: 0018:ffffbe57c203fd00 EFLAGS: 00010207
> [ 2871.681422] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
> [ 2871.685609] RDX: 0000000000000000 RSI: ffff9f59ca1506d8 RDI: ffff9f59ce7c2880
> [ 2871.689599] RBP: 0000000000000000 R08: 00007f9f14200000 R09: ffff9f59c9078508
> [ 2871.693295] R10: 00007f9ed4400000 R11: 0000000000000000 R12: 0000000000000200
> [ 2871.695969] R13: 0000000000000001 R14: ffff9f59c9ef4450 R15: ffff9f59c4ac9000
> [ 2871.699927] FS: 00007f9ed47ee740(0000) GS:ffff9f5abbc00000(0000) knlGS:0000000000000000
> [ 2871.703969] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 2871.706689] CR2: 0000000000000000 CR3: 0000000149ffe006 CR4: 0000000000170ee0
> [ 2871.709923] DR0: ffffffff91531760 DR1: ffffffff91531761 DR2: ffffffff91531762
> [ 2871.713424] DR3: ffffffff91531763 DR6: 00000000ffff0ff0 DR7: 0000000000000600
> [ 2871.716758] Call Trace:
> [ 2871.717998] <TASK>
> [ 2871.719008] __mincore_unmapped_range+0x6e/0xd0
> [ 2871.721220] mincore_unmapped_range+0x16/0x30
> [ 2871.723288] walk_pgd_range+0x485/0x9e0
> [ 2871.725128] __walk_page_range+0x195/0x1b0
> [ 2871.727224] walk_page_range+0x151/0x180
> [ 2871.728883] __do_sys_mincore+0xec/0x2b0
> [ 2871.730707] do_syscall_64+0x3a/0x90
> [ 2871.732179] entry_SYSCALL_64_after_hwframe+0x72/0xdc
> [ 2871.734148] RIP: 0033:0x7f9ed443f4ab
> [ 2871.735548] Code: 73 01 c3 48 8b 0d 75 99 1b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 1b 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 45 99 1b 00 f7 d8 64 89 01 48
> [ 2871.742194] RSP: 002b:00007ffe924d72b8 EFLAGS: 00000206 ORIG_RAX: 000000000000001b
> [ 2871.744787] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f9ed443f4ab
> [ 2871.747186] RDX: 00007ffe92557300 RSI: 0000000000200000 RDI: 00007f9ed4200000
> [ 2871.749404] RBP: 00007ffe92567330 R08: 0000000000000005 R09: 0000000000000000
> [ 2871.751683] R10: 00007f9ed4405d68 R11: 0000000000000206 R12: 00007ffe925674b8
> [ 2871.753925] R13: 0000000000404af1 R14: 000000000040ad78 R15: 00007f9ed4833000
> [ 2871.756493] </TASK>
>
> The precedure to reproduce this is (1) punch hole some page in a shmem
> file, then (2) call mincore() over the punch-holed address range.
>
> I confirmed that filemap_get_incore_folio() (actually filemap_get_entry()
> inside it) returns NULL in that case, so we unexpectedly enter the following
> if-block for the "not found" case.
Yes. Please try this fix:
diff --git a/mm/swap_state.c b/mm/swap_state.c
index c7160070b9daa9..b76a65ac28b319 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -390,6 +390,8 @@ struct folio *filemap_get_incore_folio(struct address_space *mapping,
struct swap_info_struct *si;
struct folio *folio = filemap_get_entry(mapping, index);
+ if (!folio)
+ return ERR_PTR(-ENOENT);
if (!xa_is_value(folio))
return folio;
if (!shmem_mapping(mapping))
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio
2023-03-10 7:00 ` Christoph Hellwig
@ 2023-03-10 8:02 ` Naoya Horiguchi
0 siblings, 0 replies; 21+ messages in thread
From: Naoya Horiguchi @ 2023-03-10 8:02 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrew Morton, Matthew Wilcox, Hugh Dickins, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-mm, linux-xfs,
linux-fsdevel, linux-nilfs, naoya.horiguchi
On Fri, Mar 10, 2023 at 08:00:23AM +0100, Christoph Hellwig wrote:
> On Fri, Mar 10, 2023 at 01:31:37PM +0900, Naoya Horiguchi wrote:
> > On Sat, Jan 21, 2023 at 07:57:55AM +0100, Christoph Hellwig wrote:
> > > Instead of returning NULL for all errors, distinguish between:
> > >
> > > - no entry found and not asked to allocated (-ENOENT)
> > > - failed to allocate memory (-ENOMEM)
> > > - would block (-EAGAIN)
> > >
> > > so that callers don't have to guess the error based on the passed
> > > in flags.
> > >
> > > Also pass through the error through the direct callers:
> > > filemap_get_folio, filemap_lock_folio filemap_grab_folio
> > > and filemap_get_incore_folio.
> > >
> > > Signed-off-by: Christoph Hellwig <hch@lst.de>
> >
> > Hello,
> >
> > I found a NULL pointer dereference issue related to this patch,
> > so let me share it.
> >
> > Here is the bug message (I used akpm/mm-unstable on Mar 9):
> >
> > [ 2871.648659] BUG: kernel NULL pointer dereference, address: 0000000000000000
> > [ 2871.651286] #PF: supervisor read access in kernel mode
> > [ 2871.653231] #PF: error_code(0x0000) - not-present page
> > [ 2871.655170] PGD 80000001517dd067 P4D 80000001517dd067 PUD 1491d1067 PMD 0
> > [ 2871.657739] Oops: 0000 [#1] PREEMPT SMP PTI
> > [ 2871.659329] CPU: 4 PID: 1599 Comm: page-types Tainted: G E N 6.3.0-rc1-v6.3-rc1-230309-1629-189-ga71a7+ #36
> > [ 2871.663362] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014
> > [ 2871.666507] RIP: 0010:mincore_page+0x19/0x90
> > [ 2871.668086] Code: cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 41 54 55 53 e8 92 2b 03 00 48 3d 00 f0 ff ff 77 54 48 89 c3 <48> 8b 00 48 c1 e8 02 89 c5 83 e5 01 75 21 8b 43 34 85 c0 74 47 f0
> > [ 2871.678313] RSP: 0018:ffffbe57c203fd00 EFLAGS: 00010207
> > [ 2871.681422] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
> > [ 2871.685609] RDX: 0000000000000000 RSI: ffff9f59ca1506d8 RDI: ffff9f59ce7c2880
> > [ 2871.689599] RBP: 0000000000000000 R08: 00007f9f14200000 R09: ffff9f59c9078508
> > [ 2871.693295] R10: 00007f9ed4400000 R11: 0000000000000000 R12: 0000000000000200
> > [ 2871.695969] R13: 0000000000000001 R14: ffff9f59c9ef4450 R15: ffff9f59c4ac9000
> > [ 2871.699927] FS: 00007f9ed47ee740(0000) GS:ffff9f5abbc00000(0000) knlGS:0000000000000000
> > [ 2871.703969] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [ 2871.706689] CR2: 0000000000000000 CR3: 0000000149ffe006 CR4: 0000000000170ee0
> > [ 2871.709923] DR0: ffffffff91531760 DR1: ffffffff91531761 DR2: ffffffff91531762
> > [ 2871.713424] DR3: ffffffff91531763 DR6: 00000000ffff0ff0 DR7: 0000000000000600
> > [ 2871.716758] Call Trace:
> > [ 2871.717998] <TASK>
> > [ 2871.719008] __mincore_unmapped_range+0x6e/0xd0
> > [ 2871.721220] mincore_unmapped_range+0x16/0x30
> > [ 2871.723288] walk_pgd_range+0x485/0x9e0
> > [ 2871.725128] __walk_page_range+0x195/0x1b0
> > [ 2871.727224] walk_page_range+0x151/0x180
> > [ 2871.728883] __do_sys_mincore+0xec/0x2b0
> > [ 2871.730707] do_syscall_64+0x3a/0x90
> > [ 2871.732179] entry_SYSCALL_64_after_hwframe+0x72/0xdc
> > [ 2871.734148] RIP: 0033:0x7f9ed443f4ab
> > [ 2871.735548] Code: 73 01 c3 48 8b 0d 75 99 1b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 1b 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 45 99 1b 00 f7 d8 64 89 01 48
> > [ 2871.742194] RSP: 002b:00007ffe924d72b8 EFLAGS: 00000206 ORIG_RAX: 000000000000001b
> > [ 2871.744787] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f9ed443f4ab
> > [ 2871.747186] RDX: 00007ffe92557300 RSI: 0000000000200000 RDI: 00007f9ed4200000
> > [ 2871.749404] RBP: 00007ffe92567330 R08: 0000000000000005 R09: 0000000000000000
> > [ 2871.751683] R10: 00007f9ed4405d68 R11: 0000000000000206 R12: 00007ffe925674b8
> > [ 2871.753925] R13: 0000000000404af1 R14: 000000000040ad78 R15: 00007f9ed4833000
> > [ 2871.756493] </TASK>
> >
> > The precedure to reproduce this is (1) punch hole some page in a shmem
> > file, then (2) call mincore() over the punch-holed address range.
> >
> > I confirmed that filemap_get_incore_folio() (actually filemap_get_entry()
> > inside it) returns NULL in that case, so we unexpectedly enter the following
> > if-block for the "not found" case.
>
> Yes. Please try this fix:
>
> diff --git a/mm/swap_state.c b/mm/swap_state.c
> index c7160070b9daa9..b76a65ac28b319 100644
> --- a/mm/swap_state.c
> +++ b/mm/swap_state.c
> @@ -390,6 +390,8 @@ struct folio *filemap_get_incore_folio(struct address_space *mapping,
> struct swap_info_struct *si;
> struct folio *folio = filemap_get_entry(mapping, index);
>
> + if (!folio)
> + return ERR_PTR(-ENOENT);
> if (!xa_is_value(folio))
> return folio;
> if (!shmem_mapping(mapping))
Confirmed the fix, thank you very much!
- Naoya Horiguchi
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: return an ERR_PTR from __filemap_get_folio v2
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
` (6 preceding siblings ...)
2023-01-21 6:57 ` [PATCH 7/7] mm: return an ERR_PTR from __filemap_get_folio Christoph Hellwig
@ 2023-01-22 1:06 ` Andrew Morton
2023-01-22 7:20 ` Christoph Hellwig
2023-03-28 23:04 ` Andrew Morton
8 siblings, 1 reply; 21+ messages in thread
From: Andrew Morton @ 2023-01-22 1:06 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Matthew Wilcox, Hugh Dickins, linux-afs, linux-btrfs, linux-ext4,
cluster-devel, linux-mm, linux-xfs, linux-fsdevel, linux-nilfs
On Sat, 21 Jan 2023 07:57:48 +0100 Christoph Hellwig <hch@lst.de> wrote:
> Hi all,
>
> __filemap_get_folio and its wrappers can return NULL for three different
> conditions, which in some cases requires the caller to reverse engineer
> the decision making. This is fixed by returning an ERR_PTR instead of
> NULL and thus transporting the reason for the failure. But to make
> that work we first need to ensure that no xa_value special case is
> returned and thus return the FGP_ENTRY flag. It turns out that flag
> is barely used and can usually be deal with in a better way.
>
> Note that the shmem patches in here are non-trivial and need some
> careful review and testing.
I'll hide for a while, awaiting that review. Plus...
> Changes since v1:
> - drop the patches to check for errors in btrfs and gfs2
> - document the new calling conventions for the wrappers around
> __filemap_get_folio
> - rebased against the iomap changes in latest linux-next
This patchset doesn't apply to fs/btrfs/ because linux-next contains
this 6+ month-old commit:
commit 964688b32d9ada55a7fce2e650d85ef24188f73f
Author: Matthew Wilcox (Oracle) <willy@infradead.org>
AuthorDate: Tue May 17 18:03:27 2022 -0400
Commit: Matthew Wilcox (Oracle) <willy@infradead.org>
CommitDate: Wed Jun 29 08:51:07 2022 -0400
btrfs: Use a folio in wait_dev_supers()
Matthew, what's the story here?
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: return an ERR_PTR from __filemap_get_folio v2
2023-01-22 1:06 ` return an ERR_PTR from __filemap_get_folio v2 Andrew Morton
@ 2023-01-22 7:20 ` Christoph Hellwig
2023-01-23 18:59 ` Andrew Morton
0 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-22 7:20 UTC (permalink / raw)
To: Andrew Morton
Cc: Christoph Hellwig, Matthew Wilcox, Hugh Dickins, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-mm, linux-xfs,
linux-fsdevel, linux-nilfs
On Sat, Jan 21, 2023 at 05:06:41PM -0800, Andrew Morton wrote:
> This patchset doesn't apply to fs/btrfs/ because linux-next contains
> this 6+ month-old commit:
Hmm. It was literally written against linux-next as of last morning,
which does not have that commit.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: return an ERR_PTR from __filemap_get_folio v2
2023-01-22 7:20 ` Christoph Hellwig
@ 2023-01-23 18:59 ` Andrew Morton
2023-01-23 19:18 ` Christoph Hellwig
0 siblings, 1 reply; 21+ messages in thread
From: Andrew Morton @ 2023-01-23 18:59 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Matthew Wilcox, Hugh Dickins, linux-afs, linux-btrfs, linux-ext4,
cluster-devel, linux-mm, linux-xfs, linux-fsdevel, linux-nilfs
On Sun, 22 Jan 2023 08:20:06 +0100 Christoph Hellwig <hch@lst.de> wrote:
> On Sat, Jan 21, 2023 at 05:06:41PM -0800, Andrew Morton wrote:
> > This patchset doesn't apply to fs/btrfs/ because linux-next contains
> > this 6+ month-old commit:
>
> Hmm. It was literally written against linux-next as of last morning,
> which does not have that commit.
Confused. According to
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/fs/btrfs/disk-io.c#n4023
it's there today. wait_dev_supers() has been foliofied.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: return an ERR_PTR from __filemap_get_folio v2
2023-01-23 18:59 ` Andrew Morton
@ 2023-01-23 19:18 ` Christoph Hellwig
0 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-01-23 19:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Christoph Hellwig, Matthew Wilcox, Hugh Dickins, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-mm, linux-xfs,
linux-fsdevel, linux-nilfs
On Mon, Jan 23, 2023 at 10:59:45AM -0800, Andrew Morton wrote:
> On Sun, 22 Jan 2023 08:20:06 +0100 Christoph Hellwig <hch@lst.de> wrote:
>
> > On Sat, Jan 21, 2023 at 05:06:41PM -0800, Andrew Morton wrote:
> > > This patchset doesn't apply to fs/btrfs/ because linux-next contains
> > > this 6+ month-old commit:
> >
> > Hmm. It was literally written against linux-next as of last morning,
> > which does not have that commit.
>
> Confused. According to
> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/fs/btrfs/disk-io.c#n4023
>
> it's there today. wait_dev_supers() has been foliofied.
Yes, it's there now. But I'm pretty sure it wasn't there when
I did the last rebase. Weird.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: return an ERR_PTR from __filemap_get_folio v2
2023-01-21 6:57 return an ERR_PTR from __filemap_get_folio v2 Christoph Hellwig
` (7 preceding siblings ...)
2023-01-22 1:06 ` return an ERR_PTR from __filemap_get_folio v2 Andrew Morton
@ 2023-03-28 23:04 ` Andrew Morton
2023-03-29 23:56 ` Christoph Hellwig
8 siblings, 1 reply; 21+ messages in thread
From: Andrew Morton @ 2023-03-28 23:04 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Matthew Wilcox, Hugh Dickins, linux-afs, linux-btrfs, linux-ext4,
cluster-devel, linux-mm, linux-xfs, linux-fsdevel, linux-nilfs
On Sat, 21 Jan 2023 07:57:48 +0100 Christoph Hellwig <hch@lst.de> wrote:
> __filemap_get_folio and its wrappers can return NULL for three different
> conditions, which in some cases requires the caller to reverse engineer
> the decision making. This is fixed by returning an ERR_PTR instead of
> NULL and thus transporting the reason for the failure. But to make
> that work we first need to ensure that no xa_value special case is
> returned and thus return the FGP_ENTRY flag. It turns out that flag
> is barely used and can usually be deal with in a better way.
>
> Note that the shmem patches in here are non-trivial and need some
> careful review and testing.
How are we going with the review and testing. I assume that
we're now OK on the runtime testing front, but do you feel that
review has been adequate?
Thanks.
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: return an ERR_PTR from __filemap_get_folio v2
2023-03-28 23:04 ` Andrew Morton
@ 2023-03-29 23:56 ` Christoph Hellwig
0 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2023-03-29 23:56 UTC (permalink / raw)
To: Andrew Morton
Cc: Christoph Hellwig, Matthew Wilcox, Hugh Dickins, linux-afs,
linux-btrfs, linux-ext4, cluster-devel, linux-mm, linux-xfs,
linux-fsdevel, linux-nilfs
On Tue, Mar 28, 2023 at 04:04:33PM -0700, Andrew Morton wrote:
> > Note that the shmem patches in here are non-trivial and need some
> > careful review and testing.
>
> How are we going with the review and testing. I assume that
> we're now OK on the runtime testing front, but do you feel that
> review has been adequate?
Yes, I think we're fine, mostly due to Hugh. I'm a little sad about
the simplification / descoping from him, but at least we get the main
objective done. Maybe at some point we can do another pass at
cleaning up the shmem page finding/reading mess.
^ permalink raw reply [flat|nested] 21+ messages in thread