6975 lines · 201.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* *  linux/fs/ext4/inode.c * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * *  from * *  linux/fs/minix/inode.c * *  Copyright (C) 1991, 1992  Linus Torvalds * *  64-bit file support on 64-bit platforms by Jakub Jelinek *	(jj@sunsite.ms.mff.cuni.cz) * *  Assorted race fixes, rewrite of ext4_get_block() by Al Viro, 2000 */ #include <linux/fs.h>#include <linux/mount.h>#include <linux/time.h>#include <linux/highuid.h>#include <linux/pagemap.h>#include <linux/dax.h>#include <linux/quotaops.h>#include <linux/string.h>#include <linux/buffer_head.h>#include <linux/writeback.h>#include <linux/folio_batch.h>#include <linux/mpage.h>#include <linux/rmap.h>#include <linux/namei.h>#include <linux/uio.h>#include <linux/bio.h>#include <linux/workqueue.h>#include <linux/kernel.h>#include <linux/printk.h>#include <linux/slab.h>#include <linux/bitops.h>#include <linux/iomap.h>#include <linux/iversion.h> #include "ext4_jbd2.h"#include "xattr.h"#include "acl.h"#include "truncate.h" #include <kunit/static_stub.h> #include <trace/events/ext4.h> static void ext4_journalled_zero_new_buffers(handle_t *handle,					    struct inode *inode,					    struct folio *folio,					    unsigned from, unsigned to); static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw,			      struct ext4_inode_info *ei){	__u32 csum;	__u16 dummy_csum = 0;	int offset = offsetof(struct ext4_inode, i_checksum_lo);	unsigned int csum_size = sizeof(dummy_csum); 	csum = ext4_chksum(ei->i_csum_seed, (__u8 *)raw, offset);	csum = ext4_chksum(csum, (__u8 *)&dummy_csum, csum_size);	offset += csum_size;	csum = ext4_chksum(csum, (__u8 *)raw + offset,			   EXT4_GOOD_OLD_INODE_SIZE - offset); 	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {		offset = offsetof(struct ext4_inode, i_checksum_hi);		csum = ext4_chksum(csum, (__u8 *)raw + EXT4_GOOD_OLD_INODE_SIZE,				   offset - EXT4_GOOD_OLD_INODE_SIZE);		if (EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) {			csum = ext4_chksum(csum, (__u8 *)&dummy_csum,					   csum_size);			offset += csum_size;		}		csum = ext4_chksum(csum, (__u8 *)raw + offset,				   EXT4_INODE_SIZE(inode->i_sb) - offset);	} 	return csum;} static int ext4_inode_csum_verify(struct inode *inode, struct ext4_inode *raw,				  struct ext4_inode_info *ei){	__u32 provided, calculated; 	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=	    cpu_to_le32(EXT4_OS_LINUX) ||	    !ext4_has_feature_metadata_csum(inode->i_sb))		return 1; 	provided = le16_to_cpu(raw->i_checksum_lo);	calculated = ext4_inode_csum(inode, raw, ei);	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&	    EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi))		provided |= ((__u32)le16_to_cpu(raw->i_checksum_hi)) << 16;	else		calculated &= 0xFFFF; 	return provided == calculated;} void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw,			 struct ext4_inode_info *ei){	__u32 csum; 	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=	    cpu_to_le32(EXT4_OS_LINUX) ||	    !ext4_has_feature_metadata_csum(inode->i_sb))		return; 	csum = ext4_inode_csum(inode, raw, ei);	raw->i_checksum_lo = cpu_to_le16(csum & 0xFFFF);	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&	    EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi))		raw->i_checksum_hi = cpu_to_le16(csum >> 16);} static inline int ext4_begin_ordered_truncate(struct inode *inode,					      loff_t new_size){	struct jbd2_inode *jinode = READ_ONCE(EXT4_I(inode)->jinode); 	trace_ext4_begin_ordered_truncate(inode, new_size);	/*	 * If jinode is zero, then we never opened the file for	 * writing, so there's no need to call	 * jbd2_journal_begin_ordered_truncate() since there's no	 * outstanding writes we need to flush.	 */	if (!jinode)		return 0;	return jbd2_journal_begin_ordered_truncate(EXT4_JOURNAL(inode),						   jinode,						   new_size);} /* * Test whether an inode is a fast symlink. * A fast symlink has its symlink data stored in ext4_inode_info->i_data. */int ext4_inode_is_fast_symlink(struct inode *inode){	if (!ext4_has_feature_ea_inode(inode->i_sb)) {		int ea_blocks = EXT4_I(inode)->i_file_acl ?				EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0; 		if (ext4_has_inline_data(inode))			return 0; 		return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);	}	return S_ISLNK(inode->i_mode) && inode->i_size &&	       (inode->i_size < EXT4_N_BLOCKS * 4);} /* * Called at the last iput() if i_nlink is zero. */void ext4_evict_inode(struct inode *inode){	handle_t *handle;	int err;	/*	 * Credits for final inode cleanup and freeing:	 * sb + inode (ext4_orphan_del()), block bitmap, group descriptor	 * (xattr block freeing), bitmap, group descriptor (inode freeing)	 */	int extra_credits = 6;	bool freeze_protected = false; 	trace_ext4_evict_inode(inode); 	dax_break_layout_final(inode); 	if (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)		ext4_evict_ea_inode(inode);	if (inode->i_nlink) {		struct mapping_metadata_bhs *mmb; 		/*		 * If there's dirty page will lead to data loss, user		 * could see stale data.		 */		if (unlikely(!ext4_emergency_state(inode->i_sb) &&		    mapping_tagged(&inode->i_data, PAGECACHE_TAG_DIRTY)))			ext4_warning_inode(inode, "data will be lost"); 		truncate_inode_pages_final(&inode->i_data);		mmb = ext4_i_metadata_bhs(inode);		if (mmb)			mmb_sync(mmb);		goto no_delete;	} 	if (is_bad_inode(inode))		goto no_delete;	dquot_initialize(inode); 	if (ext4_should_order_data(inode))		ext4_begin_ordered_truncate(inode, 0);	truncate_inode_pages_final(&inode->i_data); 	/*	 * For inodes with journalled data, transaction commit could have	 * dirtied the inode. And for inodes with dioread_nolock, unwritten	 * extents converting worker could merge extents and also have dirtied	 * the inode. Flush worker is ignoring it because of I_FREEING flag but	 * we still need to remove the inode from the writeback lists.	 */	inode_io_list_del(inode); 	/*	 * Protect us against freezing - iput() caller didn't have to have any	 * protection against it. When we are in a running transaction though,	 * we are already protected against freezing and we cannot grab further	 * protection due to lock ordering constraints.	 */	if (!ext4_journal_current_handle()) {		sb_start_intwrite(inode->i_sb);		freeze_protected = true;	} 	if (!IS_NOQUOTA(inode))		extra_credits += EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb); 	/*	 * Block bitmap, group descriptor, and inode are accounted in both	 * ext4_blocks_for_truncate() and extra_credits. So subtract 3.	 */	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE,			 ext4_blocks_for_truncate(inode) + extra_credits - 3);	if (IS_ERR(handle)) {		ext4_std_error(inode->i_sb, PTR_ERR(handle));		/*		 * If we're going to skip the normal cleanup, we still need to		 * make sure that the in-core orphan linked list is properly		 * cleaned up.		 */		ext4_orphan_del(NULL, inode);		if (freeze_protected)			sb_end_intwrite(inode->i_sb);		goto no_delete;	} 	if (IS_SYNC(inode))		ext4_handle_sync(handle); 	/*	 * Set inode->i_size to 0 before calling ext4_truncate(). We need	 * special handling of symlinks here because i_size is used to	 * determine whether ext4_inode_info->i_data contains symlink data or	 * block mappings. Setting i_size to 0 will remove its fast symlink	 * status. Erase i_data so that it becomes a valid empty block map.	 */	if (ext4_inode_is_fast_symlink(inode))		memset(EXT4_I(inode)->i_data, 0, sizeof(EXT4_I(inode)->i_data));	inode->i_size = 0;	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);	err = ext4_mark_inode_dirty(handle, inode);	if (err) {		ext4_warning(inode->i_sb,			     "couldn't mark inode dirty (err %d)", err);		goto stop_handle;	}	if (inode->i_blocks) {		err = ext4_truncate(inode);		if (err) {			ext4_error_err(inode->i_sb, -err,				       "couldn't truncate inode %llu (err %d)",				       inode->i_ino, err);			goto stop_handle;		}	} 	/* Remove xattr references. */	err = ext4_xattr_delete_inode(handle, inode, extra_credits);	if (err) {		ext4_warning(inode->i_sb, "xattr delete (err %d)", err);stop_handle:		ext4_journal_stop(handle);		ext4_orphan_del(NULL, inode);		if (freeze_protected)			sb_end_intwrite(inode->i_sb);		goto no_delete;	} 	/*	 * Kill off the orphan record which ext4_truncate created.	 * AKPM: I think this can be inside the above `if'.	 * Note that ext4_orphan_del() has to be able to cope with the	 * deletion of a non-existent orphan - this is because we don't	 * know if ext4_truncate() actually created an orphan record.	 * (Well, we could do this if we need to, but heck - it works)	 */	ext4_orphan_del(handle, inode);	EXT4_I(inode)->i_dtime	= (__u32)ktime_get_real_seconds(); 	/*	 * One subtle ordering requirement: if anything has gone wrong	 * (transaction abort, IO errors, whatever), then we can still	 * do these next steps (the fs will already have been marked as	 * having errors), but we can't free the inode if the mark_dirty	 * fails.	 */	if (ext4_mark_inode_dirty(handle, inode))		/* If that failed, just do the required in-core inode clear. */		ext4_clear_inode(inode);	else		ext4_free_inode(handle, inode);	ext4_journal_stop(handle);	if (freeze_protected)		sb_end_intwrite(inode->i_sb);	return;no_delete:	/*	 * Check out some where else accidentally dirty the evicting inode,	 * which may probably cause inode use-after-free issues later.	 */	WARN_ON_ONCE(!list_empty_careful(&inode->i_io_list)); 	if (!list_empty(&EXT4_I(inode)->i_fc_list))		ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL);	ext4_clear_inode(inode);	/* We must guarantee clearing of inode... */} #ifdef CONFIG_QUOTAqsize_t *ext4_get_reserved_space(struct inode *inode){	return &EXT4_I(inode)->i_reserved_quota;}#endif /* * Called with i_data_sem down, which is important since we can call * ext4_discard_preallocations() from here. */void ext4_da_update_reserve_space(struct inode *inode,					int used, int quota_claim){	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);	struct ext4_inode_info *ei = EXT4_I(inode); 	spin_lock(&ei->i_block_reservation_lock);	trace_ext4_da_update_reserve_space(inode, used, quota_claim);	if (unlikely(used > ei->i_reserved_data_blocks)) {		ext4_warning(inode->i_sb, "%s: ino %llu, used %d "			 "with only %d reserved data blocks",			 __func__, inode->i_ino, used,			 ei->i_reserved_data_blocks);		WARN_ON(1);		used = ei->i_reserved_data_blocks;	} 	/* Update per-inode reservations */	ei->i_reserved_data_blocks -= used;	percpu_counter_sub(&sbi->s_dirtyclusters_counter, used); 	spin_unlock(&ei->i_block_reservation_lock); 	/* Update quota subsystem for data blocks */	if (quota_claim)		dquot_claim_block(inode, EXT4_C2B(sbi, used));	else {		/*		 * We did fallocate with an offset that is already delayed		 * allocated. So on delayed allocated writeback we should		 * not re-claim the quota for fallocated blocks.		 */		dquot_release_reservation_block(inode, EXT4_C2B(sbi, used));	} 	/*	 * If we have done all the pending block allocations and if	 * there aren't any writers on the inode, we can discard the	 * inode's preallocations.	 */	if ((ei->i_reserved_data_blocks == 0) &&	    !inode_is_open_for_write(inode))		ext4_discard_preallocations(inode);} static int __check_block_validity(struct inode *inode, const char *func,				unsigned int line,				struct ext4_map_blocks *map){	journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; 	if (journal && inode == journal->j_inode)		return 0; 	if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) {		ext4_error_inode(inode, func, line, map->m_pblk,				 "lblock %lu mapped to illegal pblock %llu "				 "(length %d)", (unsigned long) map->m_lblk,				 map->m_pblk, map->m_len);		return -EFSCORRUPTED;	}	return 0;} int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,		       ext4_lblk_t len){	int ret; 	KUNIT_STATIC_STUB_REDIRECT(ext4_issue_zeroout, inode, lblk, pblk, len); 	if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))		return fscrypt_zeroout_range(inode,				(loff_t)lblk << inode->i_blkbits,				pblk << (inode->i_blkbits - SECTOR_SHIFT),				(u64)len << inode->i_blkbits); 	ret = sb_issue_zeroout(inode->i_sb, pblk, len, GFP_NOFS);	if (ret > 0)		ret = 0; 	return ret;} /* * For generic regular files, when updating the extent tree, Ext4 should * hold the i_rwsem and invalidate_lock exclusively. This ensures * exclusion against concurrent page faults, as well as reads and writes. */#ifdef CONFIG_EXT4_DEBUGvoid ext4_check_map_extents_env(struct inode *inode){	if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)		return; 	if (!S_ISREG(inode->i_mode) ||	    IS_NOQUOTA(inode) || IS_VERITY(inode) ||	    is_special_ino(inode->i_sb, inode->i_ino) ||	    (inode_state_read_once(inode) & (I_FREEING | I_WILL_FREE | I_NEW)) ||	    ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||	    ext4_verity_in_progress(inode))		return; 	WARN_ON_ONCE(!inode_is_locked(inode) &&		     !rwsem_is_locked(&inode->i_mapping->invalidate_lock));}#elsevoid ext4_check_map_extents_env(struct inode *inode) {}#endif #define check_block_validity(inode, map)	\	__check_block_validity((inode), __func__, __LINE__, (map)) #ifdef ES_AGGRESSIVE_TESTstatic void ext4_map_blocks_es_recheck(handle_t *handle,				       struct inode *inode,				       struct ext4_map_blocks *es_map,				       struct ext4_map_blocks *map,				       int flags){	int retval; 	map->m_flags = 0;	/*	 * There is a race window that the result is not the same.	 * e.g. xfstests #223 when dioread_nolock enables.  The reason	 * is that we lookup a block mapping in extent status tree with	 * out taking i_data_sem.  So at the time the unwritten extent	 * could be converted.	 */	down_read(&EXT4_I(inode)->i_data_sem);	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {		retval = ext4_ext_map_blocks(handle, inode, map, 0);	} else {		retval = ext4_ind_map_blocks(handle, inode, map, 0);	}	up_read((&EXT4_I(inode)->i_data_sem)); 	/*	 * We don't check m_len because extent will be collpased in status	 * tree.  So the m_len might not equal.	 */	if (es_map->m_lblk != map->m_lblk ||	    es_map->m_flags != map->m_flags ||	    es_map->m_pblk != map->m_pblk) {		printk("ES cache assertion failed for inode: %llu "		       "es_cached ex [%d/%d/%llu/%x] != "		       "found ex [%d/%d/%llu/%x] retval %d flags %x\n",		       inode->i_ino, es_map->m_lblk, es_map->m_len,		       es_map->m_pblk, es_map->m_flags, map->m_lblk,		       map->m_len, map->m_pblk, map->m_flags,		       retval, flags);	}}

Lines 1–500 of 6975.