Message ID | 20230121065755.1140136-8-hch@lst.de (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [1/7] mm: don't look at xarray value entries in split_huge_pages_in_file | expand |
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
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.
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>
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
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
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))
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
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;
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(-)