⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 *	We are freeing all blocks refered from these branches (numbers are *	stored as little-endian 32-bit) and updating @inode->i_blocks *	appropriately. */static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int depth){	struct buffer_head * bh;	unsigned long nr;	if (depth--) {		int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);		for ( ; p < q ; p++) {			nr = le32_to_cpu(*p);			if (!nr)				continue;			*p = 0;			bh = sb_bread(inode->i_sb, nr);			/*			 * A read failure? Report error and clear slot			 * (should be rare).			 */ 			if (!bh) {				ext2_error(inode->i_sb, "ext2_free_branches",					"Read failure, inode=%ld, block=%ld",					inode->i_ino, nr);				continue;			}			ext2_free_branches(inode,					   (__le32*)bh->b_data,					   (__le32*)bh->b_data + addr_per_block,					   depth);			bforget(bh);			ext2_free_blocks(inode, nr, 1);			mark_inode_dirty(inode);		}	} else		ext2_free_data(inode, p, q);}void ext2_truncate(struct inode *inode){	__le32 *i_data = EXT2_I(inode)->i_data;	struct ext2_inode_info *ei = EXT2_I(inode);	int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);	int offsets[4];	Indirect chain[4];	Indirect *partial;	__le32 nr = 0;	int n;	long iblock;	unsigned blocksize;	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||	    S_ISLNK(inode->i_mode)))		return;	if (ext2_inode_is_fast_symlink(inode))		return;	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))		return;	blocksize = inode->i_sb->s_blocksize;	iblock = (inode->i_size + blocksize-1)					>> EXT2_BLOCK_SIZE_BITS(inode->i_sb);	if (mapping_is_xip(inode->i_mapping))		xip_truncate_page(inode->i_mapping, inode->i_size);	else if (test_opt(inode->i_sb, NOBH))		nobh_truncate_page(inode->i_mapping,				inode->i_size, ext2_get_block);	else		block_truncate_page(inode->i_mapping,				inode->i_size, ext2_get_block);	n = ext2_block_to_path(inode, iblock, offsets, NULL);	if (n == 0)		return;	/*	 * From here we block out all ext2_get_block() callers who want to	 * modify the block allocation tree.	 */	mutex_lock(&ei->truncate_mutex);	if (n == 1) {		ext2_free_data(inode, i_data+offsets[0],					i_data + EXT2_NDIR_BLOCKS);		goto do_indirects;	}	partial = ext2_find_shared(inode, n, offsets, chain, &nr);	/* Kill the top of shared branch (already detached) */	if (nr) {		if (partial == chain)			mark_inode_dirty(inode);		else			mark_buffer_dirty_inode(partial->bh, inode);		ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);	}	/* Clear the ends of indirect blocks on the shared branch */	while (partial > chain) {		ext2_free_branches(inode,				   partial->p + 1,				   (__le32*)partial->bh->b_data+addr_per_block,				   (chain+n-1) - partial);		mark_buffer_dirty_inode(partial->bh, inode);		brelse (partial->bh);		partial--;	}do_indirects:	/* Kill the remaining (whole) subtrees */	switch (offsets[0]) {		default:			nr = i_data[EXT2_IND_BLOCK];			if (nr) {				i_data[EXT2_IND_BLOCK] = 0;				mark_inode_dirty(inode);				ext2_free_branches(inode, &nr, &nr+1, 1);			}		case EXT2_IND_BLOCK:			nr = i_data[EXT2_DIND_BLOCK];			if (nr) {				i_data[EXT2_DIND_BLOCK] = 0;				mark_inode_dirty(inode);				ext2_free_branches(inode, &nr, &nr+1, 2);			}		case EXT2_DIND_BLOCK:			nr = i_data[EXT2_TIND_BLOCK];			if (nr) {				i_data[EXT2_TIND_BLOCK] = 0;				mark_inode_dirty(inode);				ext2_free_branches(inode, &nr, &nr+1, 3);			}		case EXT2_TIND_BLOCK:			;	}	ext2_discard_reservation(inode);	mutex_unlock(&ei->truncate_mutex);	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;	if (inode_needs_sync(inode)) {		sync_mapping_buffers(inode->i_mapping);		ext2_sync_inode (inode);	} else {		mark_inode_dirty(inode);	}}static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino,					struct buffer_head **p){	struct buffer_head * bh;	unsigned long block_group;	unsigned long block;	unsigned long offset;	struct ext2_group_desc * gdp;	*p = NULL;	if ((ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb)) ||	    ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))		goto Einval;	block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);	gdp = ext2_get_group_desc(sb, block_group, NULL);	if (!gdp)		goto Egdp;	/*	 * Figure out the offset within the block group inode table	 */	offset = ((ino - 1) % EXT2_INODES_PER_GROUP(sb)) * EXT2_INODE_SIZE(sb);	block = le32_to_cpu(gdp->bg_inode_table) +		(offset >> EXT2_BLOCK_SIZE_BITS(sb));	if (!(bh = sb_bread(sb, block)))		goto Eio;	*p = bh;	offset &= (EXT2_BLOCK_SIZE(sb) - 1);	return (struct ext2_inode *) (bh->b_data + offset);Einval:	ext2_error(sb, "ext2_get_inode", "bad inode number: %lu",		   (unsigned long) ino);	return ERR_PTR(-EINVAL);Eio:	ext2_error(sb, "ext2_get_inode",		   "unable to read inode block - inode=%lu, block=%lu",		   (unsigned long) ino, block);Egdp:	return ERR_PTR(-EIO);}void ext2_set_inode_flags(struct inode *inode){	unsigned int flags = EXT2_I(inode)->i_flags;	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);	if (flags & EXT2_SYNC_FL)		inode->i_flags |= S_SYNC;	if (flags & EXT2_APPEND_FL)		inode->i_flags |= S_APPEND;	if (flags & EXT2_IMMUTABLE_FL)		inode->i_flags |= S_IMMUTABLE;	if (flags & EXT2_NOATIME_FL)		inode->i_flags |= S_NOATIME;	if (flags & EXT2_DIRSYNC_FL)		inode->i_flags |= S_DIRSYNC;}/* Propagate flags from i_flags to EXT2_I(inode)->i_flags */void ext2_get_inode_flags(struct ext2_inode_info *ei){	unsigned int flags = ei->vfs_inode.i_flags;	ei->i_flags &= ~(EXT2_SYNC_FL|EXT2_APPEND_FL|			EXT2_IMMUTABLE_FL|EXT2_NOATIME_FL|EXT2_DIRSYNC_FL);	if (flags & S_SYNC)		ei->i_flags |= EXT2_SYNC_FL;	if (flags & S_APPEND)		ei->i_flags |= EXT2_APPEND_FL;	if (flags & S_IMMUTABLE)		ei->i_flags |= EXT2_IMMUTABLE_FL;	if (flags & S_NOATIME)		ei->i_flags |= EXT2_NOATIME_FL;	if (flags & S_DIRSYNC)		ei->i_flags |= EXT2_DIRSYNC_FL;}void ext2_read_inode (struct inode * inode){	struct ext2_inode_info *ei = EXT2_I(inode);	ino_t ino = inode->i_ino;	struct buffer_head * bh;	struct ext2_inode * raw_inode = ext2_get_inode(inode->i_sb, ino, &bh);	int n;#ifdef CONFIG_EXT2_FS_POSIX_ACL	ei->i_acl = EXT2_ACL_NOT_CACHED;	ei->i_default_acl = EXT2_ACL_NOT_CACHED;#endif	ei->i_block_alloc_info = NULL;	if (IS_ERR(raw_inode)) 		goto bad_inode;	inode->i_mode = le16_to_cpu(raw_inode->i_mode);	inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);	inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);	if (!(test_opt (inode->i_sb, NO_UID32))) {		inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;		inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;	}	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);	inode->i_size = le32_to_cpu(raw_inode->i_size);	inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);	inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);	inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);	inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);	/* We now have enough fields to check if the inode was active or not.	 * This is needed because nfsd might try to access dead inodes	 * the test is that same one that e2fsck uses	 * NeilBrown 1999oct15	 */	if (inode->i_nlink == 0 && (inode->i_mode == 0 || ei->i_dtime)) {		/* this inode is deleted */		brelse (bh);		goto bad_inode;	}	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);	ei->i_flags = le32_to_cpu(raw_inode->i_flags);	ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);	ei->i_frag_no = raw_inode->i_frag;	ei->i_frag_size = raw_inode->i_fsize;	ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);	ei->i_dir_acl = 0;	if (S_ISREG(inode->i_mode))		inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;	else		ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);	ei->i_dtime = 0;	inode->i_generation = le32_to_cpu(raw_inode->i_generation);	ei->i_state = 0;	ei->i_block_group = (ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);	ei->i_dir_start_lookup = 0;	/*	 * NOTE! The in-memory inode i_data array is in little-endian order	 * even on big-endian machines: we do NOT byteswap the block numbers!	 */	for (n = 0; n < EXT2_N_BLOCKS; n++)		ei->i_data[n] = raw_inode->i_block[n];	if (S_ISREG(inode->i_mode)) {		inode->i_op = &ext2_file_inode_operations;		if (ext2_use_xip(inode->i_sb)) {			inode->i_mapping->a_ops = &ext2_aops_xip;			inode->i_fop = &ext2_xip_file_operations;		} else if (test_opt(inode->i_sb, NOBH)) {			inode->i_mapping->a_ops = &ext2_nobh_aops;			inode->i_fop = &ext2_file_operations;		} else {			inode->i_mapping->a_ops = &ext2_aops;			inode->i_fop = &ext2_file_operations;		}	} else if (S_ISDIR(inode->i_mode)) {		inode->i_op = &ext2_dir_inode_operations;		inode->i_fop = &ext2_dir_operations;		if (test_opt(inode->i_sb, NOBH))			inode->i_mapping->a_ops = &ext2_nobh_aops;		else			inode->i_mapping->a_ops = &ext2_aops;	} else if (S_ISLNK(inode->i_mode)) {		if (ext2_inode_is_fast_symlink(inode))			inode->i_op = &ext2_fast_symlink_inode_operations;		else {			inode->i_op = &ext2_symlink_inode_operations;			if (test_opt(inode->i_sb, NOBH))				inode->i_mapping->a_ops = &ext2_nobh_aops;			else				inode->i_mapping->a_ops = &ext2_aops;		}	} else {		inode->i_op = &ext2_special_inode_operations;		if (raw_inode->i_block[0])			init_special_inode(inode, inode->i_mode,			   old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));		else 			init_special_inode(inode, inode->i_mode,			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));	}	brelse (bh);	ext2_set_inode_flags(inode);	return;	bad_inode:	make_bad_inode(inode);	return;}static int ext2_update_inode(struct inode * inode, int do_sync){	struct ext2_inode_info *ei = EXT2_I(inode);	struct super_block *sb = inode->i_sb;	ino_t ino = inode->i_ino;	uid_t uid = inode->i_uid;	gid_t gid = inode->i_gid;	struct buffer_head * bh;	struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh);	int n;	int err = 0;	if (IS_ERR(raw_inode)) 		return -EIO;	/* For fields not not tracking in the in-memory inode,	 * initialise them to zero for new inodes. */	if (ei->i_state & EXT2_STATE_NEW)		memset(raw_inode, 0, EXT2_SB(sb)->s_inode_size);	ext2_get_inode_flags(ei);	raw_inode->i_mode = cpu_to_le16(inode->i_mode);	if (!(test_opt(sb, NO_UID32))) {		raw_inode->i_uid_low = cpu_to_le16(low_16_bits(uid));		raw_inode->i_gid_low = cpu_to_le16(low_16_bits(gid));/* * Fix up interoperability with old kernels. Otherwise, old inodes get * re-used with the upper 16 bits of the uid/gid intact */		if (!ei->i_dtime) {			raw_inode->i_uid_high = cpu_to_le16(high_16_bits(uid));			raw_inode->i_gid_high = cpu_to_le16(high_16_bits(gid));		} else {			raw_inode->i_uid_high = 0;			raw_inode->i_gid_high = 0;		}	} else {		raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(uid));		raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(gid));		raw_inode->i_uid_high = 0;		raw_inode->i_gid_high = 0;	}	raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);	raw_inode->i_size = cpu_to_le32(inode->i_size);	raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);	raw_inode->i_flags = cpu_to_le32(ei->i_flags);	raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);	raw_inode->i_frag = ei->i_frag_no;	raw_inode->i_fsize = ei->i_frag_size;	raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);	if (!S_ISREG(inode->i_mode))		raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);	else {		raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);		if (inode->i_size > 0x7fffffffULL) {			if (!EXT2_HAS_RO_COMPAT_FEATURE(sb,					EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ||			    EXT2_SB(sb)->s_es->s_rev_level ==					cpu_to_le32(EXT2_GOOD_OLD_REV)) {			       /* If this is the first large file				* created, add a flag to the superblock.				*/				lock_kernel();				ext2_update_dynamic_rev(sb);				EXT2_SET_RO_COMPAT_FEATURE(sb,					EXT2_FEATURE_RO_COMPAT_LARGE_FILE);				unlock_kernel();				ext2_write_super(sb);			}		}	}		raw_inode->i_generation = cpu_to_le32(inode->i_generation);	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {		if (old_valid_dev(inode->i_rdev)) {			raw_inode->i_block[0] =				cpu_to_le32(old_encode_dev(inode->i_rdev));			raw_inode->i_block[1] = 0;		} else {			raw_inode->i_block[0] = 0;			raw_inode->i_block[1] =				cpu_to_le32(new_encode_dev(inode->i_rdev));			raw_inode->i_block[2] = 0;		}	} else for (n = 0; n < EXT2_N_BLOCKS; n++)		raw_inode->i_block[n] = ei->i_data[n];	mark_buffer_dirty(bh);	if (do_sync) {		sync_dirty_buffer(bh);		if (buffer_req(bh) && !buffer_uptodate(bh)) {			printk ("IO error syncing ext2 inode [%s:%08lx]\n",				sb->s_id, (unsigned long) ino);			err = -EIO;		}	}	ei->i_state &= ~EXT2_STATE_NEW;	brelse (bh);	return err;}int ext2_write_inode(struct inode *inode, int wait){	return ext2_update_inode(inode, wait);}int ext2_sync_inode(struct inode *inode){	struct writeback_control wbc = {		.sync_mode = WB_SYNC_ALL,		.nr_to_write = 0,	/* sys_fsync did this */	};	return sync_inode(inode, &wbc);}int ext2_setattr(struct dentry *dentry, struct iattr *iattr){	struct inode *inode = dentry->d_inode;	int error;	error = inode_change_ok(inode, iattr);	if (error)		return error;	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||	    (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {		error = DQUOT_TRANSFER(inode, iattr) ? -EDQUOT : 0;		if (error)			return error;	}	error = inode_setattr(inode, iattr);	if (!error && (iattr->ia_valid & ATTR_MODE))		error = ext2_acl_chmod(inode);	return error;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -