| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/28 00:13 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"EXT4_FS"
],
"FocusSymbols": [
"ext4_convert_inline_data",
"ext4_generic_write_inline_data",
"ext4_destroy_inline_data"
],
"Reasoning": "The patch deprecates the inline_data feature for regular files in ext4, forcing conversion to block-based storage on write. This modifies core ext4 write paths and inline data conversion logic, which should be fuzzed to ensure no regressions or data corruption issues.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/28 00:13 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 7a530d0f5407f0fddb942be14dc7b3cc904c5413\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Tue Jul 28 00:13:47 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/filesystems/ext4/inlinedata.rst b/Documentation/filesystems/ext4/inlinedata.rst\nindex a728af0d2fd0c5..8dc1b6d75388d7 100644\n--- a/Documentation/filesystems/ext4/inlinedata.rst\n+++ b/Documentation/filesystems/ext4/inlinedata.rst\n@@ -3,6 +3,14 @@\n Inline Data\n -----------\n \n+.. warning::\n+\n+ The inline data feature is deprecated and will be removed in a future\n+ kernel release. New regular file inodes no longer store data inline,\n+ and writes to existing inline data inodes trigger automatic conversion\n+ to block-based storage. Use ``tune2fs -O ^inline_data`` to convert\n+ existing filesystems.\n+\n The inline data feature was designed to handle the case that a file's\n data is so tiny that it readily fits inside the inode, which\n (theoretically) reduces disk block consumption and reduces seeks. If the\ndiff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h\nindex 21a951f1063678..832bc1f3b60027 100644\n--- a/fs/ext4/ext4.h\n+++ b/fs/ext4/ext4.h\n@@ -3148,7 +3148,6 @@ int do_journal_get_write_access(handle_t *handle, struct inode *inode,\n \t\t\t\tstruct buffer_head *bh);\n void ext4_set_inode_mapping_order(struct inode *inode);\n #define FALL_BACK_TO_NONDELALLOC 1\n-#define EXT4_WRITE_DATA_INLINE\t 2\n \n typedef enum {\n \tEXT4_IGET_NORMAL =\t0,\n@@ -3759,12 +3758,6 @@ extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);\n extern void ext4_update_final_de(void *de_buf, int old_size, int new_size);\n \n int ext4_readpage_inline(struct inode *inode, struct folio *folio);\n-extern int ext4_try_to_write_inline_data(struct address_space *mapping,\n-\t\t\t\t\t struct inode *inode,\n-\t\t\t\t\t loff_t pos, unsigned len,\n-\t\t\t\t\t struct folio **foliop);\n-int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,\n-\t\t\t unsigned copied, struct folio *folio);\n extern int ext4_generic_write_inline_data(struct address_space *mapping,\n \t\t\t\t\t struct inode *inode,\n \t\t\t\t\t loff_t pos, unsigned len,\ndiff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c\nindex a40cb27f8116cb..278f0ab8c996e4 100644\n--- a/fs/ext4/ialloc.c\n+++ b/fs/ext4/ialloc.c\n@@ -1305,8 +1305,8 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,\n \n \tei-\u003ei_extra_isize = sbi-\u003es_want_extra_isize;\n \tei-\u003ei_inline_off = 0;\n-\tif (ext4_has_feature_inline_data(sb) \u0026\u0026\n-\t (!(ei-\u003ei_flags \u0026 (EXT4_DAX_FL|EXT4_EA_INODE_FL)) || S_ISDIR(mode)))\n+\tif (ext4_has_feature_inline_data(sb) \u0026\u0026 S_ISDIR(mode) \u0026\u0026\n+\t !(ei-\u003ei_flags \u0026 EXT4_DAX_FL))\n \t\text4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);\n \tret = inode;\n \terr = dquot_alloc_inode(inode);\ndiff --git a/fs/ext4/inline.c b/fs/ext4/inline.c\nindex ceee69a66482bc..e0b80273e322d8 100644\n--- a/fs/ext4/inline.c\n+++ b/fs/ext4/inline.c\n@@ -12,6 +12,7 @@\n \n #include \"ext4_jbd2.h\"\n #include \"ext4.h\"\n+#include \"ext4_extents.h\"\n #include \"xattr.h\"\n #include \"truncate.h\"\n \n@@ -20,10 +21,6 @@\n #define EXT4_INLINE_DOTDOT_OFFSET\t2\n #define EXT4_INLINE_DOTDOT_SIZE\t\t4\n \n-\n-static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,\n-\t\t\t\t\t\t struct inode *inode);\n-\n static int ext4_get_inline_size(struct inode *inode)\n {\n \tif (EXT4_I(inode)-\u003ei_inline_off)\n@@ -218,51 +215,6 @@ static int ext4_read_inline_data(struct inode *inode, void *buffer,\n \treturn cp_len;\n }\n \n-/*\n- * write the buffer to the inline inode.\n- * If 'create' is set, we don't need to do the extra copy in the xattr\n- * value since it is already handled by ext4_xattr_ibody_set.\n- * That saves us one memcpy.\n- */\n-static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,\n-\t\t\t\t void *buffer, loff_t pos, unsigned int len)\n-{\n-\tstruct ext4_xattr_entry *entry;\n-\tstruct ext4_xattr_ibody_header *header;\n-\tstruct ext4_inode *raw_inode;\n-\tint cp_len = 0;\n-\n-\tif (unlikely(ext4_emergency_state(inode-\u003ei_sb)))\n-\t\treturn;\n-\n-\tBUG_ON(!EXT4_I(inode)-\u003ei_inline_off);\n-\tBUG_ON(pos + len \u003e EXT4_I(inode)-\u003ei_inline_size);\n-\n-\traw_inode = ext4_raw_inode(iloc);\n-\tbuffer += pos;\n-\n-\tif (pos \u003c EXT4_MIN_INLINE_DATA_SIZE) {\n-\t\tcp_len = pos + len \u003e EXT4_MIN_INLINE_DATA_SIZE ?\n-\t\t\t EXT4_MIN_INLINE_DATA_SIZE - pos : len;\n-\t\tmemcpy((void *)raw_inode-\u003ei_block + pos, buffer, cp_len);\n-\n-\t\tlen -= cp_len;\n-\t\tbuffer += cp_len;\n-\t\tpos += cp_len;\n-\t}\n-\n-\tif (!len)\n-\t\treturn;\n-\n-\tpos -= EXT4_MIN_INLINE_DATA_SIZE;\n-\theader = IHDR(inode, raw_inode);\n-\tentry = (struct ext4_xattr_entry *)((void *)raw_inode +\n-\t\t\t\t\t EXT4_I(inode)-\u003ei_inline_off);\n-\n-\tmemcpy((void *)IFIRST(header) + le16_to_cpu(entry-\u003ee_value_offs) + pos,\n-\t buffer, len);\n-}\n-\n static int ext4_create_inline_data(handle_t *handle,\n \t\t\t\t struct inode *inode, unsigned len)\n {\n@@ -433,7 +385,8 @@ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,\n }\n \n static int ext4_destroy_inline_data_nolock(handle_t *handle,\n-\t\t\t\t\t struct inode *inode)\n+\t\t\t\t\t struct inode *inode,\n+\t\t\t\t\t ext4_fsblk_t pblk)\n {\n \tstruct ext4_inode_info *ei = EXT4_I(inode);\n \tstruct ext4_xattr_ibody_find is = {\n@@ -481,7 +434,21 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,\n \t\t S_ISREG(inode-\u003ei_mode) || S_ISLNK(inode-\u003ei_mode)) {\n \t\t\text4_set_inode_flag(inode, EXT4_INODE_EXTENTS);\n \t\t\text4_ext_tree_init(handle, inode);\n+\t\t\tif (pblk) {\n+\t\t\t\tstruct ext4_extent_header *eh;\n+\t\t\t\tstruct ext4_extent *ex;\n+\n+\t\t\t\teh = ext_inode_hdr(inode);\n+\t\t\t\tex = EXT_FIRST_EXTENT(eh);\n+\t\t\t\tex-\u003eee_block = cpu_to_le32(0);\n+\t\t\t\tex-\u003eee_len = cpu_to_le16(1);\n+\t\t\t\text4_ext_store_pblock(ex, pblk);\n+\t\t\t\teh-\u003eeh_entries = cpu_to_le16(1);\n+\t\t\t}\n \t\t}\n+\t} else if (pblk) {\n+\t\t/* indirect mapping: set i_data[0] directly */\n+\t\tEXT4_I(inode)-\u003ei_data[0] = cpu_to_le32(pblk);\n \t}\n \text4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);\n \n@@ -568,122 +535,6 @@ int ext4_readpage_inline(struct inode *inode, struct folio *folio)\n \treturn ret \u003e= 0 ? 0 : ret;\n }\n \n-static int ext4_convert_inline_data_to_extent(struct address_space *mapping,\n-\t\t\t\t\t struct inode *inode)\n-{\n-\tint ret, needed_blocks, no_expand;\n-\thandle_t *handle = NULL;\n-\tint retries = 0, sem_held = 0;\n-\tstruct folio *folio = NULL;\n-\tunsigned from, to;\n-\tstruct ext4_iloc iloc;\n-\n-\tif (!ext4_has_inline_data(inode)) {\n-\t\t/*\n-\t\t * clear the flag so that no new write\n-\t\t * will trap here again.\n-\t\t */\n-\t\text4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);\n-\t\treturn 0;\n-\t}\n-\n-\tneeded_blocks = ext4_chunk_trans_extent(inode, 1);\n-\n-\tret = ext4_get_inode_loc(inode, \u0026iloc);\n-\tif (ret)\n-\t\treturn ret;\n-\n-retry:\n-\thandle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);\n-\tif (IS_ERR(handle)) {\n-\t\tret = PTR_ERR(handle);\n-\t\thandle = NULL;\n-\t\tgoto out;\n-\t}\n-\n-\t/* We cannot recurse into the filesystem as the transaction is already\n-\t * started */\n-\tfolio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,\n-\t\t\tmapping_gfp_mask(mapping));\n-\tif (IS_ERR(folio)) {\n-\t\tret = PTR_ERR(folio);\n-\t\tgoto out_nofolio;\n-\t}\n-\n-\text4_write_lock_xattr(inode, \u0026no_expand);\n-\tsem_held = 1;\n-\t/* If some one has already done this for us, just exit. */\n-\tif (!ext4_has_inline_data(inode)) {\n-\t\tret = 0;\n-\t\tgoto out;\n-\t}\n-\n-\tfrom = 0;\n-\tto = ext4_get_inline_size(inode);\n-\tif (!folio_test_uptodate(folio)) {\n-\t\tret = ext4_read_inline_folio(inode, folio);\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto out;\n-\t}\n-\n-\text4_fc_track_inode(handle, inode);\n-\tret = ext4_destroy_inline_data_nolock(handle, inode);\n-\tif (ret)\n-\t\tgoto out;\n-\n-\tif (ext4_should_dioread_nolock(inode)) {\n-\t\tret = ext4_block_write_begin(handle, folio, from, to,\n-\t\t\t\t\t ext4_get_block_unwritten);\n-\t} else\n-\t\tret = ext4_block_write_begin(handle, folio, from, to,\n-\t\t\t\t\t ext4_get_block);\n-\tclear_buffer_new(folio_buffers(folio));\n-\n-\tif (!ret \u0026\u0026 ext4_should_journal_data(inode)) {\n-\t\tret = ext4_walk_page_buffers(handle, inode,\n-\t\t\t\t\t folio_buffers(folio), from, to,\n-\t\t\t\t\t NULL, do_journal_get_write_access);\n-\t}\n-\n-\tif (ret) {\n-\t\tfolio_unlock(folio);\n-\t\tfolio_put(folio);\n-\t\tfolio = NULL;\n-\t\text4_orphan_add(handle, inode);\n-\t\text4_write_unlock_xattr(inode, \u0026no_expand);\n-\t\tsem_held = 0;\n-\t\text4_journal_stop(handle);\n-\t\thandle = NULL;\n-\t\text4_truncate_failed_write(inode);\n-\t\t/*\n-\t\t * If truncate failed early the inode might\n-\t\t * still be on the orphan list; we need to\n-\t\t * make sure the inode is removed from the\n-\t\t * orphan list in that case.\n-\t\t */\n-\t\tif (inode-\u003ei_nlink)\n-\t\t\text4_orphan_del(NULL, inode);\n-\t}\n-\n-\tif (ret == -ENOSPC \u0026\u0026 ext4_should_retry_alloc(inode-\u003ei_sb, \u0026retries))\n-\t\tgoto retry;\n-\n-\tif (folio)\n-\t\tblock_commit_write(folio, from, to);\n-out:\n-\tif (folio) {\n-\t\tfolio_unlock(folio);\n-\t\tfolio_put(folio);\n-\t}\n-out_nofolio:\n-\tif (sem_held)\n-\t\text4_write_unlock_xattr(inode, \u0026no_expand);\n-\tif (handle)\n-\t\text4_journal_stop(handle);\n-\tbrelse(iloc.bh);\n-\treturn ret;\n-}\n-\n /*\n * Prepare the write for the inline data.\n * If the data can be written into the inode, we just read\n@@ -698,248 +549,8 @@ int ext4_generic_write_inline_data(struct address_space *mapping,\n \t\t\t\t\t struct folio **foliop,\n \t\t\t\t\t bool da)\n {\n-\tint ret;\n-\thandle_t *handle;\n-\tstruct folio *folio;\n-\tstruct ext4_iloc iloc;\n-\tint retries = 0;\n-\n-\tret = ext4_get_inode_loc(inode, \u0026iloc);\n-\tif (ret)\n-\t\treturn ret;\n-\n-retry_journal:\n-\thandle = ext4_journal_start(inode, EXT4_HT_INODE, 1);\n-\tif (IS_ERR(handle)) {\n-\t\tret = PTR_ERR(handle);\n-\t\tgoto out_release_bh;\n-\t}\n-\n-\tret = ext4_prepare_inline_data(handle, inode, pos + len);\n-\tif (ret \u0026\u0026 ret != -ENOSPC)\n-\t\tgoto out_stop_journal;\n-\n-\tif (ret == -ENOSPC) {\n-\t\text4_journal_stop(handle);\n-\t\tif (!da) {\n-\t\t\tbrelse(iloc.bh);\n-\t\t\t/* Retry inside */\n-\t\t\treturn ext4_convert_inline_data_to_extent(mapping, inode);\n-\t\t}\n-\n-\t\tret = ext4_da_convert_inline_data_to_extent(mapping, inode);\n-\t\tif (ret == -ENOSPC \u0026\u0026\n-\t\t ext4_should_retry_alloc(inode-\u003ei_sb, \u0026retries))\n-\t\t\tgoto retry_journal;\n-\t\tgoto out_release_bh;\n-\t}\n-\n-\tfolio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,\n-\t\t\t\t\tmapping_gfp_mask(mapping));\n-\tif (IS_ERR(folio)) {\n-\t\tret = PTR_ERR(folio);\n-\t\tgoto out_stop_journal;\n-\t}\n-\n-\tdown_read(\u0026EXT4_I(inode)-\u003exattr_sem);\n-\t/* Someone else had converted it to extent */\n-\tif (!ext4_has_inline_data(inode)) {\n-\t\tret = 0;\n-\t\tgoto out_release_folio;\n-\t}\n-\n-\tif (!folio_test_uptodate(folio)) {\n-\t\tret = ext4_read_inline_folio(inode, folio);\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto out_release_folio;\n-\t}\n-\n-\tret = ext4_journal_get_write_access(handle, inode-\u003ei_sb, iloc.bh, EXT4_JTR_NONE);\n-\tif (ret)\n-\t\tgoto out_release_folio;\n-\t*foliop = folio;\n-\tup_read(\u0026EXT4_I(inode)-\u003exattr_sem);\n-\tbrelse(iloc.bh);\n-\treturn 1;\n-\n-out_release_folio:\n-\tup_read(\u0026EXT4_I(inode)-\u003exattr_sem);\n-\tfolio_unlock(folio);\n-\tfolio_put(folio);\n-out_stop_journal:\n-\text4_journal_stop(handle);\n-out_release_bh:\n-\tbrelse(iloc.bh);\n-\treturn ret;\n-}\n-\n-/*\n- * Try to write data in the inode.\n- * If the inode has inline data, check whether the new write can be\n- * in the inode also. If not, create the page the handle, move the data\n- * to the page make it update and let the later codes create extent for it.\n- */\n-int ext4_try_to_write_inline_data(struct address_space *mapping,\n-\t\t\t\t struct inode *inode,\n-\t\t\t\t loff_t pos, unsigned len,\n-\t\t\t\t struct folio **foliop)\n-{\n-\tif (pos + len \u003e ext4_get_max_inline_size(inode))\n-\t\treturn ext4_convert_inline_data_to_extent(mapping, inode);\n-\treturn ext4_generic_write_inline_data(mapping, inode, pos, len,\n-\t\t\t\t\t foliop, false);\n-}\n-\n-int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,\n-\t\t\t unsigned copied, struct folio *folio)\n-{\n-\thandle_t *handle = ext4_journal_current_handle();\n-\tint no_expand;\n-\tvoid *kaddr;\n-\tstruct ext4_iloc iloc;\n-\tint ret = 0, ret2;\n-\n-\tif (unlikely(copied \u003c len) \u0026\u0026 !folio_test_uptodate(folio))\n-\t\tcopied = 0;\n-\n-\tif (likely(copied)) {\n-\t\tret = ext4_get_inode_loc(inode, \u0026iloc);\n-\t\tif (ret) {\n-\t\t\tfolio_unlock(folio);\n-\t\t\tfolio_put(folio);\n-\t\t\text4_std_error(inode-\u003ei_sb, ret);\n-\t\t\tgoto out;\n-\t\t}\n-\t\text4_write_lock_xattr(inode, \u0026no_expand);\n-\t\t/*\n-\t\t * We could have raced with ext4_page_mkwrite() converting\n-\t\t * the inode and clearing the inline data flag, so we just\n-\t\t * release resources and retry the whole write.\n-\t\t */\n-\t\tif (unlikely(!ext4_has_inline_data(inode))) {\n-\t\t\text4_write_unlock_xattr(inode, \u0026no_expand);\n-\t\t\tbrelse(iloc.bh);\n-\t\t\tfolio_unlock(folio);\n-\t\t\tfolio_put(folio);\n-\t\t\text4_journal_stop(handle);\n-\t\t\treturn 0;\n-\t\t}\n-\n-\t\t/*\n-\t\t * ei-\u003ei_inline_off may have changed since\n-\t\t * ext4_write_begin() called\n-\t\t * ext4_try_to_write_inline_data()\n-\t\t */\n-\t\t(void) ext4_find_inline_data_nolock(inode);\n-\n-\t\tkaddr = kmap_local_folio(folio, 0);\n-\t\text4_write_inline_data(inode, \u0026iloc, kaddr, pos, copied);\n-\t\tkunmap_local(kaddr);\n-\t\tfolio_mark_uptodate(folio);\n-\t\t/* clear dirty flag so that writepages wouldn't work for us. */\n-\t\tfolio_clear_dirty(folio);\n-\n-\t\text4_write_unlock_xattr(inode, \u0026no_expand);\n-\t\tbrelse(iloc.bh);\n-\n-\t\t/*\n-\t\t * It's important to update i_size while still holding folio\n-\t\t * lock: page writeout could otherwise come in and zero\n-\t\t * beyond i_size.\n-\t\t */\n-\t\text4_update_inode_size(inode, pos + copied);\n-\t}\n-\tfolio_unlock(folio);\n-\tfolio_put(folio);\n-\n-\t/*\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 (likely(copied))\n-\t\tmark_inode_dirty(inode);\n-out:\n-\t/*\n-\t * If we didn't copy as much data as expected, we need to trim back\n-\t * size of xattr containing inline data.\n-\t */\n-\tif (pos + len \u003e inode-\u003ei_size \u0026\u0026 ext4_can_truncate(inode))\n-\t\text4_orphan_add(handle, inode);\n-\n-\tret2 = ext4_journal_stop(handle);\n-\tif (!ret)\n-\t\tret = ret2;\n-\tif (pos + len \u003e inode-\u003ei_size) {\n-\t\text4_truncate_failed_write(inode);\n-\t\t/*\n-\t\t * If truncate failed early the inode might still be\n-\t\t * on the orphan list; we need to make sure the inode\n-\t\t * is removed from the orphan list in that case.\n-\t\t */\n-\t\tif (inode-\u003ei_nlink)\n-\t\t\text4_orphan_del(NULL, inode);\n-\t}\n-\treturn ret ? ret : copied;\n-}\n-\n-/*\n- * Try to make the page cache and handle ready for the inline data case.\n- * We can call this function in 2 cases:\n- * 1. The inode is created and the first write exceeds inline size. We can\n- * clear the inode state safely.\n- * 2. The inode has inline data, then we need to read the data, make it\n- * update and dirty so that ext4_da_writepages can handle it. We don't\n- * need to start the journal since the file's metadata isn't changed now.\n- */\n-static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,\n-\t\t\t\t\t\t struct inode *inode)\n-{\n-\tint ret = 0, inline_size;\n-\tstruct folio *folio;\n-\n-\tfolio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN,\n-\t\t\t\t\tmapping_gfp_mask(mapping));\n-\tif (IS_ERR(folio))\n-\t\treturn PTR_ERR(folio);\n-\n-\tdown_read(\u0026EXT4_I(inode)-\u003exattr_sem);\n-\tif (!ext4_has_inline_data(inode)) {\n-\t\text4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);\n-\t\tgoto out;\n-\t}\n-\n-\tinline_size = ext4_get_inline_size(inode);\n-\n-\tif (!folio_test_uptodate(folio)) {\n-\t\tret = ext4_read_inline_folio(inode, folio);\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto out;\n-\t}\n-\n-\tret = ext4_block_write_begin(NULL, folio, 0, inline_size,\n-\t\t\t\t ext4_da_get_block_prep);\n-\tif (ret) {\n-\t\tup_read(\u0026EXT4_I(inode)-\u003exattr_sem);\n-\t\tfolio_unlock(folio);\n-\t\tfolio_put(folio);\n-\t\text4_truncate_failed_write(inode);\n-\t\treturn ret;\n-\t}\n-\n-\tclear_buffer_new(folio_buffers(folio));\n-\tfolio_mark_dirty(folio);\n-\tfolio_mark_uptodate(folio);\n-\text4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);\n-\n-out:\n-\tup_read(\u0026EXT4_I(inode)-\u003exattr_sem);\n-\tif (folio) {\n-\t\tfolio_unlock(folio);\n-\t\tfolio_put(folio);\n-\t}\n-\treturn ret;\n+\t/* Inline data is deprecated: always convert to block format */\n+\treturn ext4_convert_inline_data(inode);\n }\n \n #ifdef INLINE_DIR_DEBUG\n@@ -1079,23 +690,6 @@ static int ext4_update_inline_dir(handle_t *handle, struct inode *dir,\n \treturn 0;\n }\n \n-static void ext4_restore_inline_data(handle_t *handle, struct inode *inode,\n-\t\t\t\t struct ext4_iloc *iloc,\n-\t\t\t\t void *buf, int inline_size)\n-{\n-\tint ret;\n-\n-\tret = ext4_create_inline_data(handle, inode, inline_size);\n-\tif (ret) {\n-\t\text4_msg(inode-\u003ei_sb, KERN_EMERG,\n-\t\t\t\"error restoring inline_data for inode -- potential data loss! (inode %llu, error %d)\",\n-\t\t\tinode-\u003ei_ino, ret);\n-\t\treturn;\n-\t}\n-\text4_write_inline_data(inode, iloc, buf, 0, inline_size);\n-\text4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);\n-}\n-\n static int ext4_convert_inline_data_nolock(handle_t *handle,\n \t\t\t\t\t struct inode *inode,\n \t\t\t\t\t struct ext4_iloc *iloc)\n@@ -1103,7 +697,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,\n \tint error;\n \tvoid *buf = NULL;\n \tstruct buffer_head *data_bh = NULL;\n-\tstruct ext4_map_blocks map;\n+\text4_fsblk_t pblk;\n \tint inline_size;\n \n \tinline_size = ext4_get_inline_size(inode);\n@@ -1129,25 +723,20 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,\n \t\t\tgoto out;\n \t}\n \n-\terror = ext4_destroy_inline_data_nolock(handle, inode);\n+\t/*\n+\t * Allocate a data block and write the inline data to it before\n+\t * destroying the inline data. This ensures that on failure we\n+\t * can simply free the allocated block without needing to restore\n+\t * the inline data.\n+\t */\n+\tpblk = ext4_new_meta_blocks(handle, inode, 0, 0, NULL, \u0026error);\n \tif (error)\n \t\tgoto out;\n \n-\tmap.m_lblk = 0;\n-\tmap.m_len = 1;\n-\tmap.m_flags = 0;\n-\terror = ext4_map_blocks(handle, inode, \u0026map, EXT4_GET_BLOCKS_CREATE);\n-\tif (error \u003c 0)\n-\t\tgoto out_restore;\n-\tif (!(map.m_flags \u0026 EXT4_MAP_MAPPED)) {\n-\t\terror = -EIO;\n-\t\tgoto out_restore;\n-\t}\n-\n-\tdata_bh = sb_getblk(inode-\u003ei_sb, map.m_pblk);\n+\tdata_bh = sb_getblk(inode-\u003ei_sb, pblk);\n \tif (!data_bh) {\n \t\terror = -ENOMEM;\n-\t\tgoto out_restore;\n+\t\tgoto out_free_block;\n \t}\n \n \tlock_buffer(data_bh);\n@@ -1155,8 +744,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,\n \t\t\t\t\t EXT4_JTR_NONE);\n \tif (error) {\n \t\tunlock_buffer(data_bh);\n-\t\terror = -EIO;\n-\t\tgoto out_restore;\n+\t\tgoto out_free_block;\n \t}\n \tmemset(data_bh-\u003eb_data, 0, inode-\u003ei_sb-\u003es_blocksize);\n \n@@ -1164,26 +752,38 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,\n \t\tmemcpy(data_bh-\u003eb_data, buf, inline_size);\n \t\tset_buffer_uptodate(data_bh);\n \t\tunlock_buffer(data_bh);\n-\t\terror = ext4_handle_dirty_metadata(handle,\n-\t\t\t\t\t\t inode, data_bh);\n+\t\terror = ext4_handle_dirty_metadata(handle, inode, data_bh);\n \t} else {\n \t\tunlock_buffer(data_bh);\n-\t\tinode-\u003ei_size = inode-\u003ei_sb-\u003es_blocksize;\n-\t\ti_size_write(inode, inode-\u003ei_sb-\u003es_blocksize);\n-\t\tEXT4_I(inode)-\u003ei_disksize = inode-\u003ei_sb-\u003es_blocksize;\n-\n \t\terror = ext4_init_dirblock(handle, inode, data_bh,\n \t\t\t le32_to_cpu(((struct ext4_dir_entry_2 *)buf)-\u003einode),\n \t\t\t buf + EXT4_INLINE_DOTDOT_SIZE,\n \t\t\t inline_size - EXT4_INLINE_DOTDOT_SIZE);\n-\t\tif (!error)\n-\t\t\terror = ext4_mark_inode_dirty(handle, inode);\n \t}\n+\tif (error)\n+\t\tgoto out_free_block;\n \n-out_restore:\n+\t/*\n+\t * Data is safely in the allocated block. Now destroy the inline\n+\t * data and populate the extent entry atomically under i_data_sem\n+\t * (inside ext4_destroy_inline_data_nolock). This ensures no\n+\t * concurrent reader sees an empty extent tree.\n+\t */\n+\terror = ext4_destroy_inline_data_nolock(handle, inode, pblk);\n \tif (error)\n-\t\text4_restore_inline_data(handle, inode, iloc, buf, inline_size);\n+\t\tgoto out_free_block;\n \n+\tif (S_ISDIR(inode-\u003ei_mode)) {\n+\t\tinode-\u003ei_size = inode-\u003ei_sb-\u003es_blocksize;\n+\t\ti_size_write(inode, inode-\u003ei_sb-\u003es_blocksize);\n+\t\tEXT4_I(inode)-\u003ei_disksize = inode-\u003ei_sb-\u003es_blocksize;\n+\t}\n+\n+\terror = ext4_mark_inode_dirty(handle, inode);\n+\tgoto out;\n+\n+out_free_block:\n+\text4_free_blocks(handle, inode, NULL, pblk, 1, 0);\n out:\n \tbrelse(data_bh);\n \tkfree(buf);\n@@ -1821,7 +1421,7 @@ int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)\n \tint ret, no_expand;\n \n \text4_write_lock_xattr(inode, \u0026no_expand);\n-\tret = ext4_destroy_inline_data_nolock(handle, inode);\n+\tret = ext4_destroy_inline_data_nolock(handle, inode, 0);\n \text4_write_unlock_xattr(inode, \u0026no_expand);\n \n \treturn ret;\n@@ -1980,18 +1580,6 @@ int ext4_convert_inline_data(struct inode *inode)\n \tif (!ext4_has_inline_data(inode)) {\n \t\text4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);\n \t\treturn 0;\n-\t} else if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {\n-\t\t/*\n-\t\t * Inode has inline data but EXT4_STATE_MAY_INLINE_DATA is\n-\t\t * cleared. This means we are in the middle of moving of\n-\t\t * inline data to delay allocated block. Just force writeout\n-\t\t * here to finish conversion.\n-\t\t */\n-\t\terror = filemap_flush(inode-\u003ei_mapping);\n-\t\tif (error)\n-\t\t\treturn error;\n-\t\tif (!ext4_has_inline_data(inode))\n-\t\t\treturn 0;\n \t}\n \n \tneeded_blocks = ext4_chunk_trans_extent(inode, 1);\ndiff --git a/fs/ext4/inode.c b/fs/ext4/inode.c\nindex ad14dd58a003b3..2256fb3826a9db 100644\n--- a/fs/ext4/inode.c\n+++ b/fs/ext4/inode.c\n@@ -1300,8 +1300,6 @@ static int ext4_write_begin(const struct kiocb *iocb,\n \tif (unlikely(ret))\n \t\treturn ret;\n \n-\t*fsdata = (void *)((unsigned long)*fsdata \u0026 ~EXT4_WRITE_DATA_INLINE);\n-\n \ttrace_ext4_write_begin(inode, pos, len);\n \t/*\n \t * Reserve one block more for addition to orphan list in case\n@@ -1312,14 +1310,9 @@ static int ext4_write_begin(const struct kiocb *iocb,\n \tindex = pos \u003e\u003e PAGE_SHIFT;\n \n \tif (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {\n-\t\tret = ext4_try_to_write_inline_data(mapping, inode, pos, len,\n-\t\t\t\t\t\t foliop);\n+\t\tret = ext4_convert_inline_data(inode);\n \t\tif (ret \u003c 0)\n \t\t\treturn ret;\n-\t\tif (ret == 1) {\n-\t\t\t*fsdata = (void *)((unsigned long)*fsdata | EXT4_WRITE_DATA_INLINE);\n-\t\t\treturn 0;\n-\t\t}\n \t}\n \n \t/*\n@@ -1452,10 +1445,6 @@ static int ext4_write_end(const struct kiocb *iocb,\n \n \ttrace_ext4_write_end(inode, pos, len, copied);\n \n-\tif ((unsigned long)fsdata \u0026 EXT4_WRITE_DATA_INLINE)\n-\t\treturn ext4_write_inline_data_end(inode, pos, len, copied,\n-\t\t\t\t\t\t folio);\n-\n \tcopied = block_write_end(pos, len, copied, folio);\n \t/*\n \t * it's important to update i_size while still holding folio lock:\n@@ -1561,10 +1550,6 @@ static int ext4_journalled_write_end(const struct kiocb *iocb,\n \n \tBUG_ON(!ext4_handle_valid(handle));\n \n-\tif ((unsigned long)fsdata \u0026 EXT4_WRITE_DATA_INLINE)\n-\t\treturn ext4_write_inline_data_end(inode, pos, len, copied,\n-\t\t\t\t\t\t folio);\n-\n \tif (unlikely(copied \u003c len) \u0026\u0026 !folio_test_uptodate(folio)) {\n \t\tcopied = 0;\n \t\text4_journalled_zero_new_buffers(handle, inode, folio,\n@@ -3173,10 +3158,6 @@ static int ext4_da_write_begin(const struct kiocb *iocb,\n \t\t\t\t\t\t foliop, true);\n \t\tif (ret \u003c 0)\n \t\t\treturn ret;\n-\t\tif (ret == 1) {\n-\t\t\t*fsdata = (void *)((unsigned long)*fsdata | EXT4_WRITE_DATA_INLINE);\n-\t\t\treturn 0;\n-\t\t}\n \t}\n \n retry:\n@@ -3313,10 +3294,6 @@ static int ext4_da_write_end(const struct kiocb *iocb,\n \n \ttrace_ext4_da_write_end(inode, pos, len, copied);\n \n-\tif (write_mode \u0026 EXT4_WRITE_DATA_INLINE)\n-\t\treturn ext4_write_inline_data_end(inode, pos, len, copied,\n-\t\t\t\t\t\t folio);\n-\n \tif (unlikely(copied \u003c len) \u0026\u0026 !folio_test_uptodate(folio))\n \t\tcopied = 0;\n \ndiff --git a/fs/ext4/super.c b/fs/ext4/super.c\nindex 6c18b5adffca32..9913e30b704008 100644\n--- a/fs/ext4/super.c\n+++ b/fs/ext4/super.c\n@@ -3145,6 +3145,12 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,\n \t\text4_msg(sb, KERN_WARNING,\n \t\t\t \"warning: checktime reached, \"\n \t\t\t \"running e2fsck is recommended\");\n+\tif (ext4_has_feature_inline_data(sb))\n+\t\text4_msg(sb, KERN_WARNING,\n+\t\t\t \"warning: inline_data feature is deprecated and \"\n+\t\t\t \"will be removed in a future kernel release. \"\n+\t\t\t \"Use 'tune2fs -O ^inline_data' to convert.\");\n+\n \tif (!sbi-\u003es_journal)\n \t\tes-\u003es_state \u0026= cpu_to_le16(~EXT4_VALID_FS);\n \tif (!(__s16) le16_to_cpu(es-\u003es_max_mnt_count))\n"
} |
| 2/1 | 2026/07/28 00:13 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"EXT4_FS"
],
"FocusSymbols": [
"ext4_convert_inline_data",
"ext4_generic_write_inline_data",
"ext4_destroy_inline_data"
],
"Reasoning": "The patch deprecates the inline_data feature for regular files in ext4, forcing conversion to block-based storage on write. This modifies core ext4 write paths and inline data conversion logic, which should be fuzzed to ensure no regressions or data corruption issues.",
"WorthFuzzing": true
}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 7a530d0f5407f0fddb942be14dc7b3cc904c5413
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Jul 28 00:13:47 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/filesystems/ext4/inlinedata.rst b/Documentation/filesystems/ext4/inlinedata.rst
index a728af0d2fd0c5..8dc1b6d75388d7 100644
--- a/Documentation/filesystems/ext4/inlinedata.rst
+++ b/Documentation/filesystems/ext4/inlinedata.rst
@@ -3,6 +3,14 @@
Inline Data
-----------
+.. warning::
+
+ The inline data feature is deprecated and will be removed in a future
+ kernel release. New regular file inodes no longer store data inline,
+ and writes to existing inline data inodes trigger automatic conversion
+ to block-based storage. Use ``tune2fs -O ^inline_data`` to convert
+ existing filesystems.
+
The inline data feature was designed to handle the case that a file's
data is so tiny that it readily fits inside the inode, which
(theoretically) reduces disk block consumption and reduces seeks. If the
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 21a951f1063678..832bc1f3b60027 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3148,7 +3148,6 @@ int do_journal_get_write_access(handle_t *handle, struct inode *inode,
struct buffer_head *bh);
void ext4_set_inode_mapping_order(struct inode *inode);
#define FALL_BACK_TO_NONDELALLOC 1
-#define EXT4_WRITE_DATA_INLINE 2
typedef enum {
EXT4_IGET_NORMAL = 0,
@@ -3759,12 +3758,6 @@ extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
extern void ext4_update_final_de(void *de_buf, int old_size, int new_size);
int ext4_readpage_inline(struct inode *inode, struct folio *folio);
-extern int ext4_try_to_write_inline_data(struct address_space *mapping,
- struct inode *inode,
- loff_t pos, unsigned len,
- struct folio **foliop);
-int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
- unsigned copied, struct folio *folio);
extern int ext4_generic_write_inline_data(struct address_space *mapping,
struct inode *inode,
loff_t pos, unsigned len,
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index a40cb27f8116cb..278f0ab8c996e4 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1305,8 +1305,8 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,
ei->i_extra_isize = sbi->s_want_extra_isize;
ei->i_inline_off = 0;
- if (ext4_has_feature_inline_data(sb) &&
- (!(ei->i_flags & (EXT4_DAX_FL|EXT4_EA_INODE_FL)) || S_ISDIR(mode)))
+ if (ext4_has_feature_inline_data(sb) && S_ISDIR(mode) &&
+ !(ei->i_flags & EXT4_DAX_FL))
ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
ret = inode;
err = dquot_alloc_inode(inode);
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index ceee69a66482bc..e0b80273e322d8 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -12,6 +12,7 @@
#include "ext4_jbd2.h"
#include "ext4.h"
+#include "ext4_extents.h"
#include "xattr.h"
#include "truncate.h"
@@ -20,10 +21,6 @@
#define EXT4_INLINE_DOTDOT_OFFSET 2
#define EXT4_INLINE_DOTDOT_SIZE 4
-
-static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
- struct inode *inode);
-
static int ext4_get_inline_size(struct inode *inode)
{
if (EXT4_I(inode)->i_inline_off)
@@ -218,51 +215,6 @@ static int ext4_read_inline_data(struct inode *inode, void *buffer,
return cp_len;
}
-/*
- * write the buffer to the inline inode.
- * If 'create' is set, we don't need to do the extra copy in the xattr
- * value since it is already handled by ext4_xattr_ibody_set.
- * That saves us one memcpy.
- */
-static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
- void *buffer, loff_t pos, unsigned int len)
-{
- struct ext4_xattr_entry *entry;
- struct ext4_xattr_ibody_header *header;
- struct ext4_inode *raw_inode;
- int cp_len = 0;
-
- if (unlikely(ext4_emergency_state(inode->i_sb)))
- return;
-
- BUG_ON(!EXT4_I(inode)->i_inline_off);
- BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);
-
- raw_inode = ext4_raw_inode(iloc);
- buffer += pos;
-
- if (pos < EXT4_MIN_INLINE_DATA_SIZE) {
- cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ?
- EXT4_MIN_INLINE_DATA_SIZE - pos : len;
- memcpy((void *)raw_inode->i_block + pos, buffer, cp_len);
-
- len -= cp_len;
- buffer += cp_len;
- pos += cp_len;
- }
-
- if (!len)
- return;
-
- pos -= EXT4_MIN_INLINE_DATA_SIZE;
- header = IHDR(inode, raw_inode);
- entry = (struct ext4_xattr_entry *)((void *)raw_inode +
- EXT4_I(inode)->i_inline_off);
-
- memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos,
- buffer, len);
-}
-
static int ext4_create_inline_data(handle_t *handle,
struct inode *inode, unsigned len)
{
@@ -433,7 +385,8 @@ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
}
static int ext4_destroy_inline_data_nolock(handle_t *handle,
- struct inode *inode)
+ struct inode *inode,
+ ext4_fsblk_t pblk)
{
struct ext4_inode_info *ei = EXT4_I(inode);
struct ext4_xattr_ibody_find is = {
@@ -481,7 +434,21 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) {
ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);
ext4_ext_tree_init(handle, inode);
+ if (pblk) {
+ struct ext4_extent_header *eh;
+ struct ext4_extent *ex;
+
+ eh = ext_inode_hdr(inode);
+ ex = EXT_FIRST_EXTENT(eh);
+ ex->ee_block = cpu_to_le32(0);
+ ex->ee_len = cpu_to_le16(1);
+ ext4_ext_store_pblock(ex, pblk);
+ eh->eh_entries = cpu_to_le16(1);
+ }
}
+ } else if (pblk) {
+ /* indirect mapping: set i_data[0] directly */
+ EXT4_I(inode)->i_data[0] = cpu_to_le32(pblk);
}
ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
@@ -568,122 +535,6 @@ int ext4_readpage_inline(struct inode *inode, struct folio *folio)
return ret >= 0 ? 0 : ret;
}
-static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
- struct inode *inode)
-{
- int ret, needed_blocks, no_expand;
- handle_t *handle = NULL;
- int retries = 0, sem_held = 0;
- struct folio *folio = NULL;
- unsigned from, to;
- struct ext4_iloc iloc;
-
- if (!ext4_has_inline_data(inode)) {
- /*
- * clear the flag so that no new write
- * will trap here again.
- */
- ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
- return 0;
- }
-
- needed_blocks = ext4_chunk_trans_extent(inode, 1);
-
- ret = ext4_get_inode_loc(inode, &iloc);
- if (ret)
- return ret;
-
-retry:
- handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);
- if (IS_ERR(handle)) {
- ret = PTR_ERR(handle);
- handle = NULL;
- goto out;
- }
-
- /* We cannot recurse into the filesystem as the transaction is already
- * started */
- folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
- mapping_gfp_mask(mapping));
- if (IS_ERR(folio)) {
- ret = PTR_ERR(folio);
- goto out_nofolio;
- }
-
- ext4_write_lock_xattr(inode, &no_expand);
- sem_held = 1;
- /* If some one has already done this for us, just exit. */
- if (!ext4_has_inline_data(inode)) {
- ret = 0;
- goto out;
- }
-
- from = 0;
- to = ext4_get_inline_size(inode);
- if (!folio_test_uptodate(folio)) {
- ret = ext4_read_inline_folio(inode, folio);
- if (ret < 0)
- goto out;
- }
-
- ext4_fc_track_inode(handle, inode);
- ret = ext4_destroy_inline_data_nolock(handle, inode);
- if (ret)
- goto out;
-
- if (ext4_should_dioread_nolock(inode)) {
- ret = ext4_block_write_begin(handle, folio, from, to,
- ext4_get_block_unwritten);
- } else
- ret = ext4_block_write_begin(handle, folio, from, to,
- ext4_get_block);
- clear_buffer_new(folio_buffers(folio));
-
- if (!ret && ext4_should_journal_data(inode)) {
- ret = ext4_walk_page_buffers(handle, inode,
- folio_buffers(folio), from, to,
- NULL, do_journal_get_write_access);
- }
-
- if (ret) {
- folio_unlock(folio);
- folio_put(folio);
- folio = NULL;
- ext4_orphan_add(handle, inode);
- ext4_write_unlock_xattr(inode, &no_expand);
- sem_held = 0;
- ext4_journal_stop(handle);
- handle = NULL;
- ext4_truncate_failed_write(inode);
- /*
- * If truncate failed early the inode might
- * still be on the orphan list; we need to
- * make sure the inode is removed from the
- * orphan list in that case.
- */
- if (inode->i_nlink)
- ext4_orphan_del(NULL, inode);
- }
-
- if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
- goto retry;
-
- if (folio)
- block_commit_write(folio, from, to);
-out:
- if (folio) {
- folio_unlock(folio);
- folio_put(folio);
- }
-out_nofolio:
- if (sem_held)
- ext4_write_unlock_xattr(inode, &no_expand);
- if (handle)
- ext4_journal_stop(handle);
- brelse(iloc.bh);
- return ret;
-}
-
/*
* Prepare the write for the inline data.
* If the data can be written into the inode, we just read
@@ -698,248 +549,8 @@ int ext4_generic_write_inline_data(struct address_space *mapping,
struct folio **foliop,
bool da)
{
- int ret;
- handle_t *handle;
- struct folio *folio;
- struct ext4_iloc iloc;
- int retries = 0;
-
- ret = ext4_get_inode_loc(inode, &iloc);
- if (ret)
- return ret;
-
-retry_journal:
- handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
- if (IS_ERR(handle)) {
- ret = PTR_ERR(handle);
- goto out_release_bh;
- }
-
- ret = ext4_prepare_inline_data(handle, inode, pos + len);
- if (ret && ret != -ENOSPC)
- goto out_stop_journal;
-
- if (ret == -ENOSPC) {
- ext4_journal_stop(handle);
- if (!da) {
- brelse(iloc.bh);
- /* Retry inside */
- return ext4_convert_inline_data_to_extent(mapping, inode);
- }
-
- ret = ext4_da_convert_inline_data_to_extent(mapping, inode);
- if (ret == -ENOSPC &&
- ext4_should_retry_alloc(inode->i_sb, &retries))
- goto retry_journal;
- goto out_release_bh;
- }
-
- folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
- mapping_gfp_mask(mapping));
- if (IS_ERR(folio)) {
- ret = PTR_ERR(folio);
- goto out_stop_journal;
- }
-
- down_read(&EXT4_I(inode)->xattr_sem);
- /* Someone else had converted it to extent */
- if (!ext4_has_inline_data(inode)) {
- ret = 0;
- goto out_release_folio;
- }
-
- if (!folio_test_uptodate(folio)) {
- ret = ext4_read_inline_folio(inode, folio);
- if (ret < 0)
- goto out_release_folio;
- }
-
- ret = ext4_journal_get_write_access(handle, inode->i_sb, iloc.bh, EXT4_JTR_NONE);
- if (ret)
- goto out_release_folio;
- *foliop = folio;
- up_read(&EXT4_I(inode)->xattr_sem);
- brelse(iloc.bh);
- return 1;
-
-out_release_folio:
- up_read(&EXT4_I(inode)->xattr_sem);
- folio_unlock(folio);
- folio_put(folio);
-out_stop_journal:
- ext4_journal_stop(handle);
-out_release_bh:
- brelse(iloc.bh);
- return ret;
-}
-
-/*
- * Try to write data in the inode.
- * If the inode has inline data, check whether the new write can be
- * in the inode also. If not, create the page the handle, move the data
- * to the page make it update and let the later codes create extent for it.
- */
-int ext4_try_to_write_inline_data(struct address_space *mapping,
- struct inode *inode,
- loff_t pos, unsigned len,
- struct folio **foliop)
-{
- if (pos + len > ext4_get_max_inline_size(inode))
- return ext4_convert_inline_data_to_extent(mapping, inode);
- return ext4_generic_write_inline_data(mapping, inode, pos, len,
- foliop, false);
-}
-
-int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
- unsigned copied, struct folio *folio)
-{
- handle_t *handle = ext4_journal_current_handle();
- int no_expand;
- void *kaddr;
- struct ext4_iloc iloc;
- int ret = 0, ret2;
-
- if (unlikely(copied < len) && !folio_test_uptodate(folio))
- copied = 0;
-
- if (likely(copied)) {
- ret = ext4_get_inode_loc(inode, &iloc);
- if (ret) {
- folio_unlock(folio);
- folio_put(folio);
- ext4_std_error(inode->i_sb, ret);
- goto out;
- }
- ext4_write_lock_xattr(inode, &no_expand);
- /*
- * We could have raced with ext4_page_mkwrite() converting
- * the inode and clearing the inline data flag, so we just
- * release resources and retry the whole write.
- */
- if (unlikely(!ext4_has_inline_data(inode))) {
- ext4_write_unlock_xattr(inode, &no_expand);
- brelse(iloc.bh);
- folio_unlock(folio);
- folio_put(folio);
- ext4_journal_stop(handle);
- return 0;
- }
-
- /*
- * ei->i_inline_off may have changed since
- * ext4_write_begin() called
- * ext4_try_to_write_inline_data()
- */
- (void) ext4_find_inline_data_nolock(inode);
-
- kaddr = kmap_local_folio(folio, 0);
- ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
- kunmap_local(kaddr);
- folio_mark_uptodate(folio);
- /* clear dirty flag so that writepages wouldn't work for us. */
- folio_clear_dirty(folio);
-
- ext4_write_unlock_xattr(inode, &no_expand);
- brelse(iloc.bh);
-
- /*
- * It's important to update i_size while still holding folio
- * lock: page writeout could otherwise come in and zero
- * beyond i_size.
- */
- ext4_update_inode_size(inode, pos + copied);
- }
- folio_unlock(folio);
- folio_put(folio);
-
- /*
- * 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 (likely(copied))
- mark_inode_dirty(inode);
-out:
- /*
- * If we didn't copy as much data as expected, we need to trim back
- * size of xattr containing inline data.
- */
- if (pos + len > inode->i_size && ext4_can_truncate(inode))
- ext4_orphan_add(handle, inode);
-
- ret2 = ext4_journal_stop(handle);
- if (!ret)
- ret = ret2;
- if (pos + len > inode->i_size) {
- ext4_truncate_failed_write(inode);
- /*
- * If truncate failed early the inode might still be
- * on the orphan list; we need to make sure the inode
- * is removed from the orphan list in that case.
- */
- if (inode->i_nlink)
- ext4_orphan_del(NULL, inode);
- }
- return ret ? ret : copied;
-}
-
-/*
- * Try to make the page cache and handle ready for the inline data case.
- * We can call this function in 2 cases:
- * 1. The inode is created and the first write exceeds inline size. We can
- * clear the inode state safely.
- * 2. The inode has inline data, then we need to read the data, make it
- * update and dirty so that ext4_da_writepages can handle it. We don't
- * need to start the journal since the file's metadata isn't changed now.
- */
-static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
- struct inode *inode)
-{
- int ret = 0, inline_size;
- struct folio *folio;
-
- folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN,
- mapping_gfp_mask(mapping));
- if (IS_ERR(folio))
- return PTR_ERR(folio);
-
- down_read(&EXT4_I(inode)->xattr_sem);
- if (!ext4_has_inline_data(inode)) {
- ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
- goto out;
- }
-
- inline_size = ext4_get_inline_size(inode);
-
- if (!folio_test_uptodate(folio)) {
- ret = ext4_read_inline_folio(inode, folio);
- if (ret < 0)
- goto out;
- }
-
- ret = ext4_block_write_begin(NULL, folio, 0, inline_size,
- ext4_da_get_block_prep);
- if (ret) {
- up_read(&EXT4_I(inode)->xattr_sem);
- folio_unlock(folio);
- folio_put(folio);
- ext4_truncate_failed_write(inode);
- return ret;
- }
-
- clear_buffer_new(folio_buffers(folio));
- folio_mark_dirty(folio);
- folio_mark_uptodate(folio);
- ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
-
-out:
- up_read(&EXT4_I(inode)->xattr_sem);
- if (folio) {
- folio_unlock(folio);
- folio_put(folio);
- }
- return ret;
+ /* Inline data is deprecated: always convert to block format */
+ return ext4_convert_inline_data(inode);
}
#ifdef INLINE_DIR_DEBUG
@@ -1079,23 +690,6 @@ static int ext4_update_inline_dir(handle_t *handle, struct inode *dir,
return 0;
}
-static void ext4_restore_inline_data(handle_t *handle, struct inode *inode,
- struct ext4_iloc *iloc,
- void *buf, int inline_size)
-{
- int ret;
-
- ret = ext4_create_inline_data(handle, inode, inline_size);
- if (ret) {
- ext4_msg(inode->i_sb, KERN_EMERG,
- "error restoring inline_data for inode -- potential data loss! (inode %llu, error %d)",
- inode->i_ino, ret);
- return;
- }
- ext4_write_inline_data(inode, iloc, buf, 0, inline_size);
- ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
-}
-
static int ext4_convert_inline_data_nolock(handle_t *handle,
struct inode *inode,
struct ext4_iloc *iloc)
@@ -1103,7 +697,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
int error;
void *buf = NULL;
struct buffer_head *data_bh = NULL;
- struct ext4_map_blocks map;
+ ext4_fsblk_t pblk;
int inline_size;
inline_size = ext4_get_inline_size(inode);
@@ -1129,25 +723,20 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
goto out;
}
- error = ext4_destroy_inline_data_nolock(handle, inode);
+ /*
+ * Allocate a data block and write the inline data to it before
+ * destroying the inline data. This ensures that on failure we
+ * can simply free the allocated block without needing to restore
+ * the inline data.
+ */
+ pblk = ext4_new_meta_blocks(handle, inode, 0, 0, NULL, &error);
if (error)
goto out;
- map.m_lblk = 0;
- map.m_len = 1;
- map.m_flags = 0;
- error = ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_CREATE);
- if (error < 0)
- goto out_restore;
- if (!(map.m_flags & EXT4_MAP_MAPPED)) {
- error = -EIO;
- goto out_restore;
- }
-
- data_bh = sb_getblk(inode->i_sb, map.m_pblk);
+ data_bh = sb_getblk(inode->i_sb, pblk);
if (!data_bh) {
error = -ENOMEM;
- goto out_restore;
+ goto out_free_block;
}
lock_buffer(data_bh);
@@ -1155,8 +744,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
EXT4_JTR_NONE);
if (error) {
unlock_buffer(data_bh);
- error = -EIO;
- goto out_restore;
+ goto out_free_block;
}
memset(data_bh->b_data, 0, inode->i_sb->s_blocksize);
@@ -1164,26 +752,38 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
memcpy(data_bh->b_data, buf, inline_size);
set_buffer_uptodate(data_bh);
unlock_buffer(data_bh);
- error = ext4_handle_dirty_metadata(handle,
- inode, data_bh);
+ error = ext4_handle_dirty_metadata(handle, inode, data_bh);
} else {
unlock_buffer(data_bh);
- inode->i_size = inode->i_sb->s_blocksize;
- i_size_write(inode, inode->i_sb->s_blocksize);
- EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-
error = ext4_init_dirblock(handle, inode, data_bh,
le32_to_cpu(((struct ext4_dir_entry_2 *)buf)->inode),
buf + EXT4_INLINE_DOTDOT_SIZE,
inline_size - EXT4_INLINE_DOTDOT_SIZE);
- if (!error)
- error = ext4_mark_inode_dirty(handle, inode);
}
+ if (error)
+ goto out_free_block;
-out_restore:
+ /*
+ * Data is safely in the allocated block. Now destroy the inline
+ * data and populate the extent entry atomically under i_data_sem
+ * (inside ext4_destroy_inline_data_nolock). This ensures no
+ * concurrent reader sees an empty extent tree.
+ */
+ error = ext4_destroy_inline_data_nolock(handle, inode, pblk);
if (error)
- ext4_restore_inline_data(handle, inode, iloc, buf, inline_size);
+ goto out_free_block;
+ if (S_ISDIR(inode->i_mode)) {
+ inode->i_size = inode->i_sb->s_blocksize;
+ i_size_write(inode, inode->i_sb->s_blocksize);
+ EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;
+ }
+
+ error = ext4_mark_inode_dirty(handle, inode);
+ goto out;
+
+out_free_block:
+ ext4_free_blocks(handle, inode, NULL, pblk, 1, 0);
out:
brelse(data_bh);
kfree(buf);
@@ -1821,7 +1421,7 @@ int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
int ret, no_expand;
ext4_write_lock_xattr(inode, &no_expand);
- ret = ext4_destroy_inline_data_nolock(handle, inode);
+ ret = ext4_destroy_inline_data_nolock(handle, inode, 0);
ext4_write_unlock_xattr(inode, &no_expand);
return ret;
@@ -1980,18 +1580,6 @@ int ext4_convert_inline_data(struct inode *inode)
if (!ext4_has_inline_data(inode)) {
ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
return 0;
- } else if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
- /*
- * Inode has inline data but EXT4_STATE_MAY_INLINE_DATA is
- * cleared. This means we are in the middle of moving of
- * inline data to delay allocated block. Just force writeout
- * here to finish conversion.
- */
- error = filemap_flush(inode->i_mapping);
- if (error)
- return error;
- if (!ext4_has_inline_data(inode))
- return 0;
}
needed_blocks = ext4_chunk_trans_extent(inode, 1);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index ad14dd58a003b3..2256fb3826a9db 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1300,8 +1300,6 @@ static int ext4_write_begin(const struct kiocb *iocb,
if (unlikely(ret))
return ret;
- *fsdata = (void *)((unsigned long)*fsdata & ~EXT4_WRITE_DATA_INLINE);
-
trace_ext4_write_begin(inode, pos, len);
/*
* Reserve one block more for addition to orphan list in case
@@ -1312,14 +1310,9 @@ static int ext4_write_begin(const struct kiocb *iocb,
index = pos >> PAGE_SHIFT;
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
- ret = ext4_try_to_write_inline_data(mapping, inode, pos, len,
- foliop);
+ ret = ext4_convert_inline_data(inode);
if (ret < 0)
return ret;
- if (ret == 1) {
- *fsdata = (void *)((unsigned long)*fsdata | EXT4_WRITE_DATA_INLINE);
- return 0;
- }
}
/*
@@ -1452,10 +1445,6 @@ static int ext4_write_end(const struct kiocb *iocb,
trace_ext4_write_end(inode, pos, len, copied);
- if ((unsigned long)fsdata & EXT4_WRITE_DATA_INLINE)
- return ext4_write_inline_data_end(inode, pos, len, copied,
- folio);
-
copied = block_write_end(pos, len, copied, folio);
/*
* it's important to update i_size while still holding folio lock:
@@ -1561,10 +1550,6 @@ static int ext4_journalled_write_end(const struct kiocb *iocb,
BUG_ON(!ext4_handle_valid(handle));
- if ((unsigned long)fsdata & EXT4_WRITE_DATA_INLINE)
- return ext4_write_inline_data_end(inode, pos, len, copied,
- folio);
-
if (unlikely(copied < len) && !folio_test_uptodate(folio)) {
copied = 0;
ext4_journalled_zero_new_buffers(handle, inode, folio,
@@ -3173,10 +3158,6 @@ static int ext4_da_write_begin(const struct kiocb *iocb,
foliop, true);
if (ret < 0)
return ret;
- if (ret == 1) {
- *fsdata = (void *)((unsigned long)*fsdata | EXT4_WRITE_DATA_INLINE);
- return 0;
- }
}
retry:
@@ -3313,10 +3294,6 @@ static int ext4_da_write_end(const struct kiocb *iocb,
trace_ext4_da_write_end(inode, pos, len, copied);
- if (write_mode & EXT4_WRITE_DATA_INLINE)
- return ext4_write_inline_data_end(inode, pos, len, copied,
- folio);
-
if (unlikely(copied < len) && !folio_test_uptodate(folio))
copied = 0;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 6c18b5adffca32..9913e30b704008 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3145,6 +3145,12 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
ext4_msg(sb, KERN_WARNING,
"warning: checktime reached, "
"running e2fsck is recommended");
+ if (ext4_has_feature_inline_data(sb))
+ ext4_msg(sb, KERN_WARNING,
+ "warning: inline_data feature is deprecated and "
+ "will be removed in a future kernel release. "
+ "Use 'tune2fs -O ^inline_data' to convert.");
+
if (!sbi->s_journal)
es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
|
| 3/2 | 2026/07/28 00:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11515 output: 33 thoughts: 692 Thoughts: **Analyzing the Ext4 Inline Data Deprecation Patch** Okay, so I've got this patch that's effectively nuking the `inline_data` feature in ext4. It's not just a cleanup; it's a functional change, a core filesystem component. The idea is to stop *writing* new inline data to regular files and convert any existing inline data to the standard block format. This immediately screams "fuzzing target" to me, especially given the potential for data corruption or unexpected behavior during these conversions and write operations. I need to nail down the key functions affected. Let's see... the patch touches `ext4_convert_inline_data_nolock`, `ext4_destroy_inline_data_nolock`, `ext4_generic_write_inline_data`, `ext4_convert_inline_data`, `ext4_write_begin`, `ext4_write_end`, `ext4_journalled_write_end`, `ext4_da_write_begin`, `ext4_da_write_end`, and `__ext4_new_inode`. A quick glance at the function signatures reveals something interesting: `ext4_convert_inline_data_nolock` is *static*, but it's crucial because it's called by the non-static `ext4_convert_inline_data` and `ext4_update_inline_dir`. That's a good starting point. `ext4_generic_write_inline_data` and `ext4_destroy_inline_data` are non-static as well. The `ext4_write_begin` and `ext4_da_write_begin` variants are static, but part of the `ext4_aops` and `ext4_da_aops` so they are still targets. Now, my focus narrows: I want a deeper look at `ext4_convert_inline_data`, `ext4_generic_write_inline_data` and `ext4_destroy_inline_data`. These are the key functions handling the conversion and potential writing or removal. Before diving into a detailed code review, I should use `default_api:grepper` to see where these functions are exported and used. That should give me a better understanding of the call graphs and potential entry points for fuzzing. |
| 4/2 | 2026/07/28 00:13 | tool | grepper |
0mArgs:{
"Expression": "ext4_convert_inline_data",
"PathPrefix": "fs/ext4/"
}Results: {
"Output": "fs/ext4/crypto.c=132=static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,\n--\nfs/ext4/crypto.c-152-\nfs/ext4/crypto.c:153:\tres = ext4_convert_inline_data(inode);\nfs/ext4/crypto.c-154-\tif (res)\n--\nfs/ext4/ext4.h=3798=extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline);\nfs/ext4/ext4.h-3799-\nfs/ext4/ext4.h:3800:extern int ext4_convert_inline_data(struct inode *inode);\nfs/ext4/ext4.h-3801-\n--\nfs/ext4/extents.c=4879=long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)\n--\nfs/ext4/extents.c-4908-\tinode_lock(inode);\nfs/ext4/extents.c:4909:\tret = ext4_convert_inline_data(inode);\nfs/ext4/extents.c-4910-\tif (ret)\n--\nfs/ext4/inline.c=546=int ext4_generic_write_inline_data(struct address_space *mapping,\n--\nfs/ext4/inline.c-552-\t/* Inline data is deprecated: always convert to block format */\nfs/ext4/inline.c:553:\treturn ext4_convert_inline_data(inode);\nfs/ext4/inline.c-554-}\n--\nfs/ext4/inline.c=671=static int ext4_update_inline_dir(handle_t *handle, struct inode *dir,\n--\nfs/ext4/inline.c-692-\nfs/ext4/inline.c:693:static int ext4_convert_inline_data_nolock(handle_t *handle,\nfs/ext4/inline.c-694-\t\t\t\t\t struct inode *inode,\n--\nfs/ext4/inline.c=798=int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,\n--\nfs/ext4/inline.c-850-\t */\nfs/ext4/inline.c:851:\tret = ext4_convert_inline_data_nolock(handle, dir, \u0026iloc);\nfs/ext4/inline.c-852-\n--\nfs/ext4/inline.c=1462=int ext4_inline_data_truncate(struct inode *inode, int *has_inline)\n--\nfs/ext4/inline.c-1573-\nfs/ext4/inline.c:1574:int ext4_convert_inline_data(struct inode *inode)\nfs/ext4/inline.c-1575-{\n--\nfs/ext4/inline.c-1599-\tif (ext4_has_inline_data(inode))\nfs/ext4/inline.c:1600:\t\terror = ext4_convert_inline_data_nolock(handle, inode, \u0026iloc);\nfs/ext4/inline.c-1601-\text4_write_unlock_xattr(inode, \u0026no_expand);\n--\nfs/ext4/inode.c=1286=static int ext4_write_begin(const struct kiocb *iocb,\n--\nfs/ext4/inode.c-1312-\tif (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {\nfs/ext4/inode.c:1313:\t\tret = ext4_convert_inline_data(inode);\nfs/ext4/inode.c-1314-\t\tif (ret \u003c 0)\n--\nfs/ext4/inode.c=5998=int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry,\n--\nfs/ext4/inode.c-6095-\t\t attr-\u003eia_size \u003e EXT4_I(inode)-\u003ei_inline_size) {\nfs/ext4/inode.c:6096:\t\t\terror = ext4_convert_inline_data(inode);\nfs/ext4/inode.c-6097-\t\t\tif (error)\n--\nfs/ext4/inode.c=6861=vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)\n--\nfs/ext4/inode.c-6882-\nfs/ext4/inode.c:6883:\terr = ext4_convert_inline_data(inode);\nfs/ext4/inode.c-6884-\tif (err)\n--\nfs/ext4/verity.c=102=static int ext4_begin_enable_verity(struct file *filp)\n--\nfs/ext4/verity.c-128-\nfs/ext4/verity.c:129:\terr = ext4_convert_inline_data(inode);\nfs/ext4/verity.c-130-\tif (err)\n"
} |
| 5/2 | 2026/07/28 00:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14070 output: 29 thoughts: 156 Thoughts: **My Initial Assessment of the Ext4 Inline Data Deprecation** Okay, so this patch is targeting the deprecation of `inline_data` for standard files in ext4. My initial thoughts are that it's a relatively straightforward change, but the implications need a close look. The core of it seems to involve replacing the inline data handling with a standard block allocation and write process within `ext4_convert_inline_data_nolock`. That makes sense; moving data out of the inode and into regular blocks is the expected approach for deprecation. Then, `ext4_destroy_inline_data_nolock` is updated to handle the cleanup using a physical block (`pblk`) and either populate the extent tree or an indirect block directly. That's a key change, and it aligns with the data now residing in standard blocks. The three functions, `ext4_convert_inline_data`, `ext4_generic_write_inline_data`, and `ext4_destroy_inline_data` are strong candidates for using `FocusSymbols`. They are the main touchpoints of this deprecation, so they're the logical places to start if I want to thoroughly review this. Now, I need to check for any special configurations. We all know `CONFIG_EXT4_FS` enables ext4, so that's the base. But is there a separate CONFIG option specifically for *inline* data? If there is, it will be critical for assessing the impact and potential compile-time effects of this change. I need to track down any config dependencies to be sure. |
| 6/2 | 2026/07/28 00:14 | tool | grepper |
0mArgs:{
"Expression": "CONFIG_EXT4",
"PathPrefix": "fs/ext4/"
}Results: {
"Output": "fs/ext4/.kunitconfig=1=CONFIG_KUNIT=y\nfs/ext4/.kunitconfig:2:CONFIG_EXT4_FS=y\nfs/ext4/.kunitconfig:3:CONFIG_EXT4_KUNIT_TESTS=y\n--\nfs/ext4/Makefile-5-\nfs/ext4/Makefile:6:obj-$(CONFIG_EXT4_FS) += ext4.o\nfs/ext4/Makefile-7-\nfs/ext4/Makefile=8=ext4-y\t:= balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \\\n--\nfs/ext4/Makefile-14-\nfs/ext4/Makefile:15:ext4-$(CONFIG_EXT4_FS_POSIX_ACL)\t+= acl.o\nfs/ext4/Makefile:16:ext4-$(CONFIG_EXT4_FS_SECURITY)\t\t+= xattr_security.o\nfs/ext4/Makefile-17-ext4-test-objs\t\t\t\t+= inode-test.o mballoc-test.o \\\nfs/ext4/Makefile-18-\t\t\t\t\t extents-test.o hash-test.o\nfs/ext4/Makefile:19:obj-$(CONFIG_EXT4_KUNIT_TESTS)\t\t+= ext4-test.o\nfs/ext4/Makefile-20-ext4-$(CONFIG_FS_VERITY)\t\t+= verity.o\n--\nfs/ext4/acl.h=39=static inline int ext4_acl_count(size_t size)\n--\nfs/ext4/acl.h-54-\nfs/ext4/acl.h:55:#ifdef CONFIG_EXT4_FS_POSIX_ACL\nfs/ext4/acl.h-56-\n--\nfs/ext4/acl.h=61=extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);\nfs/ext4/acl.h-62-\nfs/ext4/acl.h:63:#else /* CONFIG_EXT4_FS_POSIX_ACL */\nfs/ext4/acl.h-64-#include \u003clinux/sched.h\u003e\n--\nfs/ext4/acl.h=69=ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)\n--\nfs/ext4/acl.h-72-}\nfs/ext4/acl.h:73:#endif /* CONFIG_EXT4_FS_POSIX_ACL */\nfs/ext4/acl.h-74-\n--\nfs/ext4/ext4.h-91- */\nfs/ext4/ext4.h:92:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/ext4.h-93-#define ext_debug(ino, fmt, ...)\t\t\t\t\t\\\n--\nfs/ext4/ext4.h=1592=struct ext4_sb_info {\n--\nfs/ext4/ext4.h-1806-\tu64 s_dax_part_off;\nfs/ext4/ext4.h:1807:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/ext4.h-1808-\tunsigned long s_simulate_fail;\n--\nfs/ext4/ext4.h-1869-\ttid_t s_fc_ineligible_tid;\nfs/ext4/ext4.h:1870:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/ext4.h-1871-\tint s_fc_debug_max_replay;\n--\nfs/ext4/ext4.h=1994=static inline bool ext4_simulate_fail(struct super_block *sb,\n--\nfs/ext4/ext4.h-1996-{\nfs/ext4/ext4.h:1997:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/ext4.h-1998-\tstruct ext4_sb_info *sbi = EXT4_SB(sb);\n--\nfs/ext4/ext4.h=4045=extern int ext4_block_write_begin(handle_t *handle, struct folio *folio,\n--\nfs/ext4/ext4.h-4048-\nfs/ext4/ext4.h:4049:#if IS_ENABLED(CONFIG_EXT4_KUNIT_TESTS)\nfs/ext4/ext4.h-4050-#define EXPORT_SYMBOL_FOR_EXT4_TEST(sym) \\\n--\nfs/ext4/ext4_extents.h=270=extern int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex);\nfs/ext4/ext4_extents.h:271:#if IS_ENABLED(CONFIG_EXT4_KUNIT_TESTS)\nfs/ext4/ext4_extents.h-272-extern int ext4_ext_space_root_idx_test(struct inode *inode, int check);\n--\nfs/ext4/extents.c=6252=int ext4_ext_clear_bb(struct inode *inode)\n--\nfs/ext4/extents.c-6303-\nfs/ext4/extents.c:6304:#if IS_ENABLED(CONFIG_EXT4_KUNIT_TESTS)\nfs/ext4/extents.c-6305-int ext4_ext_space_root_idx_test(struct inode *inode, int check)\n--\nfs/ext4/fast_commit.c=2570=static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh,\n--\nfs/ext4/fast_commit.c-2595-\nfs/ext4/fast_commit.c:2596:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/fast_commit.c-2597-\tif (sbi-\u003es_fc_debug_max_replay \u0026\u0026 off \u003e= sbi-\u003es_fc_debug_max_replay) {\n--\nfs/ext4/hash.c=314=int ext4fs_dirhash(const struct inode *dir, const char *name, int len,\n--\nfs/ext4/hash.c-344-\nfs/ext4/hash.c:345:#if IS_ENABLED(CONFIG_EXT4_KUNIT_TESTS)\nfs/ext4/hash.c-346-EXPORT_SYMBOL_FOR_EXT4_TEST(ext4fs_dirhash);\n--\nfs/ext4/ialloc.c=876=static int ext4_xattr_credits_for_new_inode(struct inode *dir, mode_t mode,\n--\nfs/ext4/ialloc.c-880-\tint nblocks = 0;\nfs/ext4/ialloc.c:881:#ifdef CONFIG_EXT4_FS_POSIX_ACL\nfs/ext4/ialloc.c-882-\tstruct posix_acl *p = get_inode_acl(dir, ACL_TYPE_DEFAULT);\n--\nfs/ext4/inode.c=409=int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,\n--\nfs/ext4/inode.c-433- */\nfs/ext4/inode.c:434:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/inode.c-435-void ext4_check_map_extents_env(struct inode *inode)\n--\nfs/ext4/mballoc.c=5729=static void ext4_mb_pa_put_free(struct ext4_allocation_context *ac)\n--\nfs/ext4/mballoc.c-5744-\nfs/ext4/mballoc.c:5745:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/mballoc.c-5746-static inline void ext4_mb_show_pa(struct super_block *sb)\n--\nfs/ext4/mballoc.c=7130=ext4_mballoc_query_range(\n--\nfs/ext4/mballoc.c-7185-\nfs/ext4/mballoc.c:7186:#if IS_ENABLED(CONFIG_EXT4_KUNIT_TESTS)\nfs/ext4/mballoc.c-7187-void mb_clear_bits_test(void *bm, int cur, int len)\n--\nfs/ext4/mballoc.h-28- */\nfs/ext4/mballoc.h:29:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/mballoc.h-30-#define mb_debug(sb, fmt, ...)\t\t\t\t\t\t\\\n--\nfs/ext4/mballoc.h=273=extern int ext4_mb_mark_context(handle_t *handle,\n--\nfs/ext4/mballoc.h-277-\t\text4_grpblk_t *ret_changed);\nfs/ext4/mballoc.h:278:#if IS_ENABLED(CONFIG_EXT4_KUNIT_TESTS)\nfs/ext4/mballoc.h-279-extern void mb_clear_bits_test(void *bm, int cur, int len);\n--\nfs/ext4/super.c=125=static const struct fs_context_operations ext4_context_ops = {\n--\nfs/ext4/super.c-132-\nfs/ext4/super.c:133:#if !defined(CONFIG_EXT2_FS) \u0026\u0026 !defined(CONFIG_EXT2_FS_MODULE) \u0026\u0026 defined(CONFIG_EXT4_USE_FOR_EXT2)\nfs/ext4/super.c-134-static struct file_system_type ext2_fs_type = {\n--\nfs/ext4/super.c=1700=enum {\n--\nfs/ext4/super.c-1723-\tOpt_errors, Opt_data, Opt_data_err, Opt_jqfmt, Opt_dax_type,\nfs/ext4/super.c:1724:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/super.c-1725-\tOpt_fc_debug_max_replay, Opt_fc_debug_force\n--\nfs/ext4/super.c=1770=static const struct fs_parameter_spec ext4_param_specs[] = {\n--\nfs/ext4/super.c-1843-\tfsparam_flag\t(\"noinit_itable\",\tOpt_noinit_itable),\nfs/ext4/super.c:1844:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/super.c-1845-\tfsparam_flag\t(\"fc_debug_force\",\tOpt_fc_debug_force),\n--\nfs/ext4/super.c=1887=static const struct mount_opts {\n--\nfs/ext4/super.c-1930-\t{Opt_user_xattr, EXT4_MOUNT_XATTR_USER, MOPT_SET},\nfs/ext4/super.c:1931:#ifdef CONFIG_EXT4_FS_POSIX_ACL\nfs/ext4/super.c-1932-\t{Opt_acl, EXT4_MOUNT_POSIX_ACL, MOPT_SET},\n--\nfs/ext4/super.c-1953-\t MOPT_SET},\nfs/ext4/super.c:1954:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/super.c-1955-\t{Opt_fc_debug_force, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,\n--\nfs/ext4/super.c=2005=struct ext4_fs_context {\n--\nfs/ext4/super.c-2008-\tint\t\ts_jquota_fmt;\t/* Format of quota to use */\nfs/ext4/super.c:2009:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/super.c-2010-\tint s_fc_debug_max_replay;\n--\nfs/ext4/super.c=2179=static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)\n--\nfs/ext4/super.c-2314-\t\treturn 0;\nfs/ext4/super.c:2315:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/super.c-2316-\tcase Opt_fc_debug_max_replay:\n--\nfs/ext4/super.c=2863=static void ext4_apply_options(struct fs_context *fc, struct super_block *sb)\n--\nfs/ext4/super.c-2886-\nfs/ext4/super.c:2887:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/super.c-2888-\tAPPLY(s_fc_debug_max_replay);\n--\nfs/ext4/super.c=4402=static void ext4_set_def_opts(struct super_block *sb,\n--\nfs/ext4/super.c-4417-\tset_opt(sb, XATTR_USER);\nfs/ext4/super.c:4418:#ifdef CONFIG_EXT4_FS_POSIX_ACL\nfs/ext4/super.c-4419-\tset_opt(sb, POSIX_ACL);\n--\nfs/ext4/super.c=7403=static ssize_t ext4_quota_write(struct super_block *sb, int type,\n--\nfs/ext4/super.c-7463-\nfs/ext4/super.c:7464:#if !defined(CONFIG_EXT2_FS) \u0026\u0026 !defined(CONFIG_EXT2_FS_MODULE) \u0026\u0026 defined(CONFIG_EXT4_USE_FOR_EXT2)\nfs/ext4/super.c-7465-static inline void register_as_ext2(void)\n--\nfs/ext4/sysfs.c=266=EXT4_RW_ATTR_SBI_PI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);\nfs/ext4/sysfs.c:267:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/sysfs.c-268-EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail);\n--\nfs/ext4/sysfs.c=295=static struct attribute *ext4_attrs[] = {\n--\nfs/ext4/sysfs.c-335-\tATTR_LIST(journal_task),\nfs/ext4/sysfs.c:336:#ifdef CONFIG_EXT4_DEBUG\nfs/ext4/sysfs.c-337-\tATTR_LIST(simulate_fail),\n--\nfs/ext4/xattr.c=88=static const struct xattr_handler * const ext4_xattr_handler_map[] = {\nfs/ext4/xattr.c-89-\t[EXT4_XATTR_INDEX_USER]\t\t = \u0026ext4_xattr_user_handler,\nfs/ext4/xattr.c:90:#ifdef CONFIG_EXT4_FS_POSIX_ACL\nfs/ext4/xattr.c-91-\t[EXT4_XATTR_INDEX_POSIX_ACL_ACCESS] = \u0026nop_posix_acl_access,\n--\nfs/ext4/xattr.c-94-\t[EXT4_XATTR_INDEX_TRUSTED]\t = \u0026ext4_xattr_trusted_handler,\nfs/ext4/xattr.c:95:#ifdef CONFIG_EXT4_FS_SECURITY\nfs/ext4/xattr.c-96-\t[EXT4_XATTR_INDEX_SECURITY]\t = \u0026ext4_xattr_security_handler,\n--\nfs/ext4/xattr.c=101=const struct xattr_handler * const ext4_xattr_handlers[] = {\n--\nfs/ext4/xattr.c-103-\t\u0026ext4_xattr_trusted_handler,\nfs/ext4/xattr.c:104:#ifdef CONFIG_EXT4_FS_SECURITY\nfs/ext4/xattr.c-105-\t\u0026ext4_xattr_security_handler,\n--\nfs/ext4/xattr.h=208=__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,\n--\nfs/ext4/xattr.h-213-\nfs/ext4/xattr.h:214:#ifdef CONFIG_EXT4_FS_SECURITY\nfs/ext4/xattr.h-215-extern int ext4_init_security(handle_t *handle, struct inode *inode,\n"
} |
| 7/2 | 2026/07/28 00:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 18745 output: 35 thoughts: 383 Thoughts: **Fuzzing EXT4's Inline Data Conversion** Okay, so I need to focus on fuzzing the EXT4 file system's inline data features. The core configuration requirement is `EXT4_FS`, naturally. Let's see what else pops up. Right, the `inline_data` feature is integral to EXT4's operation. My initial thought is to examine the key functions involved in its lifecycle: `ext4_convert_inline_data` and `ext4_destroy_inline_data`. Looking at where `ext4_convert_inline_data` is used is useful. It's exported, and I see it called from several important areas: `ext4_setattr`, `ext4_page_mkwrite`, `ext4_fallocate`, and `ext4_begin_enable_verity`. This immediately tells me these are high-value targets for fuzzing. My initial instinct was to also include `ext4_generic_write_inline_data`, which seems relevant, and even `ext4_convert_inline_data_nolock` (although it's static and the instructions say to prioritize non-static entrypoints), but let's stick to the non-static functions for now. Therefore, the best candidates to fuzz are: * `ext4_convert_inline_data` * `ext4_destroy_inline_data` Okay, let's double-check how `ext4_generic_write_inline_data` fits in. It *appears* to be called from `ext4_da_write_begin`. Wait, is `ext4_generic_write_inline_data` exported? Let me double-check. It's actually in `fs/ext4/inline.c` and declared in `fs/ext4/ext4.h`. So let's double-check `fs/ext4/ext4.h` to make sure I'm not missing anything. |
| 8/2 | 2026/07/28 00:14 | tool | grepper |
0mArgs:{
"Expression": "ext4_generic_write_inline_data",
"PathPrefix": "fs/ext4/"
}Results: {
"Output": "fs/ext4/ext4.h=3760=int ext4_readpage_inline(struct inode *inode, struct folio *folio);\nfs/ext4/ext4.h:3761:extern int ext4_generic_write_inline_data(struct address_space *mapping,\nfs/ext4/ext4.h-3762-\t\t\t\t\t struct inode *inode,\n--\nfs/ext4/inline.c=511=int ext4_readpage_inline(struct inode *inode, struct folio *folio)\n--\nfs/ext4/inline.c-545- */\nfs/ext4/inline.c:546:int ext4_generic_write_inline_data(struct address_space *mapping,\nfs/ext4/inline.c-547-\t\t\t\t\t struct inode *inode,\n--\nfs/ext4/inode.c=3132=static int ext4_da_write_begin(const struct kiocb *iocb,\n--\nfs/ext4/inode.c-3156-\tif (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {\nfs/ext4/inode.c:3157:\t\tret = ext4_generic_write_inline_data(mapping, inode, pos, len,\nfs/ext4/inode.c-3158-\t\t\t\t\t\t foliop, true);\n"
} |
| 9/2 | 2026/07/28 00:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 19938 output: 33 thoughts: 309 Thoughts: **Analyzing the EXT4 Inline Data Write Path**
Okay, so I see that `ext4_generic_write_inline_data` is indeed called from `ext4_da_write_begin`, which aligns with my initial understanding. But hold on, the patch notes something interesting: `ext4_try_to_write_inline_data` was removed. Hmm, instead, the patch now calls `ext4_convert_inline_data` within `ext4_write_begin`. Let me quickly re-examine the code snippet from the patch:
```c
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
- ret = ext4_try_to_write_inline_data(mapping, inode, pos, len,
- foliop);
+ ret = ext4_convert_inline_data(inode);
if (ret < 0)
return ret;
- if (ret == 1) {
- *fsdata = (void *)((unsigned long)*fsdata | EXT4_WRITE_DATA_INLINE);
- return 0;
- }
}
```
Right, it's clear: `ext4_convert_inline_data` has taken over. This means that function is going to be a key focus point for understanding how the inline data conversion now works. Also, I see `ext4_destroy_inline_data` has been modified, and that modification is done via `ext4_destroy_inline_data_nolock`, so that looks like another area of interest. Now, I should dive into the `fs/ext4/inline.c` file and specifically examine `ext4_destroy_inline_data` there.
|
| 10/2 | 2026/07/28 00:14 | tool | grepper |
0mArgs:{
"Expression": "ext4_destroy_inline_data",
"PathPrefix": "fs/ext4/"
}Results: {
"Output": "fs/ext4/ext4.h=3756=extern int ext4_find_inline_data_nolock(struct inode *inode);\nfs/ext4/ext4.h:3757:extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);\nfs/ext4/ext4.h-3758-extern void ext4_update_final_de(void *de_buf, int old_size, int new_size);\n--\nfs/ext4/inline.c=358=static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,\n--\nfs/ext4/inline.c-386-\nfs/ext4/inline.c:387:static int ext4_destroy_inline_data_nolock(handle_t *handle,\nfs/ext4/inline.c-388-\t\t\t\t\t struct inode *inode,\n--\nfs/ext4/inline.c=693=static int ext4_convert_inline_data_nolock(handle_t *handle,\n--\nfs/ext4/inline.c-768-\t * data and populate the extent entry atomically under i_data_sem\nfs/ext4/inline.c:769:\t * (inside ext4_destroy_inline_data_nolock). This ensures no\nfs/ext4/inline.c-770-\t * concurrent reader sees an empty extent tree.\nfs/ext4/inline.c-771-\t */\nfs/ext4/inline.c:772:\terror = ext4_destroy_inline_data_nolock(handle, inode, pblk);\nfs/ext4/inline.c-773-\tif (error)\n--\nfs/ext4/inline.c=1356=bool empty_inline_dir(struct inode *dir, int *has_inline_data)\n--\nfs/ext4/inline.c-1418-\nfs/ext4/inline.c:1419:int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)\nfs/ext4/inline.c-1420-{\n--\nfs/ext4/inline.c-1423-\text4_write_lock_xattr(inode, \u0026no_expand);\nfs/ext4/inline.c:1424:\tret = ext4_destroy_inline_data_nolock(handle, inode, 0);\nfs/ext4/inline.c-1425-\text4_write_unlock_xattr(inode, \u0026no_expand);\n--\nfs/ext4/inode.c=2772=static int ext4_do_writepages(struct mpage_da_data *mpd)\n--\nfs/ext4/inode.c-2824-\t\t\t\tEXT4_STATE_MAY_INLINE_DATA));\nfs/ext4/inode.c:2825:\t\text4_destroy_inline_data(handle, inode);\nfs/ext4/inode.c-2826-\t\text4_journal_stop(handle);\n"
} |
| 11/2 | 2026/07/28 00:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21439 output: 125 thoughts: 1054 Thoughts: **Fuzzing Plan for Inline Data Deprecation in ext4** Okay, so I'm looking at this patch that deprecates inline data for regular files in ext4. The primary goal is to force conversion to block-based storage whenever a write operation occurs. This is a significant change to the write paths and inline data conversion logic, therefore, I need to focus on fuzzing this area. My first thought is to trace the calls. I see `ext4_destroy_inline_data` called from `ext4_do_writepages`, and `ext4_convert_inline_data` is called from a number of places: `ext4_write_begin`, `ext4_setattr`, `ext4_page_mkwrite`, `ext4_fallocate`, and `ext4_begin_enable_verity`. Also, I've got `ext4_generic_write_inline_data` called from `ext4_da_write_begin`. The core function to focus on seems to be `ext4_convert_inline_data`, as the patch is deprecating and forcing conversion from inline data. I also have `ext4_generic_write_inline_data` which seems to be a simple wrapper now and just calls `ext4_convert_inline_data(inode)`. I'll keep this as a fuzz target as an entry point. Then there is `ext4_destroy_inline_data`, which I will also focus on. So, for the configurations, the only necessary one seems to be `EXT4_FS`. I've checked the modified files (`fs/ext4/inline.c`, `fs/ext4/inode.c`, `fs/ext4/ialloc.c`, `fs/ext4/super.c`, `fs/ext4/ext4.h`) – all of them are within the `CONFIG_EXT4_FS` scope. Now, `ext4_convert_inline_data_nolock` is where the main conversion logic occurs. However, it is static and cannot be accessed directly, but that is fine as the entry is `ext4_convert_inline_data`. I also briefly looked at `__ext4_new_inode`, which is changed to prevent the setting of EXT4_STATE_MAY_INLINE_DATA for regular files. However, this seems like a generic change and not directly related to the deprecation. The conversion functions are the most important. I am confident that the parameters should be set as: - EnableConfigs: `["EXT4_FS"]` - FocusSymbols: `["ext4_convert_inline_data", "ext4_generic_write_inline_data", "ext4_destroy_inline_data"]` - Reasoning: "The patch deprecates the inline_data feature for regular files in ext4, forcing conversion to block-based storage on write. This modifies core ext4 write paths and inline data conversion logic, which should be fuzzed to ensure no regressions or data corruption issues." - WorthFuzzing: true I am ready to finalize my setup. |
| 12/2 | 2026/07/28 00:14 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"EXT4_FS"
],
"FocusSymbols": [
"ext4_convert_inline_data",
"ext4_generic_write_inline_data",
"ext4_destroy_inline_data"
],
"Reasoning": "The patch deprecates the inline_data feature for regular files in ext4, forcing conversion to block-based storage on write. This modifies core ext4 write paths and inline data conversion logic, which should be fuzzed to ensure no regressions or data corruption issues.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"EXT4_FS"
],
"FocusSymbols": [
"ext4_convert_inline_data",
"ext4_generic_write_inline_data",
"ext4_destroy_inline_data"
],
"Reasoning": "The patch deprecates the inline_data feature for regular files in ext4, forcing conversion to block-based storage on write. This modifies core ext4 write paths and inline data conversion logic, which should be fuzzed to ensure no regressions or data corruption issues.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|