diff mbox series

[2/2] mpage: Convert __mpage_writepage() to use a folio more fully

Message ID 20230126201255.1681189-3-willy@infradead.org (mailing list archive)
State New, archived
Headers show
Series Convert writepage_t to use a folio | expand

Commit Message

Matthew Wilcox Jan. 26, 2023, 8:12 p.m. UTC
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(-)

Comments

Andrew Morton Jan. 26, 2023, 10:59 p.m. UTC | #1
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.
Alexander Egorenkov Jan. 30, 2023, 11:04 a.m. UTC | #2
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 mbox series

Patch

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;