Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nilfs2: prepare backing device folios for writing after adding checksums

Patch series "nilfs2: eliminate the call to inode_attach_wb()".

This series eliminates the inode_attach_wb() call from nilfs2, which was
introduced as a workaround for a kernel bug but is suspected of layer
violation (in fact, it is undesirable since it exposes a reference to the
backing device).

Removal of the inode_attach_wb() call is done by simply using
mark_buffer_dirty() on the backing device's buffers. To use it safely,
this series will prepare it in patch 1/2, and perform the replacement
itself in patch 2/2.


This patch (of 2):

In preparation for inode_attach_wb(), which is currently called when
attaching the log writer, to be done via mark_buffer_dirty(), change the
order of preparation for log writing.

Specifically, the function call that adds checksums to segment summary and
super root blocks, which correspond to the log header and trailer, is made
before starting writeback of folios containing those blocks.

The current steps are as follows:

1. Put the folios of segment summary blocks in writeback state.
2. Put the folios of data blocks, metadata file blocks, and btree node
blocks (collectively called payload blocks) into writeback state.
3. Put the super root block folio in writeback state.
4. Add checksums.

Change these as follows:

1. Put the folios of payload blocks in writeback state.
2. Add checksums.
3. Put the folios of segment summary blocks in writeback state.
4. Put the super root block folio in writeback state.

In this order, the contents of segment summaries and super root block
that directly use buffer/folio of the backing device can be determined
including the addition of checksums, before preparing to write.

Step (1), which puts the payload block folios in writeback state, is
performed first because if there are memory-mapped data blocks, a valid
checksum can only be calculated after step (1).

Link: https://lkml.kernel.org/r/20240610160029.7673-2-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ryusuke Konishi and committed by
Andrew Morton
25fa5f99 cda1c8e0

+52 -33
+52 -33
fs/nilfs2/segment.c
··· 1639 1639 folio_unlock(folio); 1640 1640 } 1641 1641 1642 - static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci) 1642 + /** 1643 + * nilfs_prepare_write_logs - prepare to write logs 1644 + * @logs: logs to prepare for writing 1645 + * @seed: checksum seed value 1646 + * 1647 + * nilfs_prepare_write_logs() adds checksums and prepares the block 1648 + * buffers/folios for writing logs. In order to stabilize folios of 1649 + * memory-mapped file blocks by putting them in writeback state before 1650 + * calculating the checksums, first prepare to write payload blocks other 1651 + * than segment summary and super root blocks in which the checksums will 1652 + * be embedded. 1653 + */ 1654 + static void nilfs_prepare_write_logs(struct list_head *logs, u32 seed) 1643 1655 { 1644 1656 struct nilfs_segment_buffer *segbuf; 1645 1657 struct folio *bd_folio = NULL, *fs_folio = NULL; 1658 + struct buffer_head *bh; 1646 1659 1647 - list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { 1648 - struct buffer_head *bh; 1649 - 1650 - list_for_each_entry(bh, &segbuf->sb_segsum_buffers, 1651 - b_assoc_buffers) { 1652 - if (bh->b_folio != bd_folio) { 1653 - if (bd_folio) { 1654 - folio_lock(bd_folio); 1655 - folio_wait_writeback(bd_folio); 1656 - folio_clear_dirty_for_io(bd_folio); 1657 - folio_start_writeback(bd_folio); 1658 - folio_unlock(bd_folio); 1659 - } 1660 - bd_folio = bh->b_folio; 1661 - } 1662 - } 1663 - 1660 + /* Prepare to write payload blocks */ 1661 + list_for_each_entry(segbuf, logs, sb_list) { 1664 1662 list_for_each_entry(bh, &segbuf->sb_payload_buffers, 1665 1663 b_assoc_buffers) { 1666 - if (bh == segbuf->sb_super_root) { 1667 - if (bh->b_folio != bd_folio) { 1668 - folio_lock(bd_folio); 1669 - folio_wait_writeback(bd_folio); 1670 - folio_clear_dirty_for_io(bd_folio); 1671 - folio_start_writeback(bd_folio); 1672 - folio_unlock(bd_folio); 1673 - bd_folio = bh->b_folio; 1674 - } 1664 + if (bh == segbuf->sb_super_root) 1675 1665 break; 1676 - } 1677 1666 set_buffer_async_write(bh); 1678 1667 if (bh->b_folio != fs_folio) { 1679 1668 nilfs_begin_folio_io(fs_folio); ··· 1670 1681 } 1671 1682 } 1672 1683 } 1684 + nilfs_begin_folio_io(fs_folio); 1685 + 1686 + nilfs_add_checksums_on_logs(logs, seed); 1687 + 1688 + /* Prepare to write segment summary blocks */ 1689 + list_for_each_entry(segbuf, logs, sb_list) { 1690 + list_for_each_entry(bh, &segbuf->sb_segsum_buffers, 1691 + b_assoc_buffers) { 1692 + if (bh->b_folio == bd_folio) 1693 + continue; 1694 + if (bd_folio) { 1695 + folio_lock(bd_folio); 1696 + folio_wait_writeback(bd_folio); 1697 + folio_clear_dirty_for_io(bd_folio); 1698 + folio_start_writeback(bd_folio); 1699 + folio_unlock(bd_folio); 1700 + } 1701 + bd_folio = bh->b_folio; 1702 + } 1703 + } 1704 + 1705 + /* Prepare to write super root block */ 1706 + bh = NILFS_LAST_SEGBUF(logs)->sb_super_root; 1707 + if (bh) { 1708 + if (bh->b_folio != bd_folio) { 1709 + folio_lock(bd_folio); 1710 + folio_wait_writeback(bd_folio); 1711 + folio_clear_dirty_for_io(bd_folio); 1712 + folio_start_writeback(bd_folio); 1713 + folio_unlock(bd_folio); 1714 + bd_folio = bh->b_folio; 1715 + } 1716 + } 1717 + 1673 1718 if (bd_folio) { 1674 1719 folio_lock(bd_folio); 1675 1720 folio_wait_writeback(bd_folio); ··· 1711 1688 folio_start_writeback(bd_folio); 1712 1689 folio_unlock(bd_folio); 1713 1690 } 1714 - nilfs_begin_folio_io(fs_folio); 1715 1691 } 1716 1692 1717 1693 static int nilfs_segctor_write(struct nilfs_sc_info *sci, ··· 2092 2070 nilfs_segctor_update_segusage(sci, nilfs->ns_sufile); 2093 2071 2094 2072 /* Write partial segments */ 2095 - nilfs_segctor_prepare_write(sci); 2096 - 2097 - nilfs_add_checksums_on_logs(&sci->sc_segbufs, 2098 - nilfs->ns_crc_seed); 2073 + nilfs_prepare_write_logs(&sci->sc_segbufs, nilfs->ns_crc_seed); 2099 2074 2100 2075 err = nilfs_segctor_write(sci, nilfs); 2101 2076 if (unlikely(err))