對於這裡的(http://www.linuxidc.com/Linux/2012-02/53845.htm)的根目錄文件系統的安裝中涉及到了mount系統調用的調用,這裡我們考慮一個文件系統將被安裝在一個已經安裝文件系統之上的情形,即調用mount系統調用實現。mount系統調用被用來安裝一個普通文件系統,他的服務例程為sys_mount()。
[cpp]
- /*sys_mount系統調用*/
- /*dev_name為待安裝設備的路徑名;
- dir_name為安裝點的路徑名;
- type是表示文件系統類型的字符串;
- */
- SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
- char __user *, type, unsigned long, flags, void __user *, data)
- {
- int ret;
- char *kernel_type;
- char *kernel_dir;
- char *kernel_dev;
- unsigned long data_page;
- /*從用戶空間復制到系統空間*/
- ret = copy_mount_string(type, &kernel_type);
- if (ret < 0)
- goto out_type;
-
- kernel_dir = getname(dir_name);
- if (IS_ERR(kernel_dir)) {
- ret = PTR_ERR(kernel_dir);
- goto out_dir;
- }
-
- ret = copy_mount_string(dev_name, &kernel_dev);
- if (ret < 0)
- goto out_dev;
- /*用戶空間復制到系統空間,拷貝整個頁面*/
- ret = copy_mount_options(data, &data_page);
- if (ret < 0)
- goto out_data;
- /*操作主體*/
- ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
- (void *) data_page);
-
- free_page(data_page);
- out_data:
- kfree(kernel_dev);
- out_dev:
- putname(kernel_dir);
- out_dir:
- kfree(kernel_type);
- out_type:
- return ret;
- }
下面是主體實現
[cpp]
- long do_mount(char *dev_name, char *dir_name, char *type_page,
- unsigned long flags, void *data_page)
- {
- struct path path;
- int retval = 0;
- int mnt_flags = 0;
-
- /* Discard magic */
- if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
- flags &= ~MS_MGC_MSK;
-
- /* Basic sanity checks */
-
- if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
- return -EINVAL;
-
- if (data_page)
- ((char *)data_page)[PAGE_SIZE - 1] = 0;
-
- /* Default to relatime unless overriden */
- if (!(flags & MS_NOATIME))
- mnt_flags |= MNT_RELATIME;
-
- /* Separate the per-mountpoint flags */
- if (flags & MS_NOSUID)
- mnt_flags |= MNT_NOSUID;
- if (flags & MS_NODEV)
- mnt_flags |= MNT_NODEV;
- if (flags & MS_NOEXEC)
- mnt_flags |= MNT_NOEXEC;
- if (flags & MS_NOATIME)
- mnt_flags |= MNT_NOATIME;
- if (flags & MS_NODIRATIME)
- mnt_flags |= MNT_NODIRATIME;
- if (flags & MS_STRICTATIME)
- mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
- if (flags & MS_RDONLY)
- mnt_flags |= MNT_READONLY;
-
- flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
- MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
- MS_STRICTATIME);
-
- /* ... and get the mountpoint */
- /*獲得安裝點path結構*/
- retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
- if (retval)
- return retval;
-
- retval = security_sb_mount(dev_name, &path,
- type_page, flags, data_page);
- if (retval)
- goto dput_out;
-
- if (flags & MS_REMOUNT)
- /*修改已經存在的文件系統參數,即改變超級塊對象s_flags
- 字段的安裝標志*/
- retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
- data_page);
- else if (flags & MS_BIND)
- /*要求在系統目錄樹的另一個安裝點上得文件或目錄能夠可見*/
- retval = do_loopback(&path, dev_name, flags & MS_REC);
- else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
- /*is responsible for handling shared, slave, and unbindable mounts by changing
- the mount flags or building up the required data structure connections
- between the vfsmount
- instances involved.*/
- retval = do_change_type(&path, flags);
- else if (flags & MS_MOVE)
- /*改變已安裝文件的安裝點*/
- /*used to move a mounted filesystem*/
- retval = do_move_mount(&path, dev_name);
- else
- /*handles normal mount operations. This is the default situation, so no special
- flags
- are required*/
- /*當用戶要求安裝一個特殊文件系統或存放在磁盤分區
- 中的普通文件系統時,調用*/
- retval = do_new_mount(&path, type_page, flags, mnt_flags,
- dev_name, data_page);
- dput_out:
- path_put(&path);
- return retval;
- }