浅析proc文件系统的创建和create_proc_read_entry函数的具体实现

浅析kern_mount加载sysfs的流程

   因为sysfs是一个内存文件系统, 所以文件的物理存储关系就需要使用sd来维护, 因此sysfs_dirent即sd就类似于硬盘中的磁道.
   sysfs文件系统是一个排它式的文件系统,不论被mount多少次都只产生一个sb超级块,
如果尝试再次mount,即尝试再次调用sysfs_get_sb获取另一个sb超级块,那么将执行atomic_inc(old->s_active);增加
已被mount的引用计数,然后如果s已经执行了alloc_super,那么调用destroy_super将其销毁,然后返回这个已被mount了的
super_block超级块old,这样就实现了sysfs文件系统不论被mount多少次都只产生一个sb超级块的效果,所以取名为get_sb_single[luther.gliethttp]


start_kernel
= > vfs_caches_init
= > mnt_init
= > sysfs_init
sysfs_mount = kern_mount( &sysfs_fs_type) ;
static struct file_system_typesysfs_fs_type = {
    . name = "sysfs" ,
    . get_sb =sysfs_get_sb,
    . kill_sb =kill_anon_super,
} ;
# define kern_mount( type)kern_mount_data( type, NULL )
# define MS_KERNMOUNT ( 1< < 22) /*this is a kern_mount call */
struct vfsmount * kern_mount_data( structfile_system_type * type, void * data)
{
    return vfs_kern_mount( type,MS_KERNMOUNT, type- > name, data) ;
}
struct vfsmount *
vfs_kern_mount( struct file_system_type * type, int flags, const char * name, void * data)
{
    struct vfsmount * mnt;
    char *secdata = NULL ;
    int error ;

    if ( ! type)
        returnERR_PTR( - ENODEV) ;

    error = -ENOMEM;
    mnt = alloc_vfsmnt( name) ; //获取一个mnt结构体,并做一些初始化工作
    if ( ! mnt)
        goto out;

    if ( data & & ! ( type- >fs_flags & FS_BINARY_MOUNTDATA) ) {
        secdata =alloc_secdata( ) ;
        if ( !secdata)
            gotoout_mnt;

        error =security_sb_copy_data( data,secdata) ;
        if ( error )
            gotoout_free_secdata;
    }
//调用文件系统控制结构体的get_sb()方法,获取文件系统的超级块,这里就是sysfs_get_sb.
    error = type- >get_sb( type, flags, name, data, mnt) ;
    if ( error < 0)
        gotoout_free_secdata;
    BUG_ON( ! mnt- >mnt_sb) ;

     error =security_sb_kern_mount( mnt- >mnt_sb, secdata) ;
     if ( error )
         gotoout_sb;

    mnt- >mnt_mountpoint = mnt- >mnt_root; //mount点就是sysfs的'/'根目录项
    mnt- >mnt_parent = mnt; //指向自己
    up_write( & mnt- >mnt_sb- > s_umount) ;
    free_secdata(secdata) ;
    return mnt; //成功完成mnt的创建和sb超级块等信息的填充[luther.gliethttp]
out_sb:
    dput( mnt- >mnt_root) ;
    up_write( & mnt- >mnt_sb- > s_umount) ;
    deactivate_super( mnt- >mnt_sb) ;
out_free_secdata:
    free_secdata(secdata) ;
out_mnt:
    free_vfsmnt( mnt) ;
out:
    return ERR_PTR( error ) ;
}
struct vfsmount * alloc_vfsmnt( const char * name)
{
    struct vfsmount * mnt =kmem_cache_zalloc( mnt_cache,GFP_KERNEL) ; //从cache上摘一个slab空闲对象
    if ( mnt) {
//成功获取mnt内存空间,初始化之[luther.gliethttp]
        atomic_set( & mnt- >mnt_count, 1) ;
        INIT_LIST_HEAD( & mnt- >mnt_hash) ;
        INIT_LIST_HEAD( & mnt- >mnt_child) ;
        INIT_LIST_HEAD( & mnt- >mnt_mounts) ;
        INIT_LIST_HEAD( & mnt- >mnt_list) ;
        INIT_LIST_HEAD( & mnt- >mnt_expire) ;
        INIT_LIST_HEAD( & mnt- >mnt_share) ;
        INIT_LIST_HEAD( & mnt- >mnt_slave_list) ;
        INIT_LIST_HEAD( & mnt- >mnt_slave) ;
        if ( name) {
            int size = strlen ( name) + 1;
            char *newname = kmalloc( size,GFP_KERNEL) ;
            if (newname) {
                memcpy (newname, name, size) ;
                mnt- >mnt_devname = newname; //比如: "sysfs"
            }
        }
    }
    return mnt;
}
//sysfs文件系统是一个排它式的文件系统,不论被mount多少次都只产生一个sb超级块,
//如果尝试再次mount,即尝试再次调用sysfs_get_sb获取另一个sb超级块,那么将执行atomic_inc(old->s_active);增加
//已被mount的引用计数,然后如果s已经执行了alloc_super,那么调用destroy_super将其销毁,然后返回这个已被mount了的
//super_block超级块old, 这样就实现了sysfs文件系统 不论被mount多少次都只产生一个sb超级块的效果 ,所以取名为get_sb_single[luther.gliethttp]
static int sysfs_get_sb( structfile_system_type * fs_type,
    int flags, const char *dev_name, void * data, structvfsmount * mnt)
{
    return get_sb_single(fs_type, flags, data,sysfs_fill_super, mnt) ;
}

