linux 2.6.32文件系统的inode
接上文:
crash> struct -xo dentry.d_inode ffff8818118002c0 struct dentry { [ffff8818118002d0] struct inode *d_inode; } crash> struct dentry.d_inode ffff8818118002c0 d_inode = 0xffff880c11402cf8 crash> struct inode 0xffff880c11402cf8 struct inode { i_hash = { next = 0x0, pprev = 0xffffc900093d9118 }, i_list = { next = 0xffff880c11401ae8, prev = 0xffff880c11b9bda8 }, i_sb_list = { next = 0xffff880c1188ccd0,------------inode的i_sb_list串起来,形成一个双向循环链表,其链表头可以认为是该inode对应的super_block的s_inodes成员的地址 prev = 0xffff880c11402a98 }, i_dentry = { next = 0xffff881811800330, prev = 0xffff881811800330 }, i_ino = 1, i_count = { counter = 1 }, i_nlink = 2, i_uid = 0, i_gid = 0, i_rdev = 0, i_version = 0, i_size = 0, i_atime = { tv_sec = 1533672031, tv_nsec = 74999849 }, i_mtime = { tv_sec = 1533672031, tv_nsec = 74999849 }, i_ctime = { tv_sec = 1533672031, tv_nsec = 74999849 }, i_blocks = 0, i_blkbits = 10, i_bytes = 0, i_mode = 16749, i_lock = { raw_lock = { slock = 877474893 } }, i_mutex = { count = { counter = 1 }, wait_lock = { raw_lock = { slock = 2655755851 } }, wait_list = { next = 0xffff880c11402db8, prev = 0xffff880c11402db8 }, owner = 0x0 }, i_alloc_sem = { count = 0, wait_lock = { raw_lock = { slock = 0 } }, wait_list = { next = 0xffff880c11402de0, prev = 0xffff880c11402de0 } }, i_op = 0xffffffff8161fb40 <proc_reg_file_ops+192>, i_fop = 0xffffffff8161fc00 <proc_root_inode_operations+160>, i_sb = 0xffff880c1188cc00, i_flock = 0x0, i_mapping = 0xffff880c11402e18, i_data = { host = 0xffff880c11402cf8,-----------------------address_space的host是指向inode,而inode的i_data是指向对应的address_space,两者就串起来了。 page_tree = {--------------------radix树,主要管理page的 height = 0, gfp_mask = 32, rnode = 0x0 }, tree_lock = {-----------------树锁 raw_lock = { slock = 0 } }, i_mmap_writable = 0, i_mmap = { prio_tree_node = 0x0, index_bits = 1, raw = 1 }, i_mmap_nonlinear = { next = 0xffff880c11402e48, prev = 0xffff880c11402e48 }, i_mmap_lock = { raw_lock = { slock = 0 } }, truncate_count = 0, nrpages = 0, writeback_index = 0, a_ops = 0xffffffff81fcfde0 <empty_aops.36032>, flags = 131290, backing_dev_info = 0xffffffff81abfb80 <default_backing_dev_info>, private_lock = { raw_lock = { slock = 0 } }, private_list = { next = 0xffff880c11402e90, prev = 0xffff880c11402e90 }, assoc_mapping = 0x0 }, i_dquot = {0x0, 0x0}, i_devices = { next = 0xffff880c11402eb8, prev = 0xffff880c11402eb8 }, {---------------------------这个是inode的类型描述,一个inode要么是字符设备,要么是块设备,要么是pipe设备,要么都不是 i_pipe = 0x0, i_bdev = 0x0, i_cdev = 0x0 }, i_generation = 0, i_fsnotify_mask = 0, i_fsnotify_mark_entries = { first = 0x0 }, inotify_watches = { next = 0xffff880c11402ee0, prev = 0xffff880c11402ee0 }, inotify_mutex = { count = { counter = 1 }, wait_lock = { raw_lock = { slock = 0 } }, wait_list = { next = 0xffff880c11402ef8, prev = 0xffff880c11402ef8 }, owner = 0x0 }, i_state = 0, dirtied_when = 0, i_flags = 0, i_writecount = { counter = 0 }, i_security = 0x0, i_acl = 0xffffffffffffffff, i_default_acl = 0xffffffffffffffff, i_private = 0x0 }
每个inode对于所属的文件系统来说,是唯一的。比如有两个硬盘,都是xfs分别挂载到两个挂载点,那么对应的这个文件系统里,inode的内存地址也是唯一的,但是可以和其他文件系统中的i_ino成员可能会相同。
inode和对应的super_block 怎么对应起来呢,inode的i_sb_list串起来,形成一个双向循环链表,其链表头可以认为是该inode对应的super_block的s_inodes成员的地址,我们验证一下:
crash> struct inode 0xffff880c11402cf8 struct inode { i_hash = { next = 0x0, pprev = 0xffffc900093d9118 }, i_list = { next = 0xffff880c11401ae8, prev = 0xffff880c11b9bda8 }, i_sb_list = { next = 0xffff880c1188ccd0,--------对应的地址是ccd0 prev = 0xffff880c11402a98 },
可以看到,该inode对应的i_sb_list是ccd0,而该inode归属的super_block是0xffff880c1188cc00,
crash> struct -xo super_block.s_inodes struct super_block { [0xd0] struct list_head s_inodes; } crash> px 0xffff880c1188cc00+0xd0 $2 = 0xffff880c1188ccd0
两者对得上,是不是很面熟,前面我们看dentry的时候,所有子dentry的d_child成员就形成双向循环链表,嵌入到父dentry的d_subdirs中,内核中类似手法很多。
前面文章描述过dentry,但是看inode中,有一个dentry链表,这个是为啥?难道两者不是一一对应关系么?
事实上,两者真不是一一对应,一个inode可能有多个dentry:
crash> struct inode 0xffff880c11402cf8 struct inode { i_hash = { next = 0x0, pprev = 0xffffc900093d9118 }, i_list = { next = 0xffff880c11401ae8, prev = 0xffff880c11b9bda8 }, i_sb_list = { next = 0xffff880c1188ccd0, prev = 0xffff880c11402a98 }, i_dentry = { next = 0xffff881811800330, prev = 0xffff881811800330 }, crash> struct -xo dentry.d_alias struct dentry { [0x70] struct list_head d_alias; } crash> px 0xffff881811800330-0x70 $3 = 0xffff8818118002c0 crash> struct dentry 0xffff8818118002c0 struct dentry { d_count = { counter = 725 }, d_flags = 16, d_lock = { raw_lock = { slock = 797912975 } }, d_mounted = 0, d_inode = 0xffff880c11402cf8, d_hash = { next = 0x0, pprev = 0x0 }, d_parent = 0xffff8818118002c0, d_name = { hash = 0, len = 1, name = 0xffff881811800360 "/" },
对于本例中的根目录来说,一个inode只有一个dentry,但是对于硬链接来说,则肯定有多个dentry,所以inode和dentry是1对多的关系。
又同时可以看到,dentry中的d_alias串起来一个双向循环链表,而这个双向循环链表遍历的时候,可以认为这些dentry对应的inode的 i_dentry 是这个双向循环链表的头。
其实inode还有个很关键常用的成员,就是i_list,根据不同的inode状态,会放入不同的list,但是由于这个成员在3.10内核中已经被i_lru和i_wb_list 来代替了,这个两个成员都会嵌入到
该inode所属的superblock的s_inode_lru 以及i_wb_list中。所以就不放在本文中分析了。
最后,通过files -d dentry的地址 ,可以显示对应的inode和superblock,-p的话,还可以展示在pagecache中的page:
crash> files -d ffff8857a2440b40 DENTRY INODE SUPERBLK TYPE PATH ffff8857a2440b40 ffff88535be752b0 ffff88013d3a8800 REG /mnt/ZMSS/ZMSSThreadMonitor.log crash> files -p ffff88535be752b0 INODE NRPAGES ffff88535be752b0 1 PAGE PHYSICAL MAPPING INDEX CNT FLAGS ffffea0121bbd840 486ef61000 ffff88535be75400 0 1 6fffff000c0038 uptodate,dirty,lru,reclaim,swapbacked