普通文件系统安装流程

asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,

                              char __user * type, unsigned long flags, void __user * data);

参数说明:

1.  文件系统所在的设备文件的路径名,或者如果不需要则为NULL(如网络文件系统);

2.  文件系统被安装其上的某个目录的路径名,即安装点;

3.  文件系统类型,必须是已注册的文件系统;

4.  安装标志(如只读MS_RDONLY, 不允许程序执行MS_NOEXEC);

5.  指向一个与文件系统相关的数据结构的指针;

 

sysmount的工作:

1.       把参数的值拷贝到临时的内核缓冲区(copy_mount_option,申请页,拷贝数据);

retval = copy_mount_options(type, &type_page);  //文件系统类型

dir_page = getname(dir_name);                 //安装点路径

retval = copy_mount_options(dev_name, &dev_page); //设备名

retval = copy_mount_options(data, &data_page);      //其它相关的数据

2.       获取大内核锁,并调用do_mount

lock_kernel();

         retval = do_mount((char *)dev_page, dir_page, (char *)type_page, flags, (void *)data_page);

         unlock_kernel();

 

+-----------------------------------------------------------------------------------------------------------------------------+

 

long do_mount(char *dev_name, char *dir_name, char *type_page,

                     unsigned long flags, void *data_page);

参数说明:

分别为设备名的地址,路径名地址,文件系统类型地址,挂载标志,额外数据;

 

do_mount的工作:

1.       将挂载标志转换为安装文件系统的标志,以MNT_开头的;

如:if (flags & MS_NOSUID)

mnt_flags |= MNT_NOSUID;

2.       调用path_lookup查找安装点的路径名,将结果存放在nameidata类型的局部变量中;

retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);

3 检查安装标志已决定做什么:

MS_REMOUNT标志被指定,则执行do_remount

MS_MOVE标志指定,则要求改变已安装文件系统的安装点,执行do_move_mount

……

调用do_new_mount安装新的文件系统,其先后调用do_kern_mountdo_add_mount

其中do_add_mount将新安装文件系统插入到namespace链表中,不作详细分析。

 

if (flags & MS_REMOUNT)

                   retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,

                                         data_page);

         else if (flags & MS_BIND)

                   retval = do_loopback(&nd, dev_name, flags & MS_REC);

         else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))

                   retval = do_change_type(&nd, flags);

         else if (flags & MS_MOVE)

                   retval = do_move_mount(&nd, dev_name);

         else

                   retval = do_new_mount(&nd, type_page, flags, mnt_flags,

                                           dev_name, data_page);

+-----------------------------------------------------------------------------------------------------------------------------+

 

struct vfsmount *

do_kern_mount(const char *fstype, int flags, const char *name, void *data)

{

         struct file_system_type *type = get_fs_type(fstype);

         struct vfsmount *mnt;

         if (!type)

                   return ERR_PTR(-ENODEV);

         mnt = vfs_kern_mount(type, flags, name, data);

         put_filesystem(type);

         return mnt;

}

 

参数说明:

do_kern_mount接受文件系统类型,安装标志,设备名,额外数据等参数,其处理实际的安装操作并返回一个新安装文件系统描述符的地址;

 

do_kern_mount的工作:

1.  调用get_fs_type在文件系统类型链表中搜索,返回对应file_system_type描述符的地址;

struct file_system_type *type = get_fs_type(fstype);

2.  调用alloc_vfsmnt分配一个新的已安装文件系统的描述符,存放在局部变量mnt中;

mnt = alloc_vfsmnt(name);

3.  调用依赖于文件系统的type->get_sb函数分配,并初始化一个新的超级块;

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

4.  初始化mntmnt_sbmnt_root等字段;

mnt->mnt_mountpoint = mnt->mnt_root;

mnt->mnt_parent = mnt;

5.  返回mnt的地址;

 

+-----------------------------------------------------------------------------------------------------------------------------+

static int ext2_get_sb(struct file_system_type *fs_type,

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

{

         return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt);

}

get_sb_bdev函数分配并初始化一个新的适合于磁盘文件系统的超级块,它接受ext2_fill_super函数的地址,该函数从ext2磁盘分区读取磁盘超级块。

 

VFS还提供get_sb_pseudo(针对没有安装点的文件系统,如pipefs)get_sb_single(对于具有唯一安装点的函数,如sysfs),get_sb_nodev(对于可安装多次的特殊文件系统,如tmpfs)等函数以用于不同的文件系统。

 

get_sb_bdev的工作:

1.调用open_bdev_excl打开设备文件名为dev_name的块设备;

bdev = open_bdev_excl(dev_name, flags, fs_type);

2. 调用sget搜索文件系统的超级块链表(type->fs_supers)。如果找到一个与块设备相关的超级块,则返回它的地址;否则分配一个新的超级块,把它插入到文件系统链表和超级块全局链表,并返回其地址;

mutex_lock(&bdev->bd_mount_mutex);

s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);

mutex_unlock(&bdev->bd_mount_mutex);

3.如果超级块已经存在,则直接返回;否则如果为新建的,则填充新超级块的s_flagss_blocksize等信息;

s->s_flags = flags;

strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));

sb_set_blocksize(s, block_size(bdev));

4.调用依赖具体文件系统的函数访问磁盘上的超级块信息,并填充超级块的其他信息,最后返回超级块对象的地址;

error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);


posted @ 2013-04-19 14:07  ydzhang  阅读(436)  评论(0编辑  收藏  举报