| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/28 21:18 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch only contains documentation updates, kerneldoc additions, comment conversions (from page to folio terminology), and a label rename (unlock_page to unlock_folio) with no functional code changes.",
"WorthFuzzing": false
} |
| 1/1 | 2026/08/28 21:18 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit c8e72e6f2fb6b14a8af84e4b3e90ea827d318f10\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Fri Aug 28 21:18:28 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst\nindex 60880eb0c49d1..de96b6745600b 100644\n--- a/Documentation/filesystems/porting.rst\n+++ b/Documentation/filesystems/porting.rst\n@@ -348,7 +348,7 @@ simply of return 1. Note that all actual eviction work is done by caller after\n As before, clear_inode() must be called exactly once on each call of\n -\u003eevict_inode() (as it used to be for each call of -\u003edelete_inode()). Unlike\n before, if you are using inode-associated metadata buffers (i.e.\n-mark_buffer_dirty_inode()), it's your responsibility to call\n+mmb_mark_buffer_dirty()), it's your responsibility to call\n invalidate_inode_buffers() before clear_inode().\n \n NOTE: checking i_nlink in the beginning of -\u003ewrite_inode() and bailing out\ndiff --git a/fs/buffer.c b/fs/buffer.c\nindex ed966fa73b1ba..c9342aeb8cdf6 100644\n--- a/fs/buffer.c\n+++ b/fs/buffer.c\n@@ -265,7 +265,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block, bool atomic)\n \t\tbh = bh-\u003eb_this_page;\n \t} while (bh != head);\n \n-\t/* we might be here because some of the buffers on this page are\n+\t/* we might be here because some of the buffers on this folio are\n \t * not mapped. This is due to various races between\n \t * file io on the block device and getblk. It gets dealt with\n \t * elsewhere, don't buffer_error if we had some unmapped buffers\n@@ -311,7 +311,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)\n \t/*\n \t * Be _very_ careful from here on. Bad things can happen if\n \t * two buffer heads end IO at almost the same time and both\n-\t * decide that the page is now completely done.\n+\t * decide that the folio is now completely done.\n \t */\n \tfirst = folio_buffers(folio);\n \tspin_lock_irqsave(\u0026first-\u003eb_uptodate_lock, flags);\n@@ -520,8 +520,8 @@ EXPORT_SYMBOL_GPL(mmb_has_buffers);\n *\n * Do this in two main stages: first we copy dirty buffers to a\n * temporary inode list, queueing the writes as we go. Then we clean\n- * up, waiting for those writes to complete. mark_buffer_dirty_inode()\n- * doesn't touch b_assoc_buffers list if b_mmb is not NULL so we are sure the\n+ * up, waiting for those writes to complete. mmb_mark_buffer_dirty()\n+ * doesn't touch b_assoc_buffers list if b_mmb is set so we are sure the\n * buffer stays on our list until IO completes (at which point it can be\n * reaped).\n */\n@@ -542,7 +542,7 @@ int mmb_sync(struct mapping_metadata_bhs *mmb)\n \t\tbh = BH_ENTRY(mmb-\u003elist.next);\n \t\tWARN_ON_ONCE(bh-\u003eb_mmb != mmb);\n \t\t__remove_assoc_queue(mmb, bh);\n-\t\t/* Avoid race with mark_buffer_dirty_inode() which does\n+\t\t/* Avoid race with mmb_mark_buffer_dirty() which does\n \t\t * a lockless check and we rely on seeing the dirty bit */\n \t\tsmp_mb();\n \t\tif (buffer_dirty(bh) || buffer_locked(bh)) {\n@@ -580,7 +580,7 @@ int mmb_sync(struct mapping_metadata_bhs *mmb)\n \t\tbh = BH_ENTRY(tmp.prev);\n \t\tget_bh(bh);\n \t\t__remove_assoc_queue(mmb, bh);\n-\t\t/* Avoid race with mark_buffer_dirty_inode() which does\n+\t\t/* Avoid race with mmb_mark_buffer_dirty() which does\n \t\t * a lockless check and we rely on seeing the dirty bit */\n \t\tsmp_mb();\n \t\tif (buffer_dirty(bh)) {\n@@ -618,6 +618,14 @@ void write_boundary_block(struct block_device *bdev,\n \t}\n }\n \n+/**\n+ * mmb_mark_buffer_dirty - Mark a metadata buffer dirty.\n+ * @bh: The buffer to mark dirty.\n+ * @mmb: The list of buffers to add the buffer to.\n+ *\n+ * Mark the buffer dirty and add it to the list if it is not already on\n+ * a list.\n+ */\n void mmb_mark_buffer_dirty(struct buffer_head *bh,\n \t\t\t struct mapping_metadata_bhs *mmb)\n {\n@@ -686,7 +694,7 @@ bool block_dirty_folio(struct address_space *mapping, struct folio *folio)\n \t\t} while (bh != head);\n \t}\n \t/*\n-\t * Lock out page's memcg migration to keep PageDirty\n+\t * Lock out folio's memcg migration to keep folio dirty flag\n \t * synchronized with per-memcg dirty page counters.\n \t */\n \tnewly_dirty = !folio_test_set_dirty(folio);\n@@ -952,23 +960,23 @@ __getblk_slow(struct block_device *bdev, sector_t block,\n }\n \n /*\n- * The relationship between dirty buffers and dirty pages:\n+ * The relationship between dirty buffers and dirty folios:\n *\n- * Whenever a page has any dirty buffers, the page's dirty bit is set, and\n- * the page is tagged dirty in the page cache.\n+ * Whenever a folio has any dirty buffers, the folio's dirty flag is set, and\n+ * the folio is tagged dirty in the page cache.\n *\n * At all times, the dirtiness of the buffers represents the dirtiness of\n- * subsections of the page. If the page has buffers, the page dirty bit is\n+ * subsections of the folio. If the folio has buffers, the folio dirty flag is\n * merely a hint about the true dirty state.\n *\n- * When a page is set dirty in its entirety, all its buffers are marked dirty\n- * (if the page has buffers).\n+ * When a folio is set dirty in its entirety, all its buffers are marked dirty\n+ * (if the folio has buffers).\n *\n- * When a buffer is marked dirty, its page is dirtied, but the page's other\n+ * When a buffer is marked dirty, its folio is dirtied, but the folio's other\n * buffers are not.\n *\n * Also. When blockdev buffers are explicitly read with bread(), they\n- * individually become uptodate. But their backing page remains not\n+ * individually become uptodate. But their backing folio remains not\n * uptodate - even if all of its buffers are uptodate. A subsequent\n * block_read_full_folio() against that folio will discover all the uptodate\n * buffers, will set the folio uptodate and will perform no I/O.\n@@ -979,7 +987,7 @@ __getblk_slow(struct block_device *bdev, sector_t block,\n * @bh: the buffer_head to mark dirty\n *\n * mark_buffer_dirty() will set the dirty bit against the buffer, then set\n- * its backing page dirty, then tag the page as dirty in the page cache\n+ * its backing folio dirty, then tag the folio as dirty in the page cache\n * and then attach the address_space's inode to its superblock's dirty\n * inode list.\n *\n@@ -1074,7 +1082,7 @@ static void buffer_set_crypto_ctx(struct bio *bio, const struct buffer_head *bh,\n \n \t/*\n \t * The ext4 journal (jbd2) can submit a buffer_head it directly created\n-\t * for a non-pagecache page. fscrypt doesn't care about these.\n+\t * for a non-pagecache folio. fscrypt doesn't care about these.\n \t */\n \tif (!mapping)\n \t\treturn;\n@@ -1216,7 +1224,7 @@ static void bh_lru_install(struct buffer_head *bh)\n \n \t/*\n \t * the refcount of buffer_head in bh_lru prevents dropping the\n-\t * attached page(i.e., try_to_free_buffers) so it could cause\n+\t * attached folio (i.e., try_to_free_buffers) so it could cause\n \t * failing page migration.\n \t * Skip putting upcoming bh into bh_lru until migration is done.\n \t */\n@@ -1280,7 +1288,7 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)\n * Perform a pagecache lookup for the matching buffer. If it's there, refresh\n * it in the LRU and mark it as accessed. If it is not present then return\n * NULL. Atomic context callers may also return NULL if the buffer is being\n- * migrated; similarly the page is not marked accessed either.\n+ * migrated; similarly the folio is not marked accessed either.\n */\n static struct buffer_head *\n find_get_block_common(struct block_device *bdev, sector_t block,\n@@ -1289,7 +1297,7 @@ find_get_block_common(struct block_device *bdev, sector_t block,\n \tstruct buffer_head *bh = lookup_bh_lru(bdev, block, size);\n \n \tif (bh == NULL) {\n-\t\t/* __find_get_block_slow will mark the page accessed */\n+\t\t/* __find_get_block_slow will mark the folio accessed */\n \t\tbh = __find_get_block_slow(bdev, block, atomic);\n \t\tif (bh)\n \t\t\tbh_lru_install(bh);\n@@ -1475,15 +1483,14 @@ void folio_set_bh(struct buffer_head *bh, struct folio *folio,\n }\n EXPORT_SYMBOL(folio_set_bh);\n \n-/*\n- * Called when truncating a buffer on a page completely.\n- */\n-\n /* Bits that are cleared during an invalidate */\n #define BUFFER_FLAGS_DISCARD \\\n \t(1 \u003c\u003c BH_Mapped | 1 \u003c\u003c BH_New | 1 \u003c\u003c BH_Req | \\\n \t 1 \u003c\u003c BH_Delay | 1 \u003c\u003c BH_Unwritten)\n \n+/*\n+ * Called when truncating a buffer on a folio completely.\n+ */\n static void discard_buffer(struct buffer_head * bh)\n {\n \tunsigned long b_state;\n@@ -1611,9 +1618,7 @@ EXPORT_SYMBOL(create_empty_buffers);\n * moment when something will explicitly mark the buffer dirty (hopefully that\n * will not happen until we will free that block ;-) We don't even need to mark\n * it not-uptodate - nobody can expect anything from a newly allocated buffer\n- * anyway. We used to use unmap_buffer() for such invalidation, but that was\n- * wrong. We definitely don't want to mark the alias unmapped, for example - it\n- * would confuse anyone who might pick it with bread() afterwards...\n+ * anyway.\n *\n * Also.. Note that bforget() doesn't lock the buffer. So there can be\n * writeout I/O going on against recently-freed buffers. We don't wait on that\n@@ -1649,7 +1654,7 @@ void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len)\n \t\t\t/* Recheck when the folio is locked which pins bhs */\n \t\t\thead = folio_buffers(folio);\n \t\t\tif (!head)\n-\t\t\t\tgoto unlock_page;\n+\t\t\t\tgoto unlock_folio;\n \t\t\tbh = head;\n \t\t\tdo {\n \t\t\t\tif (!buffer_mapped(bh) || (bh-\u003eb_blocknr \u003c block))\n@@ -1662,7 +1667,7 @@ void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len)\n next:\n \t\t\t\tbh = bh-\u003eb_this_page;\n \t\t\t} while (bh != head);\n-unlock_page:\n+unlock_folio:\n \t\t\tfolio_unlock(folio);\n \t\t}\n \t\tfolio_batch_release(\u0026fbatch);\n@@ -1710,7 +1715,7 @@ static struct buffer_head *folio_create_buffers(struct folio *folio,\n *\n * If block_write_full_folio() is called for regular writeback\n * (wbc-\u003esync_mode == WB_SYNC_NONE) then it will redirty a folio which\n- * has a locked buffer. This only can happen if someone has written\n+ * has a locked buffer. This can only happen if someone has written\n * the buffer directly, with bh_submit(). At the address_space level\n * the folio writeback flag prevents this contention from occurring.\n *\n@@ -2213,9 +2218,9 @@ int generic_write_end(const struct kiocb *iocb, struct address_space *mapping,\n \tif (old_size \u003c pos)\n \t\tpagecache_isize_extended(inode, old_size, pos);\n \t/*\n-\t * Don't mark the inode dirty under page lock. First, it unnecessarily\n-\t * makes the holding time of page lock longer. Second, it forces lock\n-\t * ordering of page lock and transaction start for journaling\n+\t * Don't mark the inode dirty under folio lock. First, it unnecessarily\n+\t * makes the holding time of folio lock longer. Second, it forces lock\n+\t * ordering of folio lock and transaction start for journaling\n \t * filesystems.\n \t */\n \tif (i_size_changed)\n@@ -2341,7 +2346,7 @@ int block_read_full_folio(struct folio *folio, get_block_t *get_block)\n \t\t * BH_Async_Read tells end_buffer_async_read() that this\n \t\t * buffer is not under async I/O.\n \t\t *\n-\t\t * The folio comes unlocked when it has no locked\n+\t\t * The folio is unlocked when it has no locked\n \t\t * buffer_async buffers left.\n \t\t *\n \t\t * The folio lock prevents anyone starting new async\n@@ -2451,7 +2456,7 @@ static int cont_expand_zero(const struct kiocb *iocb,\n \t\t}\n \t}\n \n-\t/* page covers the boundary, find the boundary offset */\n+\t/* folio crosses the boundary, find the boundary offset */\n \tif (index == curidx) {\n \t\tzerofrom = curpos \u0026 ~PAGE_MASK;\n \t\t/* if we will expand the thing last block will be filled */\n@@ -2509,18 +2514,18 @@ EXPORT_SYMBOL(cont_write_begin);\n \n /*\n * block_page_mkwrite() is not allowed to change the file size as it gets\n- * called from a page fault handler when a page is first dirtied. Hence we must\n- * be careful to check for EOF conditions here. We set the page up correctly\n- * for a written page which means we get ENOSPC checking when writing into\n+ * called from a page fault handler when a folio is first dirtied. Hence we must\n+ * be careful to check for EOF conditions here. We set the folio up correctly\n+ * for a written folio which means we get ENOSPC checking when writing into\n * holes and correct delalloc and unwritten extent mapping on filesystems that\n * support these features.\n *\n * We are not allowed to take the i_rwsem here so we have to play games to\n- * protect against truncate races as the page could now be beyond EOF. Because\n- * truncate writes the inode size before removing pages, once we have the\n- * page lock we can determine safely if the page is beyond EOF. If it is not\n- * beyond EOF, then the page is guaranteed safe against truncation until we\n- * unlock the page.\n+ * protect against truncate races as the folio could now be beyond EOF. Because\n+ * truncate writes the inode size before removing folios, once we have the\n+ * folio lock we can determine safely if the folio is beyond EOF. If it is not\n+ * beyond EOF, then the folio is guaranteed safe against truncation until we\n+ * unlock the folio.\n *\n * Direct callers of this function should protect against filesystem freezing\n * using sb_start_pagefault() - sb_end_pagefault() functions.\n@@ -2538,7 +2543,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,\n \tsize = i_size_read(inode);\n \tif ((folio-\u003emapping != inode-\u003ei_mapping) ||\n \t (folio_pos(folio) \u003e= size)) {\n-\t\t/* We overload EFAULT to mean page got truncated */\n+\t\t/* We overload EFAULT to mean folio got truncated */\n \t\tret = -EFAULT;\n \t\tgoto out_unlock;\n \t}\ndiff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h\nindex fd2c7115c0542..1d55f7770cad1 100644\n--- a/include/linux/buffer_head.h\n+++ b/include/linux/buffer_head.h\n@@ -338,20 +338,58 @@ static inline void bforget(struct buffer_head *bh)\n \t\t__bforget(bh);\n }\n \n-static inline struct buffer_head *\n-sb_bread(struct super_block *sb, sector_t block)\n+/**\n+ * sb_bread - Read a block.\n+ * @sb: The superblock to read from.\n+ * @block: Block number in units of block size.\n+ *\n+ * Read a specified block, and return the buffer head that refers\n+ * to it. The memory is allocated from the movable area so that it can\n+ * be migrated. The returned buffer head has its refcount increased.\n+ * The caller should call brelse() when it has finished with the buffer.\n+ *\n+ * Context: May sleep waiting for I/O.\n+ * Return: NULL if the block was unreadable.\n+ */\n+static inline\n+struct buffer_head *sb_bread(struct super_block *sb, sector_t block)\n {\n \treturn __bread_gfp(sb-\u003es_bdev, block, sb-\u003es_blocksize, __GFP_MOVABLE);\n }\n \n-static inline struct buffer_head *\n-sb_bread_unmovable(struct super_block *sb, sector_t block)\n+/**\n+ * sb_bread_unmovable - Read a block.\n+ * @sb: The superblock to read from.\n+ * @block: Block number in units of block size.\n+ *\n+ * Read a specified block, and return the buffer head that refers to it.\n+ * The memory is allocated from the unmovable area so that pointers into\n+ * it remain valid after compaction runs. The returned buffer head has\n+ * its refcount increased. The caller should call brelse() when it has\n+ * finished with the buffer.\n+ *\n+ * Context: May sleep waiting for I/O.\n+ * Return: NULL if the block was unreadable.\n+ */\n+static inline\n+struct buffer_head *sb_bread_unmovable(struct super_block *sb, sector_t block)\n {\n \treturn __bread_gfp(sb-\u003es_bdev, block, sb-\u003es_blocksize, 0);\n }\n \n-static inline void\n-sb_breadahead(struct super_block *sb, sector_t block)\n+/**\n+ * sb_breadahead - Start readahead.\n+ * @sb: Superblock identifying the block device.\n+ * @block: The block to read.\n+ *\n+ * Read this block. The I/O will be flagged as being readahead rather\n+ * than immediate read, but (unlike the page cache), surrounding blocks\n+ * will not be read.\n+ *\n+ * Context: May sleep in order to allocate memory.\n+ */\n+static inline\n+void sb_breadahead(struct super_block *sb, sector_t block)\n {\n \t__breadahead(sb-\u003es_bdev, block, sb-\u003es_blocksize);\n }\n"
} |
| 2/1 | 2026/08/28 21:18 | agent | patch-evaluator |
0mModel:core Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only contains documentation updates, kerneldoc additions, comment conversions (from page to folio terminology), and a label rename (unlock_page to unlock_folio) with no functional code changes.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit c8e72e6f2fb6b14a8af84e4b3e90ea827d318f10
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Aug 28 21:18:28 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 60880eb0c49d1..de96b6745600b 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -348,7 +348,7 @@ simply of return 1. Note that all actual eviction work is done by caller after
As before, clear_inode() must be called exactly once on each call of
->evict_inode() (as it used to be for each call of ->delete_inode()). Unlike
before, if you are using inode-associated metadata buffers (i.e.
-mark_buffer_dirty_inode()), it's your responsibility to call
+mmb_mark_buffer_dirty()), it's your responsibility to call
invalidate_inode_buffers() before clear_inode().
NOTE: checking i_nlink in the beginning of ->write_inode() and bailing out
diff --git a/fs/buffer.c b/fs/buffer.c
index ed966fa73b1ba..c9342aeb8cdf6 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -265,7 +265,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block, bool atomic)
bh = bh->b_this_page;
} while (bh != head);
- /* we might be here because some of the buffers on this page are
+ /* we might be here because some of the buffers on this folio are
* not mapped. This is due to various races between
* file io on the block device and getblk. It gets dealt with
* elsewhere, don't buffer_error if we had some unmapped buffers
@@ -311,7 +311,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
/*
* Be _very_ careful from here on. Bad things can happen if
* two buffer heads end IO at almost the same time and both
- * decide that the page is now completely done.
+ * decide that the folio is now completely done.
*/
first = folio_buffers(folio);
spin_lock_irqsave(&first->b_uptodate_lock, flags);
@@ -520,8 +520,8 @@ EXPORT_SYMBOL_GPL(mmb_has_buffers);
*
* Do this in two main stages: first we copy dirty buffers to a
* temporary inode list, queueing the writes as we go. Then we clean
- * up, waiting for those writes to complete. mark_buffer_dirty_inode()
- * doesn't touch b_assoc_buffers list if b_mmb is not NULL so we are sure the
+ * up, waiting for those writes to complete. mmb_mark_buffer_dirty()
+ * doesn't touch b_assoc_buffers list if b_mmb is set so we are sure the
* buffer stays on our list until IO completes (at which point it can be
* reaped).
*/
@@ -542,7 +542,7 @@ int mmb_sync(struct mapping_metadata_bhs *mmb)
bh = BH_ENTRY(mmb->list.next);
WARN_ON_ONCE(bh->b_mmb != mmb);
__remove_assoc_queue(mmb, bh);
- /* Avoid race with mark_buffer_dirty_inode() which does
+ /* Avoid race with mmb_mark_buffer_dirty() which does
* a lockless check and we rely on seeing the dirty bit */
smp_mb();
if (buffer_dirty(bh) || buffer_locked(bh)) {
@@ -580,7 +580,7 @@ int mmb_sync(struct mapping_metadata_bhs *mmb)
bh = BH_ENTRY(tmp.prev);
get_bh(bh);
__remove_assoc_queue(mmb, bh);
- /* Avoid race with mark_buffer_dirty_inode() which does
+ /* Avoid race with mmb_mark_buffer_dirty() which does
* a lockless check and we rely on seeing the dirty bit */
smp_mb();
if (buffer_dirty(bh)) {
@@ -618,6 +618,14 @@ void write_boundary_block(struct block_device *bdev,
}
}
+/**
+ * mmb_mark_buffer_dirty - Mark a metadata buffer dirty.
+ * @bh: The buffer to mark dirty.
+ * @mmb: The list of buffers to add the buffer to.
+ *
+ * Mark the buffer dirty and add it to the list if it is not already on
+ * a list.
+ */
void mmb_mark_buffer_dirty(struct buffer_head *bh,
struct mapping_metadata_bhs *mmb)
{
@@ -686,7 +694,7 @@ bool block_dirty_folio(struct address_space *mapping, struct folio *folio)
} while (bh != head);
}
/*
- * Lock out page's memcg migration to keep PageDirty
+ * Lock out folio's memcg migration to keep folio dirty flag
* synchronized with per-memcg dirty page counters.
*/
newly_dirty = !folio_test_set_dirty(folio);
@@ -952,23 +960,23 @@ __getblk_slow(struct block_device *bdev, sector_t block,
}
/*
- * The relationship between dirty buffers and dirty pages:
+ * The relationship between dirty buffers and dirty folios:
*
- * Whenever a page has any dirty buffers, the page's dirty bit is set, and
- * the page is tagged dirty in the page cache.
+ * Whenever a folio has any dirty buffers, the folio's dirty flag is set, and
+ * the folio is tagged dirty in the page cache.
*
* At all times, the dirtiness of the buffers represents the dirtiness of
- * subsections of the page. If the page has buffers, the page dirty bit is
+ * subsections of the folio. If the folio has buffers, the folio dirty flag is
* merely a hint about the true dirty state.
*
- * When a page is set dirty in its entirety, all its buffers are marked dirty
- * (if the page has buffers).
+ * When a folio is set dirty in its entirety, all its buffers are marked dirty
+ * (if the folio has buffers).
*
- * When a buffer is marked dirty, its page is dirtied, but the page's other
+ * When a buffer is marked dirty, its folio is dirtied, but the folio's other
* buffers are not.
*
* Also. When blockdev buffers are explicitly read with bread(), they
- * individually become uptodate. But their backing page remains not
+ * individually become uptodate. But their backing folio remains not
* uptodate - even if all of its buffers are uptodate. A subsequent
* block_read_full_folio() against that folio will discover all the uptodate
* buffers, will set the folio uptodate and will perform no I/O.
@@ -979,7 +987,7 @@ __getblk_slow(struct block_device *bdev, sector_t block,
* @bh: the buffer_head to mark dirty
*
* mark_buffer_dirty() will set the dirty bit against the buffer, then set
- * its backing page dirty, then tag the page as dirty in the page cache
+ * its backing folio dirty, then tag the folio as dirty in the page cache
* and then attach the address_space's inode to its superblock's dirty
* inode list.
*
@@ -1074,7 +1082,7 @@ static void buffer_set_crypto_ctx(struct bio *bio, const struct buffer_head *bh,
/*
* The ext4 journal (jbd2) can submit a buffer_head it directly created
- * for a non-pagecache page. fscrypt doesn't care about these.
+ * for a non-pagecache folio. fscrypt doesn't care about these.
*/
if (!mapping)
return;
@@ -1216,7 +1224,7 @@ static void bh_lru_install(struct buffer_head *bh)
/*
* the refcount of buffer_head in bh_lru prevents dropping the
- * attached page(i.e., try_to_free_buffers) so it could cause
+ * attached folio (i.e., try_to_free_buffers) so it could cause
* failing page migration.
* Skip putting upcoming bh into bh_lru until migration is done.
*/
@@ -1280,7 +1288,7 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
* Perform a pagecache lookup for the matching buffer. If it's there, refresh
* it in the LRU and mark it as accessed. If it is not present then return
* NULL. Atomic context callers may also return NULL if the buffer is being
- * migrated; similarly the page is not marked accessed either.
+ * migrated; similarly the folio is not marked accessed either.
*/
static struct buffer_head *
find_get_block_common(struct block_device *bdev, sector_t block,
@@ -1289,7 +1297,7 @@ find_get_block_common(struct block_device *bdev, sector_t block,
struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
if (bh == NULL) {
- /* __find_get_block_slow will mark the page accessed */
+ /* __find_get_block_slow will mark the folio accessed */
bh = __find_get_block_slow(bdev, block, atomic);
if (bh)
bh_lru_install(bh);
@@ -1475,15 +1483,14 @@ void folio_set_bh(struct buffer_head *bh, struct folio *folio,
}
EXPORT_SYMBOL(folio_set_bh);
-/*
- * Called when truncating a buffer on a page completely.
- */
-
/* Bits that are cleared during an invalidate */
#define BUFFER_FLAGS_DISCARD \
(1 << BH_Mapped | 1 << BH_New | 1 << BH_Req | \
1 << BH_Delay | 1 << BH_Unwritten)
+/*
+ * Called when truncating a buffer on a folio completely.
+ */
static void discard_buffer(struct buffer_head * bh)
{
unsigned long b_state;
@@ -1611,9 +1618,7 @@ EXPORT_SYMBOL(create_empty_buffers);
* moment when something will explicitly mark the buffer dirty (hopefully that
* will not happen until we will free that block ;-) We don't even need to mark
* it not-uptodate - nobody can expect anything from a newly allocated buffer
- * anyway. We used to use unmap_buffer() for such invalidation, but that was
- * wrong. We definitely don't want to mark the alias unmapped, for example - it
- * would confuse anyone who might pick it with bread() afterwards...
+ * anyway.
*
* Also.. Note that bforget() doesn't lock the buffer. So there can be
* writeout I/O going on against recently-freed buffers. We don't wait on that
@@ -1649,7 +1654,7 @@ void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len)
/* Recheck when the folio is locked which pins bhs */
head = folio_buffers(folio);
if (!head)
- goto unlock_page;
+ goto unlock_folio;
bh = head;
do {
if (!buffer_mapped(bh) || (bh->b_blocknr < block))
@@ -1662,7 +1667,7 @@ void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len)
next:
bh = bh->b_this_page;
} while (bh != head);
-unlock_page:
+unlock_folio:
folio_unlock(folio);
}
folio_batch_release(&fbatch);
@@ -1710,7 +1715,7 @@ static struct buffer_head *folio_create_buffers(struct folio *folio,
*
* If block_write_full_folio() is called for regular writeback
* (wbc->sync_mode == WB_SYNC_NONE) then it will redirty a folio which
- * has a locked buffer. This only can happen if someone has written
+ * has a locked buffer. This can only happen if someone has written
* the buffer directly, with bh_submit(). At the address_space level
* the folio writeback flag prevents this contention from occurring.
*
@@ -2213,9 +2218,9 @@ int generic_write_end(const struct kiocb *iocb, struct address_space *mapping,
if (old_size < pos)
pagecache_isize_extended(inode, old_size, pos);
/*
- * Don't mark the inode dirty under page lock. First, it unnecessarily
- * makes the holding time of page lock longer. Second, it forces lock
- * ordering of page lock and transaction start for journaling
+ * Don't mark the inode dirty under folio lock. First, it unnecessarily
+ * makes the holding time of folio lock longer. Second, it forces lock
+ * ordering of folio lock and transaction start for journaling
* filesystems.
*/
if (i_size_changed)
@@ -2341,7 +2346,7 @@ int block_read_full_folio(struct folio *folio, get_block_t *get_block)
* BH_Async_Read tells end_buffer_async_read() that this
* buffer is not under async I/O.
*
- * The folio comes unlocked when it has no locked
+ * The folio is unlocked when it has no locked
* buffer_async buffers left.
*
* The folio lock prevents anyone starting new async
@@ -2451,7 +2456,7 @@ static int cont_expand_zero(const struct kiocb *iocb,
}
}
- /* page covers the boundary, find the boundary offset */
+ /* folio crosses the boundary, find the boundary offset */
if (index == curidx) {
zerofrom = curpos & ~PAGE_MASK;
/* if we will expand the thing last block will be filled */
@@ -2509,18 +2514,18 @@ EXPORT_SYMBOL(cont_write_begin);
/*
* block_page_mkwrite() is not allowed to change the file size as it gets
- * called from a page fault handler when a page is first dirtied. Hence we must
- * be careful to check for EOF conditions here. We set the page up correctly
- * for a written page which means we get ENOSPC checking when writing into
+ * called from a page fault handler when a folio is first dirtied. Hence we must
+ * be careful to check for EOF conditions here. We set the folio up correctly
+ * for a written folio which means we get ENOSPC checking when writing into
* holes and correct delalloc and unwritten extent mapping on filesystems that
* support these features.
*
* We are not allowed to take the i_rwsem here so we have to play games to
- * protect against truncate races as the page could now be beyond EOF. Because
- * truncate writes the inode size before removing pages, once we have the
- * page lock we can determine safely if the page is beyond EOF. If it is not
- * beyond EOF, then the page is guaranteed safe against truncation until we
- * unlock the page.
+ * protect against truncate races as the folio could now be beyond EOF. Because
+ * truncate writes the inode size before removing folios, once we have the
+ * folio lock we can determine safely if the folio is beyond EOF. If it is not
+ * beyond EOF, then the folio is guaranteed safe against truncation until we
+ * unlock the folio.
*
* Direct callers of this function should protect against filesystem freezing
* using sb_start_pagefault() - sb_end_pagefault() functions.
@@ -2538,7 +2543,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
size = i_size_read(inode);
if ((folio->mapping != inode->i_mapping) ||
(folio_pos(folio) >= size)) {
- /* We overload EFAULT to mean page got truncated */
+ /* We overload EFAULT to mean folio got truncated */
ret = -EFAULT;
goto out_unlock;
}
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index fd2c7115c0542..1d55f7770cad1 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -338,20 +338,58 @@ static inline void bforget(struct buffer_head *bh)
__bforget(bh);
}
-static inline struct buffer_head *
-sb_bread(struct super_block *sb, sector_t block)
+/**
+ * sb_bread - Read a block.
+ * @sb: The superblock to read from.
+ * @block: Block number in units of block size.
+ *
+ * Read a specified block, and return the buffer head that refers
+ * to it. The memory is allocated from the movable area so that it can
+ * be migrated. The returned buffer head has its refcount increased.
+ * The caller should call brelse() when it has finished with the buffer.
+ *
+ * Context: May sleep waiting for I/O.
+ * Return: NULL if the block was unreadable.
+ */
+static inline
+struct buffer_head *sb_bread(struct super_block *sb, sector_t block)
{
return __bread_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
}
-static inline struct buffer_head *
-sb_bread_unmovable(struct super_block *sb, sector_t block)
+/**
+ * sb_bread_unmovable - Read a block.
+ * @sb: The superblock to read from.
+ * @block: Block number in units of block size.
+ *
+ * Read a specified block, and return the buffer head that refers to it.
+ * The memory is allocated from the unmovable area so that pointers into
+ * it remain valid after compaction runs. The returned buffer head has
+ * its refcount increased. The caller should call brelse() when it has
+ * finished with the buffer.
+ *
+ * Context: May sleep waiting for I/O.
+ * Return: NULL if the block was unreadable.
+ */
+static inline
+struct buffer_head *sb_bread_unmovable(struct super_block *sb, sector_t block)
{
return __bread_gfp(sb->s_bdev, block, sb->s_blocksize, 0);
}
-static inline void
-sb_breadahead(struct super_block *sb, sector_t block)
+/**
+ * sb_breadahead - Start readahead.
+ * @sb: Superblock identifying the block device.
+ * @block: The block to read.
+ *
+ * Read this block. The I/O will be flagged as being readahead rather
+ * than immediate read, but (unlike the page cache), surrounding blocks
+ * will not be read.
+ *
+ * Context: May sleep in order to allocate memory.
+ */
+static inline
+void sb_breadahead(struct super_block *sb, sector_t block)
{
__breadahead(sb->s_bdev, block, sb->s_blocksize);
}
|
| 3/2 | 2026/08/28 21:18 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 6943 output: 71 thoughts: 689 Thoughts: **Patch Analysis: WorthFuzzing Evaluation** Okay, let's break down this patch. My initial focus is to understand its scope and potential impact. First, I note the changed files: `Documentation/filesystems/porting.rst`, `fs/buffer.c`, and `include/linux/buffer_head.h`. That gives me a general area to look into. Now for the detailed diff. I see that the documentation file has a simple doc update, renaming `mark_buffer_dirty_inode()` to `mmb_mark_buffer_dirty()`. In `fs/buffer.c`, it's primarily comment updates, replacing "page" with "folio," and the same function name change, including renaming a label from `unlock_page` to `unlock_folio` in `clean_bdev_aliases`. There also looks like some new kerneldoc comments for `mmb_mark_buffer_dirty` are present. Over in `include/linux/buffer_head.h`, there are kerneldoc additions for `sb_bread`, `sb_bread_unmovable`, and `sb_breadahead`, along with some very minor formatting adjustments to function signatures (just line wrapping, no actual code changes). Crucially, I need to confirm there's no functional change. I'd love to grab the specific commit diff (c8e72e6f2fb6b14a8af84e4b3e90ea827d318f10) if possible, but reading the diff directly confirms my suspicion: *all* the changes are strictly documentation updates, comment modifications, kerneldoc, the label rename (which is purely cosmetic), and formatting tweaks. Absolutely no logic changes. Now, based on the provided instructions, I need to determine if this patch warrants fuzzing. The criteria clearly state that if the patch contains only documentation, code comments, or purely decorative changes, like logging, it's not worth fuzzing. That covers all the changes I've observed: documentation, comments, and the label/formatting changes. Therefore, my conclusion is clear: `WorthFuzzing` should be `false`. This patch introduces no new code paths or modifications to existing execution logic, therefore fuzzing it would be a waste of resources. Finally, I need to make sure I'm setting the proper values: - `WorthFuzzing`: `false` - `FocusSymbols`: `[]` (empty list, as there are no symbols to focus on) - `EnableConfigs`: `[]` (empty list, as there are no configurations to enable) - `Reasoning`: "The patch contains only documentation, code comments, kerneldoc, label renaming and formatting changes. There are no functional changes." Time to verify with the `set-results` tool and move on. |
| 4/2 | 2026/08/28 21:18 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch only contains documentation updates, kerneldoc additions, comment conversions (from page to folio terminology), and a label rename (unlock_page to unlock_folio) with no functional code changes.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only contains documentation updates, kerneldoc additions, comment conversions (from page to folio terminology), and a label rename (unlock_page to unlock_folio) with no functional code changes.",
"WorthFuzzing": false
} |
| 5/1 | 2026/08/28 21:18 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|