int get_sb_single( structfile_system_type * fs_type,
    int flags, void * data,
    int ( *fill_super) ( structsuper_block * , void * , int ) ,
    struct vfsmount * mnt)
{
    struct super_block * s;
    int error ;

    s = sget(fs_type, compare_single,set_anon_super, NULL ) ; //获取超级块,如果之前已经创建了sb,那么这里将不再创建,将返回上一次创建的sb,所以这表明sb超级块将只被生成1个 [luther.gliethttp]
    if ( IS_ERR( s) )
        returnPTR_ERR( s) ;
    if ( ! s- >s_root) {
//如果是第一次mount该sysfs文件系统,那么首先填充sb超级块
        s- >s_flags = flags;
        error =fill_super( s, data, flags& MS_SILENT ? 1 : 0) ; //这里对应sysfs_fill_super函数,细化sb超级块
        if ( error ) {
            up_write( & s- >s_umount) ;
            deactivate_super( s) ;
            return error ;
        }
        s- >s_flags | = MS_ACTIVE;
    }
    do_remount_sb( s, flags, data, 0) ; //asksfilesystem to change mount options,在sysfs中sysfs_ops没有实现remount_fs
    return simple_set_mnt( mnt, s) ; //将s超级块安装到mnt这个mount节点上
}
int simple_set_mnt( structvfsmount * mnt, structsuper_block * sb)
{
    mnt- >mnt_sb = sb; //mnt的sb
    mnt- >mnt_root = dget( sb- >s_root) ; //对应的根目录项
    return 0;
}
static int compare_single( structsuper_block * s, void * p)
{
    return 1;
}
struct super_block * sget( structfile_system_type * type,
            int ( * test ) ( structsuper_block * , void * ) ,
            int ( * set ) ( structsuper_block * , void * ) ,
            void * data)
{
    struct super_block * s = NULL ;
    struct super_block * old;
    int err;

retry:
    spin_lock( &sb_lock) ;
    if ( test ) {
        list_for_each_entry( old, & type- >fs_supers, s_instances) {
//sysfs文件系统是一个排它式的文件系统, 不论被mount多少次都只产生一个sb超级块,
//如果尝试再次mount,即尝试再次调用sysfs_get_sb获取另一个sb超级块,那么将执行atomic_inc(old->s_active);增加
//已被mount的引用计数,然后如果s已经执行了alloc_super,那么调用destroy_super将其销毁,然后返回这个已被mount了的
//super_block超级块old, 这样就实现了sysfs文件系统 不论被mount多少次都只产生一个sb超级块的效果 ,所以取名为get_sb_single[luther.gliethttp]
            if ( ! test ( old, data) ) //compare_single一直返回1
               continue ;
            if ( !grab_super( old) )
                goto retry;
            if ( s)
                destroy_super( s) ;
            return old;
        }
    }
    if ( ! s) {
//没有找到
        spin_unlock( &sb_lock) ;
        s =alloc_super( type) ; //获取一个sb超级块的控制内存,同时做部分结构初始化
        if ( ! s)
            returnERR_PTR( - ENOMEM) ;
        goto retry; //继续尝试一次,看看是否重复了
    }
        
    err = set ( s, data) ; //sysfs对应set_anon_super,获取一个sb超级块的设备号,major为0
    if ( err) {
        spin_unlock( &sb_lock) ;
        destroy_super( s) ;
        returnERR_PTR( err) ;
    }
    s- >s_type = type; //填充该sb超级块的type
    strlcpy( s- > s_id, type- > name, sizeof ( s- > s_id) ) ; //该sb超级块的s_id为type->name,比如:"sysfs"
    list_add_tail( & s- >s_list, & super_blocks) ; //将该超级块添加到全局超级块链表super_blocks
    list_add( & s- >s_instances, & type- >fs_supers) ; //sb超级块将自己添加到type->fs_supers管理链表上
    spin_unlock( &sb_lock) ;
    get_filesystem( type) ; //
    return s;
}
//type->fs_supers链表上挂上了有效的sb超级块之后,才会执行到这里
static int grab_super( structsuper_block * s)__releases( sb_lock)
{
    s- >s_count+ + ; / /alloc_super时将设置 s->s_count = S_BIAS;
    spin_unlock( &sb_lock) ;
    down_write( & s- >s_umount) ;
    if ( s- >s_root) {
        spin_lock( &sb_lock) ;
        if ( s- >s_count > S_BIAS) {
            atomic_inc( & s- >s_active) ;
            s- >s_count- - ;
            spin_unlock( &sb_lock) ;
            return 1; //确实有一个有效的sb超级块对应的s_root目录项,那么返回1,然后由destroy_super将其销毁
        }
        spin_unlock( &sb_lock) ;
    }
    up_write( & s- >s_umount) ;
    put_super( s) ;
    yield( ) ;
    return 0;
}
//获取一个sb超级块的控制内存,同时做部分结构初始化
static struct super_block * alloc_super( structfile_system_type * type)
{
    struct super_block * s =kzalloc( sizeof ( structsuper_block) , GFP_USER) ;
    static structsuper_operations default_op;

