Message ID | 20230126201255.1681189-3-willy@infradead.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Convert writepage_t to use a folio | expand |
On Thu, 26 Jan 2023 20:12:55 +0000 "Matthew Wilcox (Oracle)" <willy@infradead.org> wrote: > This is just a conversion to the folio API. While there are some nods > towards supporting multi-page folios in here, the blocks array is > still sized for one page's worth of blocks, and there are other > assumptions such as the blocks_per_page variable. > > ... > > @@ -588,7 +585,7 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, > if (bio == NULL) { > if (first_unmapped == blocks_per_page) { > if (!bdev_write_page(bdev, blocks[0] << (blkbits - 9), > - page, wbc)) > + &folio->page, wbc)) > goto out; > } > bio = bio_alloc(bdev, BIO_MAX_VECS, > hch removed this code in https://lkml.kernel.org/r/20230125133436.447864-2-hch@lst.de, so I'll drop this hunk.
Hi,
after this change we see a WARNING on s390 linux-next with LTP tests (writev03).
RELEASE: 6.2.0-20230129.rc5.git1.e2f86c02fdc9.300.fc37.s390x+next
[ 5577.900868] BTRFS: device fsid 4127fc5b-a6b3-44ff-927d-7bfc5163686e devid 1 transid 6 /dev/loop0 scanned by mkfs.btrfs (2502327)
[ 5577.901186] BTRFS info (device loop0): using crc32c (crc32c-vx) checksum algorithm
[ 5577.901192] BTRFS info (device loop0): using free space tree
[ 5577.901847] BTRFS info (device loop0): enabling ssd optimizations
[ 5577.901850] BTRFS info (device loop0): auto enabling async discard
[ 5577.901895] BTRFS info (device loop0): checking UUID tree
[ 5620.655695] ------------[ cut here ]------------
[ 5620.655702] WARNING: CPU: 6 PID: 2404385 at fs/mpage.c:570 __mpage_writepage+0x79c/0x7b0
[ 5620.655711] Modules linked in: xt_state(E) quota_v2(E) quota_tree(E) tun(E) nls_utf8(E) overlay(E) nls_iso8859_1(E) nls_cp437(E) ntfs(E) exfat(E) vfat(E) fat(E) loop(E) sctp(E) ip6_udp_tunnel(E) udp_tunnel(E) kunit(E) af_packet_diag(E) unix_diag(E) mptcp_diag(E) xfrm_user(E) xfrm_algo(E) crypto_user(E) tcp_diag(E) inet_diag(E) netlink_diag(E) algif_hash(E) af_alg(E) dm_service_time(E) nft_fib_inet(E) nft_fib_ipv4(E) nft_fib_ipv6(E) nft_fib(E) nft_reject_inet(E) nf_reject_ipv4(E) nf_reject_ipv6(E) nft_reject(E) nft_ct(E) nft_chain_nat(E) nf_nat(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) ip_set(E) nf_tables(E) nfnetlink(E) sunrpc(E) zfcp(E) scsi_transport_fc(E) s390_trng(E) vfio_ccw(E) mdev(E) vfio_iommu_type1(E) vfio(E) sch_fq_codel(E) ip6_tables(E) ip_tables(E) x_tables(E) configfs(E) ghash_s390(E) prng(E) chacha_s390(E) libchacha(E) aes_s390(E) des_s390(E) libdes(E) sha3_512_s390(E) sha3_256_s390(E) sha512_s390(E) sha256_s390(E) sha1_s390(E) sha_common(E) scsi_dh_rdac(E) scsi_dh_emc(E) scsi_dh_alua(E)
[ 5620.655763] pkey(E) zcrypt(E) rng_core(E) dm_multipath(E) autofs4(E)
[ 5620.655778] Unloaded tainted modules: init_module(OE):3 finit_module(OE):3 dummy_del_mod_dep(OE):1 dummy_del_mod(OE):2 test_unwind(E):1 test_modules(E):1 test_kprobes_s390(E):1 test_kprobes(E):1 klp_tc_17_livepatch(OEK):1 klp_tc_16_livepatch(OEK):1 klp_tc_15_livepatch(OEK):1 klp_tc_14_livepatch(OEK):1 klp_tc_13_livepatch(OEK):1 klp_tc_12_livepatch(OEK):1 klp_tc_11_livepatch(OEK):1 klp_test_support_mod(OE):8 klp_tc_10_livepatch(OEK):1 klp_tc_8_5_livepatch(OEK):1 klp_tc_8_4_livepatch(OEK):1 klp_tc_8_3_livepatch(OEK):1 klp_tc_8_2_livepatch(OEK):1 klp_tc_8_1_livepatch(OEK):1 klp_tc_6_livepatch(OEK):1 klp_tc_5_1_livepatch(OEK):1 klp_tc_5_2_livepatch(OEK):1 klp_tc_5_3_livepatch(OEK):1 klp_tc_5_4_livepatch(OEK):1 klp_tc_5_5_livepatch(OEK):1 klp_tc_5_6_livepatch(OEK):1 klp_tc_5_7_livepatch(OEK):1 klp_tc_5_8_livepatch(OEK):1 klp_tc_5_9_livepatch(OEK):1 klp_tc_5_10_livepatch(OEK):1 klp_tc_5_11_livepatch(OEK):1 klp_tc_5_12_livepatch(OEK):1 klp_tc_5_13_livepatch(OEK):1 klp_tc_5_14_livepatch(OEK):1 klp_tc_5_15_livepatch(OEK):1
[ 5620.655806] klp_tc_3_livepatch(OEK):1 [last unloaded: init_module(OE)]
[ 5620.655815] CPU: 6 PID: 2404385 Comm: kworker/u128:8 Tainted: G OE K N 6.2.0-20230129.rc5.git1.e2f86c02fdc9.300.fc37.s390x+next #1
[ 5620.655818] Hardware name: IBM 3931 A01 704 (z/VM 7.3.0)
[ 5620.655820] Workqueue: writeback wb_workfn (flush-7:0)
[ 5620.655861] Krnl PSW : 0704c00180000000 0000000077704118 (__mpage_writepage+0x7a0/0x7b0)
[ 5620.655866] R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 RI:0 EA:3
[ 5620.655869] Krnl GPRS: 0000000000000000 0000000000001000 0000000000000000 0000000000000000
[ 5620.655872] 0000038000000001 00000001ce688000 0000000000000000 0000037200000009
[ 5620.655874] 00000380004cb970 0000000000000000 0000038000000001 0000037203a01d80
[ 5620.655877] 00000000855f2100 0000000000000000 0000000000000000 00000380004cb660
[ 5620.655885] Krnl Code: 000000007770410c: a7181000 lhi %r1,4096
0000000077704110: a7f4fe34 brc 15,0000000077703d78
#0000000077704114: af000000 mc 0,0
>0000000077704118: a7f4fccc brc 15,0000000077703ab0
000000007770411c: af000000 mc 0,0
0000000077704120: d70010001000 xc 0(1,%r1),0(%r1)
0000000077704126: 0707 bcr 0,%r7
0000000077704128: c00400497b2c brcl 0,0000000078033780
[ 5620.655905] Call Trace:
[ 5620.655907] [<0000000077704118>] __mpage_writepage+0x7a0/0x7b0
[ 5620.655911] [<00000000775c9df0>] write_cache_pages+0x1b0/0x418
[ 5620.655916] [<0000000077703824>] mpage_writepages+0x64/0xb0
[ 5620.655918] [<00000000775cb416>] do_writepages+0x66/0x1d0
[ 5620.655921] [<00000000776ee14c>] __writeback_single_inode+0x4c/0x410
[ 5620.655925] [<00000000776eea2a>] writeback_sb_inodes+0x232/0x5a0
[ 5620.655928] [<00000000776eedf2>] __writeback_inodes_wb+0x5a/0x138
[ 5620.655931] [<00000000776ef140>] wb_writeback+0x270/0x3a0
[ 5620.655934] [<00000000776f04e0>] wb_workfn+0x370/0x5b8
[ 5620.655936] [<00000000773daab8>] process_one_work+0x200/0x458
[ 5620.655940] [<00000000773db246>] worker_thread+0x66/0x490
[ 5620.655942] [<00000000773e4098>] kthread+0x108/0x110
[ 5620.655944] [<000000007736736c>] __ret_from_fork+0x3c/0x58
[ 5620.655947] [<0000000077fecb6a>] ret_from_fork+0xa/0x40
[ 5620.655952] Last Breaking-Event-Address:
[ 5620.655953] [<0000000077703d2e>] __mpage_writepage+0x3b6/0x7b0
[ 5620.655956] Kernel panic - not syncing: kernel: panic_on_warn set ...
[ 5620.655958] CPU: 6 PID: 2404385 Comm: kworker/u128:8 Tainted: G OE K N 6.2.0-20230129.rc5.git1.e2f86c02fdc9.300.fc37.s390x+next #1
[ 5620.655961] Hardware name: IBM 3931 A01 704 (z/VM 7.3.0)
[ 5620.655962] Workqueue: writeback wb_workfn (flush-7:0)
[ 5620.655965] Call Trace:
[ 5620.655966] [<0000000077fdd01a>] dump_stack_lvl+0x62/0x80
[ 5620.655970] [<0000000077fcb658>] panic+0x118/0x300
[ 5620.655973] [<00000000773b5d80>] check_panic_on_warn+0x70/0x88
[ 5620.655977] [<00000000773b6028>] __warn+0x108/0x150
[ 5620.655979] [<0000000077fa06da>] report_bug+0xba/0x140
[ 5620.655983] [<00000000773651a4>] monitor_event_exception+0x44/0x80
[ 5620.655985] [<0000000077fdd218>] __do_pgm_check+0xf0/0x1b0
[ 5620.655988] [<0000000077feccbc>] pgm_check_handler+0x11c/0x170
[ 5620.655991] [<0000000077704118>] __mpage_writepage+0x7a0/0x7b0
[ 5620.655993] [<00000000775c9df0>] write_cache_pages+0x1b0/0x418
[ 5620.655995] [<0000000077703824>] mpage_writepages+0x64/0xb0
[ 5620.655998] [<00000000775cb416>] do_writepages+0x66/0x1d0
[ 5620.656000] [<00000000776ee14c>] __writeback_single_inode+0x4c/0x410
[ 5620.656003] [<00000000776eea2a>] writeback_sb_inodes+0x232/0x5a0
[ 5620.656006] [<00000000776eedf2>] __writeback_inodes_wb+0x5a/0x138
[ 5620.656010] [<00000000776ef140>] wb_writeback+0x270/0x3a0
[ 5620.656012] [<00000000776f04e0>] wb_workfn+0x370/0x5b8
[ 5620.656014] [<00000000773daab8>] process_one_work+0x200/0x458
[ 5620.656016] [<00000000773db246>] worker_thread+0x66/0x490
[ 5620.656019] [<00000000773e4098>] kthread+0x108/0x110
[ 5620.656020] [<000000007736736c>] __ret_from_fork+0x3c/0x58
[ 5620.656023] [<0000000077fecb6a>] ret_from_fork+0xa/0x40
crash> q
Regards
Alex
diff --git a/fs/mpage.c b/fs/mpage.c index 840f57ed2542..2efa393f0db7 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -448,13 +448,11 @@ void clean_page_buffers(struct page *page) static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, void *data) { - struct page *page = &folio->page; struct mpage_data *mpd = data; struct bio *bio = mpd->bio; - struct address_space *mapping = page->mapping; - struct inode *inode = page->mapping->host; + struct address_space *mapping = folio->mapping; + struct inode *inode = mapping->host; const unsigned blkbits = inode->i_blkbits; - unsigned long end_index; const unsigned blocks_per_page = PAGE_SIZE >> blkbits; sector_t last_block; sector_t block_in_file; @@ -465,13 +463,13 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, int boundary = 0; sector_t boundary_block = 0; struct block_device *boundary_bdev = NULL; - int length; + size_t length; struct buffer_head map_bh; loff_t i_size = i_size_read(inode); int ret = 0; + struct buffer_head *head = folio_buffers(folio); - if (page_has_buffers(page)) { - struct buffer_head *head = page_buffers(page); + if (head) { struct buffer_head *bh = head; /* If they're all mapped and dirty, do it */ @@ -523,8 +521,8 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, /* * The page has no buffers: map it to disk */ - BUG_ON(!PageUptodate(page)); - block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits); + BUG_ON(!folio_test_uptodate(folio)); + block_in_file = (sector_t)folio->index << (PAGE_SHIFT - blkbits); /* * Whole page beyond EOF? Skip allocating blocks to avoid leaking * space. @@ -532,7 +530,7 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, if (block_in_file >= (i_size + (1 << blkbits) - 1) >> blkbits) goto page_is_mapped; last_block = (i_size - 1) >> blkbits; - map_bh.b_page = page; + map_bh.b_folio = folio; for (page_block = 0; page_block < blocks_per_page; ) { map_bh.b_state = 0; @@ -561,8 +559,8 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, first_unmapped = page_block; page_is_mapped: - end_index = i_size >> PAGE_SHIFT; - if (page->index >= end_index) { + length = folio_size(folio); + if (folio_pos(folio) + length > i_size) { /* * The page straddles i_size. It must be zeroed out on each * and every writepage invocation because it may be mmapped. @@ -571,11 +569,10 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, * is zeroed when mapped, and writes to that region are not * written out to the file." */ - unsigned offset = i_size & (PAGE_SIZE - 1); - - if (page->index > end_index || !offset) + length = i_size - folio_pos(folio); + if (WARN_ON_ONCE(folio_pos(folio) >= i_size)) goto confused; - zero_user_segment(page, offset, PAGE_SIZE); + folio_zero_segment(folio, length, folio_size(folio)); } /* @@ -588,7 +585,7 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, if (bio == NULL) { if (first_unmapped == blocks_per_page) { if (!bdev_write_page(bdev, blocks[0] << (blkbits - 9), - page, wbc)) + &folio->page, wbc)) goto out; } bio = bio_alloc(bdev, BIO_MAX_VECS, @@ -603,18 +600,18 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, * the confused fail path above (OOM) will be very confused when * it finds all bh marked clean (i.e. it will not write anything) */ - wbc_account_cgroup_owner(wbc, page, PAGE_SIZE); + wbc_account_cgroup_owner(wbc, &folio->page, folio_size(folio)); length = first_unmapped << blkbits; - if (bio_add_page(bio, page, length, 0) < length) { + if (!bio_add_folio(bio, folio, length, 0)) { bio = mpage_bio_submit(bio); goto alloc_new; } - clean_buffers(page, first_unmapped); + clean_buffers(&folio->page, first_unmapped); - BUG_ON(PageWriteback(page)); - set_page_writeback(page); - unlock_page(page); + BUG_ON(folio_test_writeback(folio)); + folio_start_writeback(folio); + folio_unlock(folio); if (boundary || (first_unmapped != blocks_per_page)) { bio = mpage_bio_submit(bio); if (boundary_block) { @@ -633,7 +630,7 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, /* * The caller has a ref on the inode, so *mapping is stable */ - ret = block_write_full_page(page, mpd->get_block, wbc); + ret = block_write_full_page(&folio->page, mpd->get_block, wbc); mapping_set_error(mapping, ret); out: mpd->bio = bio;
This is just a conversion to the folio API. While there are some nods towards supporting multi-page folios in here, the blocks array is still sized for one page's worth of blocks, and there are other assumptions such as the blocks_per_page variable. Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> --- fs/mpage.c | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-)