VFS四大struct:file、dentry、inode、super_block


VFS四大struct:file、dentry、inode、super_block

dentry

dentry有什么作用?dentry保存了目录/文件到inode的映射,在open一个文件时,如果路径上的某个目录或者最后的文件没有对应的dentry,则会为其建立dentry并插入dentry hashtable,dentry里的d_inode成员保存了该目录文件/文件的indoe指针。这样后面如果在lookup这个目录/文件时就可以根据目录/文件的hash值/name等找到对应的dentry,找到了对应的dentry后,则就知道了这个目录文件/文件的inode struct,就不用再进入文件系统层面去lookup这个目录/文件了,如果是进入到文件系统层面去lookup了,会去读目录文件lookup,而这个涉及到读IO,比较耗时。

dentry其实是包含路径含义的,比如说某个目录/文件的dentry,这里说的目录/文件是需要有其完整的路径的,比如/data/test/foo目录,/data/test/foo/bar.txt文件,因为dentry的hash值是根据其父目录的dentry和目录名/文件名两者计算出来的。

  • d_name: qstr struct,里面存储了此dentry的hash值,此hash值用于在dentry hashtable上查找匹配;里面的name成员指向d_iname成员数组
  • d_parent:此dentry的parent dentry
  • d_iname: 保存的目录或者文件的名字,这个名字不包含路径,这个数组的大小是32(CONFIG_64BIT defined case)
struct dentry {
    /* RCU lookup touched fields */
    unsigned int d_flags;        /* protected by d_lock */
    seqcount_t d_seq;        /* per dentry seqlock */
    struct hlist_bl_node d_hash;    /* lookup hash list */
    struct dentry *d_parent;    /* parent directory */
    struct qstr d_name;
    struct inode *d_inode;        /* Where the name belongs to - NULL is
                     * negative */
    unsigned char d_iname[DNAME_INLINE_LEN];    /* small names */

    /* Ref lookup also touches following */
    struct lockref d_lockref;    /* per-dentry lock and refcount */
    const struct dentry_operations *d_op;
    struct super_block *d_sb;    /* The root of the dentry tree */
    unsigned long d_time;        /* used by d_revalidate */
    void *d_fsdata;            /* fs-specific data */

    union {
        struct list_head d_lru;        /* LRU list */
        wait_queue_head_t *d_wait;    /* in-lookup ones only */
    };
    struct list_head d_child;    /* child of parent list */
    struct list_head d_subdirs;    /* our children */
    /*
     * d_alias and d_rcu can share memory
     */
    union {
        struct hlist_node d_alias;    /* inode alias list */
        struct hlist_bl_node d_in_lookup_hash;    /* only for in-lookup ones */
         struct rcu_head d_rcu;
    } d_u;
} __randomize_layout;

file struct

表示一个file

  • f_path: 一个path结构体,这个path结构体里保存了这个文件的dentry,根据dentry又可以得到inode struct。path结构体里还有file所在的文件系统对应的vfs_mount struct;
  • f_op:很重要的成员,read/write等系统调用就是根据这个file_operations来调用具体文件系统的file_operations函数;
struct file {
    union {
        struct llist_node    fu_llist;
        struct rcu_head     fu_rcuhead;
    } f_u;
    struct path        f_path;
    struct inode        *f_inode;    /* cached value */
    const struct file_operations    *f_op;

    /*
     * Protects f_ep_links, f_flags.
     * Must not be taken from IRQ context.
     */
    spinlock_t        f_lock;
    enum rw_hint        f_write_hint;
    atomic_long_t        f_count;
    unsigned int         f_flags;
    fmode_t            f_mode;
    struct mutex        f_pos_lock;
    loff_t            f_pos;
    struct fown_struct    f_owner;
    const struct cred    *f_cred;
    struct file_ra_state    f_ra;

    u64            f_version;
#ifdef CONFIG_SECURITY
    void            *f_security;
#endif
    /* needed for tty driver, and maybe others */
    void            *private_data;

#ifdef CONFIG_EPOLL
    /* Used by fs/eventpoll.c to link all the hooks to this file */
    struct list_head    f_ep_links;
    struct list_head    f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
    struct address_space    *f_mapping;
    errseq_t        f_wb_err;
} __randomize_layout
  __attribute__((aligned(4)));    /* lest something weird decides that 2 is OK */

struct inode

文件目录都会有inode(目录也是一种文件,目录文件里的内容是其子目录/文件名及其inode number)

  • i_fop,这个成员将会被赋值给file struct f_op成员,成为file struct里的file_operations函数集;
  • i_ino,file inode number
struct inode {
    umode_t            i_mode;
    unsigned short        i_opflags;
    kuid_t            i_uid;
    kgid_t            i_gid;
    unsigned int        i_flags;

#ifdef CONFIG_FS_POSIX_ACL
    struct posix_acl    *i_acl;
    struct posix_acl    *i_default_acl;
#endif

    const struct inode_operations    *i_op;
    struct super_block    *i_sb;
    struct address_space    *i_mapping;

#ifdef CONFIG_SECURITY
    void            *i_security;
#endif

    /* Stat data, not accessed from path walking */
    unsigned long        i_ino;
    /*
     * Filesystems may only read i_nlink directly.  They shall use the
     * following functions for modification:
     *
     *    (set|clear|inc|drop)_nlink
     *    inode_(inc|dec)_link_count
     */
    union {
        const unsigned int i_nlink;
        unsigned int __i_nlink;
    };
    dev_t            i_rdev;
    loff_t            i_size;
    struct timespec64    i_atime;
    struct timespec64    i_mtime;
    struct timespec64    i_ctime;
    spinlock_t        i_lock;    /* i_blocks, i_bytes, maybe i_size */
    unsigned short          i_bytes;
    u8            i_blkbits;
    u8            i_write_hint;
    blkcnt_t        i_blocks;

#ifdef __NEED_I_SIZE_ORDERED
    seqcount_t        i_size_seqcount;
#endif

    /* Misc */
    unsigned long        i_state;
    struct rw_semaphore    i_rwsem;

    unsigned long        dirtied_when;    /* jiffies of first dirtying */
    unsigned long        dirtied_time_when;

    struct hlist_node    i_hash;
    struct list_head    i_io_list;    /* backing dev IO list */
#ifdef CONFIG_CGROUP_WRITEBACK
    struct bdi_writeback    *i_wb;        /* the associated cgroup wb */

    /* foreign inode detection, see wbc_detach_inode() */
    int            i_wb_frn_winner;
    u16            i_wb_frn_avg_time;
    u16            i_wb_frn_history;
#endif
    struct list_head    i_lru;        /* inode LRU list */
    struct list_head    i_sb_list;
    struct list_head    i_wb_list;    /* backing dev writeback list */
    union {
        struct hlist_head    i_dentry;
        struct rcu_head        i_rcu;
    };
    atomic64_t        i_version;
    atomic64_t        i_sequence; /* see futex */
    atomic_t        i_count;
    atomic_t        i_dio_count;
    atomic_t        i_writecount;
#ifdef CONFIG_IMA
    atomic_t        i_readcount; /* struct files open RO */
#endif
    const struct file_operations    *i_fop;    /* former ->i_op->default_file_ops */
    struct file_lock_context    *i_flctx;
    struct address_space    i_data;
    struct list_head    i_devices;
    union {
        struct pipe_inode_info    *i_pipe;
        struct block_device    *i_bdev;
        struct cdev        *i_cdev;
        char            *i_link;
        unsigned        i_dir_seq;
    };

    __u32            i_generation;

#ifdef CONFIG_FSNOTIFY
    __u32            i_fsnotify_mask; /* all events this inode cares about */
    struct fsnotify_mark_connector __rcu    *i_fsnotify_marks;
#endif

#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
    struct fscrypt_info    *i_crypt_info;
#endif

    void            *i_private; /* fs or device private pointer */
} __randomize_layout;
fs