/* only atomic file w/ FI_ATOMIC_COMMITTED can be set vfs dirty */ if (f2fs_is_atomic_file(inode) &&
!is_inode_flag_set(inode, FI_ATOMIC_COMMITTED)) return;
if (!f2fs_sb_has_extra_attr(sbi)) { if (f2fs_sb_has_project_quota(sbi)) {
f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
__func__, inode->i_ino, F2FS_FEATURE_PRJQUOTA); returnfalse;
} if (f2fs_sb_has_inode_chksum(sbi)) {
f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
__func__, inode->i_ino, F2FS_FEATURE_INODE_CHKSUM); returnfalse;
} if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
__func__, inode->i_ino, F2FS_FEATURE_FLEXIBLE_INLINE_XATTR); returnfalse;
} if (f2fs_sb_has_inode_crtime(sbi)) {
f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
__func__, inode->i_ino, F2FS_FEATURE_INODE_CRTIME); returnfalse;
} if (f2fs_sb_has_compression(sbi)) {
f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
__func__, inode->i_ino, F2FS_FEATURE_COMPRESSION); returnfalse;
}
}
if (f2fs_sanity_check_inline_data(inode, node_folio)) {
f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_data, run fsck to fix",
__func__, inode->i_ino, inode->i_mode); returnfalse;
}
if (f2fs_has_inline_dentry(inode) && !S_ISDIR(inode->i_mode)) {
f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_dentry, run fsck to fix",
__func__, inode->i_ino, inode->i_mode); returnfalse;
}
if ((fi->i_flags & F2FS_CASEFOLD_FL) && !f2fs_sb_has_casefold(sbi)) {
f2fs_warn(sbi, "%s: inode (ino=%lx) has casefold flag, but casefold feature is off",
__func__, inode->i_ino); returnfalse;
}
if (fi->i_xattr_nid && f2fs_check_nid_range(sbi, fi->i_xattr_nid)) {
f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_xattr_nid: %u, run fsck to fix.",
__func__, inode->i_ino, fi->i_xattr_nid); returnfalse;
}
if (IS_DEVICE_ALIASING(inode)) { if (!f2fs_sb_has_device_alias(sbi)) {
f2fs_warn(sbi, "%s: inode (ino=%lx) has device alias flag, but the feature is off",
__func__, inode->i_ino); returnfalse;
} if (!f2fs_is_pinned_file(inode)) {
f2fs_warn(sbi, "%s: inode (ino=%lx) has device alias flag, but is not pinned",
__func__, inode->i_ino); returnfalse;
}
}
/* * Previous inline data or directory always reserved 200 bytes * in inode layout, even if inline_xattr is disabled. In order * to keep inline_dentry's structure for backward compatibility, * we get the space back only from inline_data.
*/
fi->i_inline_xattr_size = 0;
}
if (inode->i_ino == F2FS_NODE_INO(sbi) ||
inode->i_ino == F2FS_META_INO(sbi)) return 0;
/* * atime could be updated without dirtying f2fs inode in lazytime mode
*/ if (f2fs_is_time_consistent(inode) &&
!is_inode_flag_set(inode, FI_DIRTY_INODE)) return 0;
/* * no need to update inode page, ultimately f2fs_evict_inode() will * clear dirty status of inode.
*/ if (f2fs_cp_error(sbi)) return -EIO;
if (!f2fs_is_checkpoint_ready(sbi)) {
f2fs_mark_inode_dirty_sync(inode, true); return -ENOSPC;
}
/* * We need to balance fs here to prevent from producing dirty node pages * during the urgent cleaning time when running out of free sections.
*/
f2fs_update_inode_page(inode); if (wbc && wbc->nr_to_write)
f2fs_balance_fs(sbi, true); return 0;
}
/* * Called at the last iput() if i_nlink is zero
*/ void f2fs_evict_inode(struct inode *inode)
{ struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode);
nid_t xnid = fi->i_xattr_nid; int err = 0; bool freeze_protected = false;
if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING)) {
sb_start_intwrite(inode->i_sb);
freeze_protected = true;
}
set_inode_flag(inode, FI_NO_ALLOC);
i_size_write(inode, 0);
retry: if (F2FS_HAS_BLOCKS(inode))
err = f2fs_truncate(inode);
if (time_to_inject(sbi, FAULT_EVICT_INODE))
err = -EIO;
if (!err) {
f2fs_lock_op(sbi);
err = f2fs_remove_inode_page(inode);
f2fs_unlock_op(sbi); if (err == -ENOENT) {
err = 0;
/* * in fuzzed image, another node may has the same * block address as inode's, if it was truncated * previously, truncation of inode node will fail.
*/ if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
f2fs_warn(F2FS_I_SB(inode), "f2fs_evict_inode: inconsistent node id, ino:%lu",
inode->i_ino);
f2fs_inode_synced(inode);
set_sbi_flag(sbi, SBI_NEED_FSCK);
}
}
}
/* give more chances, if ENOMEM case */ if (err == -ENOMEM) {
err = 0; goto retry;
}
if (IS_DEVICE_ALIASING(inode))
f2fs_destroy_extent_tree(inode);
if (err) {
f2fs_update_inode_page(inode); if (dquot_initialize_needed(inode))
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
/* * If both f2fs_truncate() and f2fs_update_inode_page() failed * due to fuzzed corrupted inode, call f2fs_inode_synced() to * avoid triggering later f2fs_bug_on().
*/ if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
f2fs_warn(sbi, "f2fs_evict_inode: inode is dirty, ino:%lu",
inode->i_ino);
f2fs_inode_synced(inode);
set_sbi_flag(sbi, SBI_NEED_FSCK);
}
} if (freeze_protected)
sb_end_intwrite(inode->i_sb);
no_delete:
dquot_drop(inode);
if (likely(!f2fs_cp_error(sbi) &&
!is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE));
/* * anyway, it needs to remove the inode from sbi->inode_list[DIRTY_META] * list to avoid UAF in f2fs_sync_inode_meta() during checkpoint.
*/
f2fs_inode_synced(inode);
/* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */ if (inode->i_ino)
invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino,
inode->i_ino); if (xnid)
invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid); if (inode->i_nlink) { if (is_inode_flag_set(inode, FI_APPEND_WRITE))
f2fs_add_ino_entry(sbi, inode->i_ino, APPEND_INO); if (is_inode_flag_set(inode, FI_UPDATE_WRITE))
f2fs_add_ino_entry(sbi, inode->i_ino, UPDATE_INO);
} if (is_inode_flag_set(inode, FI_FREE_NID)) {
f2fs_alloc_nid_failed(sbi, inode->i_ino);
clear_inode_flag(inode, FI_FREE_NID);
} else { /* * If xattr nid is corrupted, we can reach out error condition, * err & !f2fs_exist_written_data(sbi, inode->i_ino, ORPHAN_INO)). * In that case, f2fs_check_nid_range() is enough to give a clue.
*/
}
out_clear:
fscrypt_put_encryption_info(inode);
fsverity_cleanup_inode(inode);
clear_inode(inode);
}
/* * clear nlink of inode in order to release resource of inode * immediately.
*/
clear_nlink(inode);
/* * we must call this to avoid inode being remained as dirty, resulting * in a panic when flushing dirty inodes in gdirty_list.
*/
f2fs_update_inode_page(inode);
f2fs_inode_synced(inode);
/* don't make bad inode, since it becomes a regular file. */
unlock_new_inode(inode);
/* * Note: we should add inode to orphan list before f2fs_unlock_op() * so we can prevent losing this orphan when encoutering checkpoint * and following suddenly power-off.
*/
err = f2fs_get_node_info(sbi, inode->i_ino, &ni, false); if (err) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
set_inode_flag(inode, FI_FREE_NID);
f2fs_warn(sbi, "May loss orphan inode, run fsck to fix."); goto out;
}
if (ni.blk_addr != NULL_ADDR) {
err = f2fs_acquire_orphan_inode(sbi); if (err) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_warn(sbi, "Too many orphan inodes, run fsck to fix.");
} else {
f2fs_add_orphan_inode(inode);
}
f2fs_alloc_nid_done(sbi, inode->i_ino);
} else {
set_inode_flag(inode, FI_FREE_NID);
}
out:
f2fs_unlock_op(sbi);
/* iput will drop the inode object */
iput(inode);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-04-25)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.