    if ( s) {
        if (security_sb_alloc( s) ) {
            kfree( s) ;
            s = NULL ;
            goto out;
        }
        INIT_LIST_HEAD( & s- >s_dirty) ;
        INIT_LIST_HEAD( & s- > s_io) ;
        INIT_LIST_HEAD( & s- >s_more_io) ;
        INIT_LIST_HEAD( & s- >s_files) ;
        INIT_LIST_HEAD( & s- >s_instances) ;
        INIT_HLIST_HEAD( & s- >s_anon) ;
        INIT_LIST_HEAD( & s- >s_inodes) ;
        init_rwsem( & s- >s_umount) ;
        mutex_init( & s- >s_lock) ;
        lockdep_set_class( & s- >s_umount, & type- >s_umount_key) ;
        /*
         *The locking rules for s_lock are up to the
         *filesystem. For example ext3fs has different
         *lock ordering than usbfs:
         */
        lockdep_set_class( & s- >s_lock, & type- >s_lock_key) ;
        down_write( & s- >s_umount) ;
        s- >s_count = S_BIAS;
        atomic_set( & s- >s_active, 1) ;
        mutex_init( & s- >s_vfs_rename_mutex) ;
        mutex_init( & s- >s_dquot. dqio_mutex) ;
        mutex_init( & s- >s_dquot. dqonoff_mutex) ;
        init_rwsem( & s- >s_dquot. dqptr_sem) ;
        init_waitqueue_head( & s- >s_wait_unfrozen) ;
        s- >s_maxbytes = MAX_NON_LFS;
        s- > dq_op= sb_dquot_ops;
        s- >s_qcop = sb_quotactl_ops;
        s- > s_op = &default_op;
        s- >s_time_gran = 1000000000;
    }
out:
    return s;
}
int set_anon_super( structsuper_block * s, void * data)
{
    int dev;
    int error ;

 retry:
    if ( idr_pre_get( &unnamed_dev_idr, GFP_ATOMIC) = = 0)
        return -ENOMEM;
    spin_lock( &unnamed_dev_lock) ;
    error =idr_get_new( & unnamed_dev_idr, NULL , & dev) ; //从radix树中,递增式的获取一个唯一整数值到&dev
    spin_unlock( &unnamed_dev_lock) ;
    if ( error = = -EAGAIN)
        /* We raced andlost with another CPU. */
        goto retry;
    else if ( error )
        return -EAGAIN;

    if ( ( dev &MAX_ID_MASK) = = ( 1 < <MINORBITS) ) {
        spin_lock( &unnamed_dev_lock) ;
        idr_remove( &unnamed_dev_idr, dev) ;
        spin_unlock( &unnamed_dev_lock) ;
        return -EMFILE;
    }
    s- > s_dev= MKDEV( 0, dev &MINORMASK) ; //生成major为0的超级块设备号
    return 0;
}
//给申请的sb超级块填充细化数据
static int sysfs_fill_super( structsuper_block * sb, void * data, intsilent)
{
    struct inode * inode;
    struct dentry * root;

    sb- >s_blocksize = PAGE_CACHE_SIZE; //块大小4k
    sb- >s_blocksize_bits = PAGE_CACHE_SHIFT; //12
    sb- >s_magic = SYSFS_MAGIC; //magic代号
    sb- > s_op = &sysfs_ops; //超级块操作函数集
    sb- >s_time_gran = 1;
    sysfs_sb = sb; //保存

    /* get root inode, initialize and unlockit */
    inode = sysfs_get_inode( &sysfs_root) ; //生成sysfs_root中所定义要求的inode内存节点
    if ( ! inode) {
        pr_debug( "sysfs:could not get root inode/n" ) ;
        return -ENOMEM;
    }

    /* instantiate and link root dentry */
    root = d_alloc_root( inode) ; //将inode安装到'/'根目录项上
    if ( ! root) {
        pr_debug( "%s:could not get root dentry!/n" , __FUNCTION__ ) ;
        iput( inode) ;
        return -ENOMEM;
    }
    root- >d_fsdata = & sysfs_root; //根目录项的文件系统数据fsdata指向sysfs_root
    sb- >s_root = root; //填充sb超级块对应的根目录项
    return 0;
}
struct sysfs_dirent sysfs_root = {
    . s_name = "" , //0
    . s_count =ATOMIC_INIT( 1) ,
    . s_flags =SYSFS_DIR, //目录
    . s_mode =S_IFDIR | S_IRWXU |S_IRUGO | S_IXUGO,
    . s_ino = 1, //节点号搞为1
} ;
struct inode * sysfs_get_inode( structsysfs_dirent * sd)
{
    struct inode * inode;

