📄 inode.c
字号:
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; } /*组描述符在组描述表中的块号=块组号/每块中组描述符数, *每个组描述符是32字节大小,在一个1KB大小的块中可存储32个组描述符, *每个块用一个组描述符表示, *因为组描述符已读入buffer中形成组描述表s_group_desc[]数组, *组描述表是以buffer为数组元素的, *每个buffer大小为一个数据块, *所以需要确定组描述符在组描述表的那一块 *以及是该块中的第几组描述符 */ group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb); /*组描述符具体是该块中第几个描述符 * =组号对每块中组描述符作相与运算 */ desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1); /*通过s_group_desc[]数组找到这个组描述符所在块在高速缓存中的缓冲区首部*/ 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; } /*通过缓冲区首部找到数据区,找到组描述符后, *就可以通过组描述符结构中的bg_inode_table *找到索引节点表首块在高速缓存中的地址 */ 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和offset就可以找到索引节点了 */ block = le32_to_cpu(gdp[desc].bg_inode_table) + (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)); if (!(bh = sb_bread(inode->i_sb, block))) { 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); /*从该节点raw_inode中读出信息填充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 = 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); /* 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 || inode->u.ext2_i.i_dtime)) { /* this inode is deleted */ brelse (bh);/*释放块在高速缓存中的缓冲区首部*/ goto bad_inode; } 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_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_file_acl = le32_to_cpu(raw_inode->i_file_acl); if (S_ISREG(inode->i_mode)) inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32; else inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); inode->i_generation = le32_to_cpu(raw_inode->i_generation); inode->u.ext2_i.i_prealloc_count = 0; inode->u.ext2_i.i_block_group = block_group; /* * 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 (block = 0; block < EXT2_N_BLOCKS; block++) inode->u.ext2_i.i_data[block] = raw_inode->i_block[block]; /*赋上操作函数集实例*/ 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; inode->i_fop = &ext2_file_operations; inode->i_mapping->a_ops = &ext2_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ext2_dir_inode_operations; inode->i_fop = &ext2_dir_operations; inode->i_mapping->a_ops = &ext2_aops; } else if (S_ISLNK(inode->i_mode)) { if (!inode->i_blocks) inode->i_op = &ext2_fast_symlink_inode_operations; else { inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &ext2_aops; } } else init_special_inode(inode, inode->i_mode, le32_to_cpu(raw_inode->i_block[0])); brelse (bh);/*释放块在高速缓存中的缓冲区首部*/ /*节点属性设置*/ 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 |= S_SYNC; } 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 |= S_NOATIME; } return; bad_inode: make_bad_inode(inode);/*由于I/O错误,标记inode已损坏*/ /*make_bad_inode - mark an inode bad due to an I/O error*/ 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; /*inode合法性检查*/ 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); /*通过s_group_desc[]数组找到这个组描述符所在块在高速缓存中的缓冲区首部*/ 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; } /*得到描述符所在的buffer*/ 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 = sb_bread(inode->i_sb, block))) { 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); /*用inode填写row_inode*/ raw_inode->i_mode = cpu_to_le16(inode->i_mode); if(!(test_opt(inode->i_sb, NO_UID32))) { raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));/* * Fix up interoperability with old kernels. Otherwise, old inodes get * re-used with the upper 16 bits of the uid/gid intact */ if(!inode->u.ext2_i.i_dtime) { raw_inode->i_uid_high = cpu_to_le16(high_16_bits(inode->i_uid)); raw_inode->i_gid_high = cpu_to_le16(high_16_bits(inode->i_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(inode->i_uid)); raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(inode->i_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); 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 { raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32); if (inode->i_size > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; 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)) raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); else for (block = 0; block < EXT2_N_BLOCKS; block++) raw_inode->i_block[block] = inode->u.ext2_i.i_data[block]; mark_buffer_dirty(bh); if (do_sync) { /*发出设备写请求*/ ll_rw_block (WRITE, 1, &bh); /*在等待队列上等待buffer写入设备*/ wait_on_buffer (bh); /*将buffer设置成req和uptodate状态*/ 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;}/*将inode结构中数据写入到硬盘*/void ext2_write_inode (struct inode * inode, int wait){ lock_kernel();/*给内核上锁*/ ext2_update_inode (inode, wait);/*调用更新inode的函数*/ unlock_kernel();/*给内核解锁*/}/*把节点缓存中数据写入设备*/int ext2_sync_inode (struct inode *inode){ return ext2_update_inode (inode, 1);/*调用更新inode的函数*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -