inode.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 796 行 · 第 1/2 页

C
796
字号
			   create, inode->i_sb->s_blocksize, b, err);	return block_getblk (inode, bh, block & (addr_per_block - 1), create,			     inode->i_sb->s_blocksize, b, err);}struct buffer_head * ext2_bread (struct inode * inode, int block, 				 int create, int *err){	struct buffer_head * bh;	int prev_blocks;		prev_blocks = inode->i_blocks;		bh = ext2_getblk (inode, block, create, err);	if (!bh)		return bh;		/*	 * If the inode has grown, and this is a directory, then perform	 * preallocation of a few more blocks to try to keep directory	 * fragmentation down.	 */	if (create && 	    S_ISDIR(inode->i_mode) && 	    inode->i_blocks > prev_blocks &&	    EXT2_HAS_COMPAT_FEATURE(inode->i_sb,				    EXT2_FEATURE_COMPAT_DIR_PREALLOC)) {		int i;		struct buffer_head *tmp_bh;				for (i = 1;		     i < EXT2_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;		     i++) {			/* 			 * ext2_getblk will zero out the contents of the			 * directory for us			 */			tmp_bh = ext2_getblk(inode, block+i, create, err);			if (!tmp_bh) {				brelse (bh);				return 0;			}			brelse (tmp_bh);		}	}		if (buffer_uptodate(bh))		return bh;	ll_rw_block (READ, 1, &bh);	wait_on_buffer (bh);	if (buffer_uptodate(bh))		return bh;	brelse (bh);	*err = -EIO;	return NULL;}void ext2_read_inode (struct inode * inode){	struct buffer_head * bh;	struct ext2_inode * raw_inode;	unsigned long block_group;	unsigned long group_desc;	unsigned long desc;	unsigned long block;	unsigned long offset;	struct ext2_group_desc * gdp;	if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&	     inode->i_ino != EXT2_ACL_DATA_INO &&	     inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||	    inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {		ext2_error (inode->i_sb, "ext2_read_inode",			    "bad inode number: %lu", inode->i_ino);		goto bad_inode;	}	block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);	if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {		ext2_error (inode->i_sb, "ext2_read_inode",			    "group >= groups count");		goto bad_inode;	}	group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);	desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);	bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];	if (!bh) {		ext2_error (inode->i_sb, "ext2_read_inode",			    "Descriptor not loaded");		goto bad_inode;	}	gdp = (struct ext2_group_desc *) bh->b_data;	/*	 * Figure out the offset within the block group inode table	 */	offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) *		EXT2_INODE_SIZE(inode->i_sb);	block = le32_to_cpu(gdp[desc].bg_inode_table) +		(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {		ext2_error (inode->i_sb, "ext2_read_inode",			    "unable to read inode block - "			    "inode=%lu, block=%lu", inode->i_ino, block);		goto bad_inode;	}	offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);	raw_inode = (struct ext2_inode *) (bh->b_data + offset);	inode->i_mode = le16_to_cpu(raw_inode->i_mode);	inode->i_uid = le16_to_cpu(raw_inode->i_uid);	inode->i_gid = le16_to_cpu(raw_inode->i_gid);	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);	inode->i_size = le32_to_cpu(raw_inode->i_size);	inode->i_atime = le32_to_cpu(raw_inode->i_atime);	inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);	inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);	inode->u.ext2_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);	inode->i_version = ++event;	inode->u.ext2_i.i_new_inode = 0;	inode->u.ext2_i.i_flags = le32_to_cpu(raw_inode->i_flags);	inode->u.ext2_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);	inode->u.ext2_i.i_frag_no = raw_inode->i_frag;	inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;	inode->u.ext2_i.i_osync = 0;	inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);	if (S_ISDIR(inode->i_mode))		inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);	else {		inode->u.ext2_i.i_dir_acl = 0;		inode->u.ext2_i.i_high_size =			le32_to_cpu(raw_inode->i_size_high);#if BITS_PER_LONG < 64		if (raw_inode->i_size_high)			inode->i_size = (__u32)-1;#else		inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high))			<< 32;#endif	}	inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version);	inode->u.ext2_i.i_block_group = block_group;	inode->u.ext2_i.i_next_alloc_block = 0;	inode->u.ext2_i.i_next_alloc_goal = 0;	if (inode->u.ext2_i.i_prealloc_count)		ext2_error (inode->i_sb, "ext2_read_inode",			    "New inode has non-zero prealloc count!");	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))		inode->i_rdev = to_kdev_t(le32_to_cpu(raw_inode->i_block[0]));	else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)		for (block = 0; block < EXT2_N_BLOCKS; block++)			inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];	else for (block = 0; block < EXT2_N_BLOCKS; block++)		inode->u.ext2_i.i_data[block] = le32_to_cpu(raw_inode->i_block[block]);	brelse (bh);	inode->i_op = NULL;	if (inode->i_ino == EXT2_ACL_IDX_INO ||	    inode->i_ino == EXT2_ACL_DATA_INO)		/* Nothing to do */ ;	else if (S_ISREG(inode->i_mode))		inode->i_op = &ext2_file_inode_operations;	else if (S_ISDIR(inode->i_mode))		inode->i_op = &ext2_dir_inode_operations;	else if (S_ISLNK(inode->i_mode))		inode->i_op = &ext2_symlink_inode_operations;	else if (S_ISCHR(inode->i_mode))		inode->i_op = &chrdev_inode_operations;	else if (S_ISBLK(inode->i_mode))		inode->i_op = &blkdev_inode_operations;	else if (S_ISFIFO(inode->i_mode))		init_fifo(inode);	inode->i_attr_flags = 0;	if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {		inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS;		inode->i_flags |= MS_SYNCHRONOUS;	}	if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) {		inode->i_attr_flags |= ATTR_FLAG_APPEND;		inode->i_flags |= S_APPEND;	}	if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) {		inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;		inode->i_flags |= S_IMMUTABLE;	}	if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) {		inode->i_attr_flags |= ATTR_FLAG_NOATIME;		inode->i_flags |= MS_NOATIME;	}	return;	bad_inode:	make_bad_inode(inode);	return;}static int ext2_update_inode(struct inode * inode, int do_sync){	struct buffer_head * bh;	struct ext2_inode * raw_inode;	unsigned long block_group;	unsigned long group_desc;	unsigned long desc;	unsigned long block;	unsigned long offset;	int err = 0;	struct ext2_group_desc * gdp;	if ((inode->i_ino != EXT2_ROOT_INO &&	     inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||	    inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {		ext2_error (inode->i_sb, "ext2_write_inode",			    "bad inode number: %lu", inode->i_ino);		return -EIO;	}	block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);	if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {		ext2_error (inode->i_sb, "ext2_write_inode",			    "group >= groups count");		return -EIO;	}	group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);	desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);	bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];	if (!bh) {		ext2_error (inode->i_sb, "ext2_write_inode",			    "Descriptor not loaded");		return -EIO;	}	gdp = (struct ext2_group_desc *) bh->b_data;	/*	 * Figure out the offset within the block group inode table	 */	offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) *		EXT2_INODE_SIZE(inode->i_sb);	block = le32_to_cpu(gdp[desc].bg_inode_table) +		(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {		ext2_error (inode->i_sb, "ext2_write_inode",			    "unable to read inode block - "			    "inode=%lu, block=%lu", inode->i_ino, block);		return -EIO;	}	offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1;	raw_inode = (struct ext2_inode *) (bh->b_data + offset);	raw_inode->i_mode = cpu_to_le16(inode->i_mode);	raw_inode->i_uid = cpu_to_le16(inode->i_uid);	raw_inode->i_gid = cpu_to_le16(inode->i_gid);	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);	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);	raw_inode->i_dtime = cpu_to_le32(inode->u.ext2_i.i_dtime);	raw_inode->i_flags = cpu_to_le32(inode->u.ext2_i.i_flags);	raw_inode->i_faddr = cpu_to_le32(inode->u.ext2_i.i_faddr);	raw_inode->i_frag = inode->u.ext2_i.i_frag_no;	raw_inode->i_fsize = inode->u.ext2_i.i_frag_size;	raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl);	if (S_ISDIR(inode->i_mode))		raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);	else { #if BITS_PER_LONG < 64		raw_inode->i_size_high =			cpu_to_le32(inode->u.ext2_i.i_high_size);#else		raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);#endif	}	raw_inode->i_version = cpu_to_le32(inode->u.ext2_i.i_version);	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))		raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));	else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)		for (block = 0; block < EXT2_N_BLOCKS; block++)			raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];	else for (block = 0; block < EXT2_N_BLOCKS; block++)		raw_inode->i_block[block] = cpu_to_le32(inode->u.ext2_i.i_data[block]);	mark_buffer_dirty(bh, 1);	if (do_sync) {		ll_rw_block (WRITE, 1, &bh);		wait_on_buffer (bh);		if (buffer_req(bh) && !buffer_uptodate(bh)) {			printk ("IO error syncing ext2 inode ["				"%s:%08lx]\n",				bdevname(inode->i_dev), inode->i_ino);			err = -EIO;		}	}	brelse (bh);	return err;}void ext2_write_inode (struct inode * inode){	ext2_update_inode (inode, 0);}int ext2_sync_inode (struct inode *inode){	return ext2_update_inode (inode, 1);}int ext2_notify_change(struct dentry *dentry, struct iattr *iattr){	struct inode *inode = dentry->d_inode;	int		retval;	unsigned int	flags;		retval = -EPERM;	if (iattr->ia_valid & ATTR_ATTR_FLAG)	{	     if((!(iattr->ia_attr_flags & ATTR_FLAG_APPEND) !=	      !(inode->u.ext2_i.i_flags & EXT2_APPEND_FL)) ||	      (!(iattr->ia_attr_flags & ATTR_FLAG_IMMUTABLE) !=	      !(inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL))) {		if (!capable(CAP_LINUX_IMMUTABLE))			goto out;	     }	     else if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))		goto out;	}	if (iattr->ia_valid & ATTR_SIZE) {		off_t size = iattr->ia_size;		unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;		if (size < 0)			return -EINVAL;#if BITS_PER_LONG == 64			if (size > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])			return -EFBIG;#endif		if (limit < RLIM_INFINITY && size > limit) {			send_sig(SIGXFSZ, current, 0);			return -EFBIG;		}#if BITS_PER_LONG == 64			if (size >> 33) {			struct super_block *sb = inode->i_sb;			struct ext2_super_block *es = sb->u.ext2_sb.s_es;			if (!(es->s_feature_ro_compat &			      cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))){				/* If this is the first large file				 * created, add a flag to the superblock */				es->s_feature_ro_compat |=				cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);				mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);			}		}#endif	}		retval = inode_change_ok(inode, iattr);	if (retval != 0)		goto out;	inode_setattr(inode, iattr);		if (iattr->ia_valid & ATTR_ATTR_FLAG) {		flags = iattr->ia_attr_flags;		if (flags & ATTR_FLAG_SYNCRONOUS) {			inode->i_flags |= MS_SYNCHRONOUS;			inode->u.ext2_i.i_flags = EXT2_SYNC_FL;		} else {			inode->i_flags &= ~MS_SYNCHRONOUS;			inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL;		}		if (flags & ATTR_FLAG_NOATIME) {			inode->i_flags |= MS_NOATIME;			inode->u.ext2_i.i_flags = EXT2_NOATIME_FL;		} else {			inode->i_flags &= ~MS_NOATIME;			inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL;		}		if (flags & ATTR_FLAG_APPEND) {			inode->i_flags |= S_APPEND;			inode->u.ext2_i.i_flags = EXT2_APPEND_FL;		} else {			inode->i_flags &= ~S_APPEND;			inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL;		}		if (flags & ATTR_FLAG_IMMUTABLE) {			inode->i_flags |= S_IMMUTABLE;			inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL;		} else {			inode->i_flags &= ~S_IMMUTABLE;			inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;		}	}	mark_inode_dirty(inode);out:	return retval;}

⌨️ 快捷键说明

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