    inode = iget_locked(sysfs_sb, sd- > s_ino) ;
    if ( inode & & ( inode- >i_state & I_NEW) )
        sysfs_init_inode( sd, inode) ; //这是一个新创建的inode节点,那么调用sysfs对它进一步做符合sysfs要求的初始化[luther.gliethttp]

    return inode;
}
//对新创建的inode节点,进行sysfs特性格式化[luther.gliethttp]
static void sysfs_init_inode( structsysfs_dirent * sd, struct inode* inode)
{
    struct bin_attribute *bin_attr;

    inode- >i_blocks = 0;
    inode- >i_mapping- > a_ops = &sysfs_aops;
    inode- >i_mapping- > backing_dev_info = &sysfs_backing_dev_info;
    inode- > i_op = &sysfs_inode_operations; //更改inode的方法集
/*
static const struct inode_operationssysfs_inode_operations ={
    .setattr = sysfs_setattr,
};
*/
    inode- > i_ino= sd- > s_ino; //inode的节点号要和sd->s_ino目录项节点号一致
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
自此
sysfs_fill_super= >sysfs_sb = sb; //保存

sysfs_create_dir
= > parent_sd = &sysfs_root;
sysfs_addrm_start
inode = ilookup5_nowait(sysfs_sb, parent_sd- > s_ino,sysfs_ilookup_test, parent_sd) ;
= > 就能够找到sysfs_root对应的inode节点了, 所以
start_kernel
= > vfs_caches_init
= > mnt_init
= > sysfs_init执行完之后,driver们也就能够在稍后的时候顺利使用sysfs文件系统进行文件创建了.

start_kernel
= > rest_init
= > kernel_thread(kernel_init, NULL ,CLONE_FS | CLONE_SIGHAND) ;
kernel_init
= > do_basic_setup
= > driver_init会创建如下:
/ sys/devices
/ sys/ bus
/ sys/ class
/ sys/firmware
等sysfs目录和文件
然后do_basic_setup继续调用
= > do_initcalls
调用所有build in到kernel中的module_init驱动程序,
所以这时的驱动程序就可以自由使用sysfs以及上面创建的那些sysfs文件系统下的目录和文件了[luther. gliethttp]
void __init driver_init( void )
{
    /* These are the core pieces */
    devices_init( ) ;
    buses_init( ) ;
    classes_init( ) ;
    firmware_init( ) ;
    hypervisor_init( ) ;

    /* These are also core pieces, but mustcome after the
     * core core pieces.
     */
    platform_bus_init( ) ;
    system_bus_init( ) ;
    cpu_dev_init( ) ;
    memory_dev_init( ) ;
}
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    lockdep_set_class( & inode- >i_mutex, & sysfs_inode_imutex_key) ;

    if ( sd- >s_iattr) {
        /* sysfs_direnthas non-default attributes
         *get them for the new inode from persistent copy
         *in sysfs_dirent
         */
        set_inode_attr( inode, sd- >s_iattr) ;
    } else
        set_default_inode_attr( inode, sd- >s_mode) ; //设备inode默认attr属性们


    /* initialize inode according to type */
    switch (sysfs_type( sd) ) { //根据sd目录项信息,来反向订制该inode节点的fops等操作函数集[luther.gliethttp]
    case SYSFS_DIR:
        inode- > i_op = &sysfs_dir_inode_operations;
        inode- > i_fop= &sysfs_dir_operations; //dir目录的fops操作函数集
        inode- >i_nlink = sysfs_count_nlink( sd) ;
        break ;
    case SYSFS_KOBJ_ATTR:
        inode- >i_size = PAGE_SIZE;
        inode- > i_fop= &sysfs_file_operations; //attr属性文件的fops操作函数集
        break ;
    caseSYSFS_KOBJ_BIN_ATTR:
        bin_attr = sd- >s_bin_attr. bin_attr; //bin_attr属性文件的fops操作函数集
        inode- >i_size = bin_attr- > size;
        inode- > i_fop= & bin_fops;
        break ;
    case SYSFS_KOBJ_LINK:
        inode- > i_op = &sysfs_symlink_inode_operations; //link文件的fops操作函数集
        break ;
    default :
        BUG( ) ;
    }

    unlock_new_inode( inode) ;
}
static inline voidset_default_inode_attr( struct inode* inode,mode_t mode)
{
    inode- >i_mode = mode;
    inode- > i_uid= 0;
    inode- > i_gid= 0;
    inode- >i_atime = inode- >i_mtime = inode- >i_ctime = CURRENT_TIME;
}
struct inode * iget_locked( structsuper_block * sb, unsigned long ino)
{
    struct hlist_head * head =inode_hashtable + hash( sb, ino) ;
    struct inode * inode;

