From: Chi Zhiling Change SGP_NOALLOC to return 0 with NULL folio on hole, matching SGP_READ/SGP_GET behavior. This simplifies the sgp_type handling by unifying hole semantics across these three types. Previously, SGP_NOALLOC returned -ENOENT on hole, while SGP_READ/SGP_GET returned 0. This inconsistency required special handling in callers like khugepaged and userfaultfd. After this change: - khugepaged: behavior unchanged (checks both error and NULL folio) - userfaultfd: behavior unchanged (both -ENOENT and NULL are converted to -EFAULT before returning to userspace) Signed-off-by: Chi Zhiling --- include/linux/shmem_fs.h | 2 +- mm/khugepaged.c | 2 +- mm/shmem.c | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 24698faea5a4..6f7f8b9e2a10 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -166,7 +166,7 @@ extern unsigned long shmem_partial_swap_usage(struct address_space *mapping, enum sgp_type { SGP_GET, /* don't exceed i_size, don't allocate page, don't lock */ SGP_READ, /* don't exceed i_size, don't allocate page, lock folio */ - SGP_NOALLOC, /* similar, but fail on hole or use fallocated page */ + SGP_NOALLOC, /* like SGP_READ, but accept fallocated page */ 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 */ diff --git a/mm/khugepaged.c b/mm/khugepaged.c index b8452dbdb043..3309d1c094df 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -1950,7 +1950,7 @@ static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr, xas_unlock_irq(&xas); /* swap in or instantiate fallocated page */ if (shmem_get_folio(mapping->host, index, 0, - &folio, SGP_NOALLOC)) { + &folio, SGP_NOALLOC) || !folio) { result = SCAN_FAIL; goto xa_unlocked; } diff --git a/mm/shmem.c b/mm/shmem.c index 4bc4e463ca97..41f5e251f7ed 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2531,14 +2531,11 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index, } /* - * SGP_READ/SGP_GET: succeed on hole, with NULL folio, letting caller zero. - * SGP_NOALLOC: fail on hole, with NULL folio, letting caller fail. + * SGP_READ/SGP_GET/SGP_NOALLOC: succeed on hole, with NULL folio. */ *foliop = NULL; - if (sgp == SGP_READ || sgp == SGP_GET) + if (sgp <= SGP_NOALLOC) return 0; - if (sgp == SGP_NOALLOC) - return -ENOENT; /* * Fast cache lookup and swap lookup did not find it: allocate. @@ -2666,7 +2663,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index, * When no folio is found, the behavior depends on @sgp: * - for SGP_GET, *@foliop is %NULL and 0 is returned * - for SGP_READ, *@foliop is %NULL and 0 is returned - * - for SGP_NOALLOC, *@foliop is %NULL and -ENOENT is returned + * - for SGP_NOALLOC, *@foliop is %NULL and 0 is returned * - for all other flags a new folio is allocated, inserted into the * page cache and returned locked in @foliop. * -- 2.43.0