您的位置:首页 > 其它

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

2012-02-22 20:47 567 查看
浅析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_type sysfs_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( struct file_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) 

        return ERR_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) 

            goto out_mnt; 

        error = security_sb_copy_data( data, secdata) ; 

        if ( error ) 

            goto out_free_secdata; 

    } 
//调用文件系统控制结构体的get_sb()方法,获取文件系统的超级块,这里就是sysfs_get_sb. 

    error = type- > get_sb( type, flags, name, data, mnt) ; 

    if ( error < 0) 

        goto out_free_secdata; 

    BUG_ON( ! mnt- > mnt_sb) ; 

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

     if ( error ) 

         goto out_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( struct file_system_type * fs_type, 

    int flags, const char * dev_name, void * data, struct vfsmount * mnt) 
{ 

    return get_sb_single( fs_type, flags, data, sysfs_fill_super, mnt) ; 
} 

int get_sb_single( struct file_system_type * fs_type, 

    int flags, void * data, 

    int ( * fill_super) ( struct super_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) ) 

        return PTR_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) ; //asks
filesystem to change mount options,在sysfs中sysfs_ops没有实现remount_fs
    return simple_set_mnt( mnt, s) ; //将s超级块安装到mnt这个mount节点上
} 
int simple_set_mnt( struct vfsmount * mnt, struct super_block * sb) 
{ 

    mnt- > mnt_sb = sb; //mnt的sb
    mnt- > mnt_root = dget( sb- > s_root) ; //对应的根目录项
    return 0; 
} 
static int compare_single( struct super_block * s, void * p) 
{ 

    return 1; 
} 
struct super_block * sget( struct file_system_type * type, 

            int ( * test ) ( struct super_block * , void * ) , 

            int ( * set ) ( struct super_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) 

            return ERR_PTR( - ENOMEM) ; 

        goto retry; //继续尝试一次,看看是否重复了
    } 

        

    err = set ( s, data) ; //sysfs对应set_anon_super,获取一个sb超级块的设备号,major为0
    if ( err) { 

        spin_unlock( & sb_lock) ; 

        destroy_super( s) ; 

        return ERR_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( struct super_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( struct file_system_type * type) 
{ 

    struct super_block * s = kzalloc( sizeof ( struct super_block) , GFP_USER) ; 

    static struct super_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( struct super_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 and lost 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( struct super_block * sb, void * data, int silent) 
{ 

    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 unlock it */ 

    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( struct sysfs_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( struct sysfs_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_operations sysfs_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 must come 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_dirent has 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 ; 

    case SYSFS_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 void set_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( struct super_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() will do the right thing, re-trying the search

     * in case it had to block at any point.

     */ 

    return get_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, struct hlist_head * head,unsigned long ino) 
{ 

    struct inode * inode; 

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

        struct inode * old; 

        spin_lock( & inode_lock) ; //锁住
        /* We released the 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 struct super_operations sysfs_ops = { 

    . statfs = simple_statfs, 

    . drop_inode = generic_delete_inode, 
} ; 

sb- > s_op = & sysfs_ops; //超级块操作函数集
static struct inode * alloc_inode( struct super_block * sb) 
{ 

    static const struct address_space_operations empty_aops; 

    static struct inode_operations empty_iops; 

    static const struct file_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的部分结单元
        struct address_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) { 

            struct backing_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 qstr name = { . 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( struct dentry * 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) ; 
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息