    inode = ifind_fast( sb, head, ino) ;
    if ( inode) //第一次的话,肯定inode=NULL;
        return inode;
    /*
     * get_new_inode_fast() willdo the right thing, re-trying the search
     * in case it had to blockat any point.
     */
    returnget_new_inode_fast( sb, head, ino) ; //为root获取一个inode存储结构体,对于sysfs就是获取一个内存空间
    //对于ext3和yaffs2文件系统就是申请flash或者硬盘上的物理空间了[luther.gliethttp].
}
static struct inode *get_new_inode_fast( struct super_block * sb, structhlist_head * head, unsigned long ino)
{
    struct inode * inode;

    inode = alloc_inode( sb) ; //从sb超级块上获取一个新的inode
    if ( inode) {
        struct inode* old;

        spin_lock( &inode_lock) ; //锁住
        /* We releasedthe lock, so.. */
        old =find_inode_fast( sb, head, ino) ; //可能他人已经创建完成了,所以再查一遍
        if ( ! old) {
//确实ino节点号仍然没有被创建,那么我们可以安全的将inode作为ino节点号对应的inode了[luther.gliethttp]
            inode- > i_ino= ino; //节点对应的节点号
           inodes_stat. nr_inodes+ + ;
            list_add( & inode- >i_list, & inode_in_use) ; //挂到全局量inode_in_use链表上
           list_add( & inode- >i_sb_list, & sb- >s_inodes) ; //挂到超级块的s_inodes链表上
           hlist_add_head( & inode- >i_hash, head) ; //将inode添加到所有节点都挂接到的hash数组inode_hashtable中.
            inode- >i_state = I_LOCK| I_NEW; //标记该inode为新建节点
           spin_unlock( & inode_lock) ; //解锁

            /*Return the locked inode with I_NEW set, the
             *caller is responsible for filling in the contents
             */
            return inode; //返回这个新生成的inode节点
        }

        /*
         *Uhhuh, somebody else created the same inode under
         *us. Use the old inode instead of the one we just
         *allocated.
         */
//很不走运,该ino对应的inode节点别人已经在你上边某一步时,提前搞定了,所以我们需要把刚才申请的咚咚释放掉[luther.gliethttp]
        __iget( old) ;
        spin_unlock( &inode_lock) ;
        destroy_inode( inode) ; //销毁前面申请的inode节点,因为别人已经成功添加了.
        inode = old;
        wait_on_inode( inode) ;
    }
    return inode; //inode=NULL
}
static const structsuper_operations sysfs_ops = {
    . statfs =simple_statfs,
    . drop_inode =generic_delete_inode,
} ;
sb- > s_op = &sysfs_ops; //超级块操作函数集
static struct inode * alloc_inode( structsuper_block * sb)
{
    static const structaddress_space_operations empty_aops;
    static structinode_operations empty_iops;
    static const structfile_operations empty_fops;
    struct inode * inode;

