Linux虚拟文件系统之文件系统安装(sys_mount())

对于这里的(http://www.linuxidc.com/Linux/2012-02/53845.htm)的根目录文件系统的安装中涉及到了mount系统调用的调用,这里我们考虑一个文件系统将被安装在一个已经安装文件系统之上的情形,即调用mount系统调用实现。mount系统调用被用来安装一个普通文件系统,他的服务例程为sys_mount()。 
[cpp]
  1. /*sys_mount系统调用*/  
  2. /*dev_name为待安装设备的路径名; 
  3. dir_name为安装点的路径名; 
  4. type是表示文件系统类型的字符串; 
  5. */  
  6. SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,  
  7.         char __user *, type, unsigned long, flags, void __user *, data)  
  8. {  
  9.     int ret;  
  10.     char *kernel_type;  
  11.     char *kernel_dir;  
  12.     char *kernel_dev;  
  13.     unsigned long data_page;  
  14.     /*从用户空间复制到系统空间*/  
  15.     ret = copy_mount_string(type, &kernel_type);  
  16.     if (ret < 0)  
  17.         goto out_type;  
  18.   
  19.     kernel_dir = getname(dir_name);  
  20.     if (IS_ERR(kernel_dir)) {  
  21.         ret = PTR_ERR(kernel_dir);  
  22.         goto out_dir;  
  23.     }  
  24.   
  25.     ret = copy_mount_string(dev_name, &kernel_dev);  
  26.     if (ret < 0)  
  27.         goto out_dev;  
  28.     /*用户空间复制到系统空间,拷贝整个页面*/  
  29.     ret = copy_mount_options(data, &data_page);  
  30.     if (ret < 0)  
  31.         goto out_data;  
  32.     /*操作主体*/  
  33.     ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,  
  34.         (void *) data_page);  
  35.   
  36.     free_page(data_page);  
  37. out_data:  
  38.     kfree(kernel_dev);  
  39. out_dev:  
  40.     putname(kernel_dir);  
  41. out_dir:  
  42.     kfree(kernel_type);  
  43. out_type:  
  44.     return ret;  
  45. }  
下面是主体实现
[cpp]
  1. long do_mount(char *dev_name, char *dir_name, char *type_page,  
  2.           unsigned long flags, void *data_page)  
  3. {  
  4.     struct path path;  
  5.     int retval = 0;  
  6.     int mnt_flags = 0;  
  7.   
  8.     /* Discard magic */  
  9.     if ((flags & MS_MGC_MSK) == MS_MGC_VAL)  
  10.         flags &= ~MS_MGC_MSK;  
  11.   
  12.     /* Basic sanity checks */  
  13.   
  14.     if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))  
  15.         return -EINVAL;  
  16.   
  17.     if (data_page)  
  18.         ((char *)data_page)[PAGE_SIZE - 1] = 0;  
  19.   
  20.     /* Default to relatime unless overriden */  
  21.     if (!(flags & MS_NOATIME))  
  22.         mnt_flags |= MNT_RELATIME;  
  23.   
  24.     /* Separate the per-mountpoint flags */  
  25.     if (flags & MS_NOSUID)  
  26.         mnt_flags |= MNT_NOSUID;  
  27.     if (flags & MS_NODEV)  
  28.         mnt_flags |= MNT_NODEV;  
  29.     if (flags & MS_NOEXEC)  
  30.         mnt_flags |= MNT_NOEXEC;  
  31.     if (flags & MS_NOATIME)  
  32.         mnt_flags |= MNT_NOATIME;  
  33.     if (flags & MS_NODIRATIME)  
  34.         mnt_flags |= MNT_NODIRATIME;  
  35.     if (flags & MS_STRICTATIME)  
  36.         mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);  
  37.     if (flags & MS_RDONLY)  
  38.         mnt_flags |= MNT_READONLY;  
  39.   
  40.     flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |  
  41.            MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |  
  42.            MS_STRICTATIME);  
  43.   
  44.     /* ... and get the mountpoint */  
  45.     /*获得安装点path结构*/  
  46.     retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);  
  47.     if (retval)  
  48.         return retval;  
  49.       
  50.     retval = security_sb_mount(dev_name, &path,  
  51.                    type_page, flags, data_page);  
  52.     if (retval)  
  53.         goto dput_out;  
  54.   
  55.     if (flags & MS_REMOUNT)  
  56.         /*修改已经存在的文件系统参数,即改变超级块对象s_flags 
  57.     字段的安装标志*/  
  58.         retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,  
  59.                     data_page);  
  60.     else if (flags & MS_BIND)  
  61.             /*要求在系统目录树的另一个安装点上得文件或目录能够可见*/  
  62.         retval = do_loopback(&path, dev_name, flags & MS_REC);  
  63.     else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))  
  64.         /*is responsible for handling shared, slave, and unbindable mounts by changing 
  65.         the mount flags or building up the required data structure connections  
  66.         between the vfsmount 
  67.         instances involved.*/  
  68.         retval = do_change_type(&path, flags);  
  69.     else if (flags & MS_MOVE)  
  70.         /*改变已安装文件的安装点*/  
  71.             /*used to move a mounted filesystem*/  
  72.         retval = do_move_mount(&path, dev_name);  
  73.     else  
  74.         /*handles normal mount operations. This is the default situation, so no special  
  75.         flags 
  76.         are required*/  
  77.         /*当用户要求安装一个特殊文件系统或存放在磁盘分区 
  78.         中的普通文件系统时,调用*/  
  79.         retval = do_new_mount(&path, type_page, flags, mnt_flags,  
  80.                       dev_name, data_page);  
  81. dput_out:  
  82.     path_put(&path);  
  83.     return retval;  
  84. }  

相关推荐