    if ( sb- > s_op- > alloc_inode) //该sb超级块提供自定义,特殊的alloc_inode函数,对于sysfs没有提供专门的函数[luther.gliethttp]
        inode = sb- > s_op- >alloc_inode( sb) ;
    else
        inode = ( struct inode* ) kmem_cache_alloc(inode_cachep, GFP_KERNEL) ; //所以从cache中获取一个空闲染色的slab对象

    if ( inode) {
//细化inode的部分结单元
        structaddress_space * const mapping = & inode- >i_data;

        inode- > i_sb = sb;
        inode- >i_blkbits = sb- >s_blocksize_bits;
        inode- >i_flags = 0;
        atomic_set( & inode- >i_count, 1) ;
        inode- > i_op = &empty_iops;
        inode- > i_fop= & empty_fops;
        inode- >i_nlink = 1;
        atomic_set( & inode- >i_writecount, 0) ;
        inode- >i_size = 0;
        inode- >i_blocks = 0;
        inode- >i_bytes = 0;
        inode- >i_generation = 0;
# ifdef CONFIG_QUOTA
        memset ( & inode- >i_dquot, 0, sizeof ( inode- >i_dquot) ) ;
# endif
        inode- >i_pipe = NULL ;
        inode- >i_bdev = NULL ;
        inode- >i_cdev = NULL ;
        inode- > i_rdev= 0;
        inode- >dirtied_when = 0;
        if (security_inode_alloc( inode) ) {
            if ( inode- > i_sb- > s_op- >destroy_inode)
                inode- > i_sb- > s_op- >destroy_inode( inode) ;
            else
                kmem_cache_free(inode_cachep, ( inode) ) ;
            return NULL ;
        }

        spin_lock_init( & inode- >i_lock) ;
        lockdep_set_class( & inode- >i_lock, & sb- >s_type- > i_lock_key) ;

        mutex_init( & inode- >i_mutex) ;
        lockdep_set_class( & inode- >i_mutex, & sb- >s_type- > i_mutex_key) ;

        init_rwsem( & inode- >i_alloc_sem) ;
        lockdep_set_class( & inode- >i_alloc_sem, & sb- >s_type- > i_alloc_sem_key) ;

        mapping- > a_ops= & empty_aops;
         mapping- > host = inode;
        mapping- > flags= 0;
        mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE) ;
        mapping- >assoc_mapping = NULL ;
        mapping- >backing_dev_info = &default_backing_dev_info;

        /*
         *If the block_device provides a backing_dev_info for client
         *inodes then use that. Otherwise the inode share the bdev's
         *backing_dev_info.
         */
        if ( sb- >s_bdev) {
            structbacking_dev_info * bdi;

            bdi= sb- >s_bdev- >bd_inode_backing_dev_info;
            if ( ! bdi)
                bdi= sb- >s_bdev- > bd_inode- >i_mapping- > backing_dev_info;
            mapping- >backing_dev_info = bdi;
        }
        inode- >i_private = NULL ;
        inode- >i_mapping = mapping;
    }
    return inode;
}

struct dentry * d_alloc_root( struct inode* root_inode)
{
    struct dentry * res = NULL ;

    if ( root_inode) {
        static const struct qstrname = { . name = "/" , . len = 1 } ;

        res =d_alloc( NULL , & name) ; //申请一个根目录项,调用dentry = kmem_cache_alloc(dentry_cache,GFP_KERNEL);
        if ( res) {
            res- > d_sb =root_inode- > i_sb; //根目录项的超级块
            res- >d_parent = res; //自己指向自己
            d_instantiate( res,root_inode) ; //将inode安装到根目录项上
        }
    }
    return res;
}
void d_instantiate( structdentry * entry, struct inode* inode)
{
    BUG_ON( !list_empty( & entry- >d_alias) ) ;
    spin_lock( &dcache_lock) ;
    if ( inode)
        list_add( & entry- >d_alias, & inode- >i_dentry) ; //将目录向链接到inode上,所以一个inode可以有多个目录项指向,
    //这些目录项可以通过扫描inode->i_dentry链表获得
    entry- >d_inode = inode; //目录项对应的所管理的inode节点
    fsnotify_d_instantiate( entry, inode) ;
    spin_unlock( &dcache_lock) ;
    security_d_instantiate( entry, inode) ;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值