对于前面的根目录文件系统的安装中涉及到了mount系统调用的调用,这里我们考虑一个文件系统将被安装在一个已经安装文件系统之上的情形,即调用mount系统调用实现。mount系统调用被用来安装一个普通文件系统,他的服务例程为sys_mount()。
-
-
-
-
-
-
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;
-
}
下面是主体实现
-
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;
-
-
-
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
-
flags &= ~MS_MGC_MSK;
-
-
-
-
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
-
return -EINVAL;
-
-
if (data_page)
-
((char *)data_page)[PAGE_SIZE - 1] = 0;
-
-
-
if (!(flags & MS_NOATIME))
-
mnt_flags |= MNT_RELATIME;
-
-
-
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);
-
-
-
-
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)
-
-
-
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))
-
-
-
-
-
retval = do_change_type(&path, flags);
-
else if (flags & MS_MOVE)
-
-
-
retval = do_move_mount(&path, dev_name);
-
else
-
-
-
-
-
-
retval = do_new_mount(&path, type_page, flags, mnt_flags,
-
dev_name, data_page);
-
dput_out:
-
path_put(&path);
-
return retval;
-
}
-
-
-
-
-
static int do_new_mount(struct path *path, char *type, int flags,
-
int mnt_flags, char *name, void *data)
-
{
-
struct vfsmount *mnt;
-
-
if (!type)
-
return -EINVAL;
-
-
-
if (!capable(CAP_SYS_ADMIN))
-
return -EPERM;
-
-
lock_kernel();
-
-
-
-
-
*/
-
mnt = do_kern_mount(type, flags, name, data);
-
unlock_kernel();
-
if (IS_ERR(mnt))
-
return PTR_ERR(mnt);
-
-
-
return do_add_mount(mnt, path, mnt_flags, NULL);
-
}
do_kern_mount函数在前面初始化中介绍过了,下面看do_add_mount函数用于将文件系统整合到系统中。
-
-
-
-
-
int do_add_mount(struct vfsmount *newmnt, struct path *path,
-
int mnt_flags, struct list_head *fslist)
-
{
-
int err;
-
-
down_write(&namespace_sem);
-
-
while (d_mountpoint(path->dentry) &&
-
follow_down(path))
-
;
-
err = -EINVAL;
-
-
-
if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
-
goto unlock;
-
-
-
err = -EBUSY;
-
-
-
if (path->mnt->mnt_sb == newmnt->mnt_sb &&
-
path->mnt->mnt_root == path->dentry)
-
goto unlock;
-
-
err = -EINVAL;
-
-
if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
-
goto unlock;
-
-
newmnt->mnt_flags = mnt_flags;
-
-
-
if ((err = graft_tree(newmnt, path)))
-
goto unlock;
-
-
if (fslist)
-
list_add_tail(&newmnt->mnt_expire, fslist);
-
-
up_write(&namespace_sem);
-
return 0;
-
-
unlock:
-
up_write(&namespace_sem);
-
mntput(newmnt);
-
return err;
-
}
新安装的文件系统对象链入系统树。
-
static int graft_tree(struct vfsmount *mnt, struct path *path)
-
{
-
int err;
-
if (mnt->mnt_sb->s_flags & MS_NOUSER)
-
return -EINVAL;
-
-
if (S_ISDIR(path->dentry->d_inode->i_mode) !=
-
S_ISDIR(mnt->mnt_root->d_inode->i_mode))
-
return -ENOTDIR;
-
-
err = -ENOENT;
-
mutex_lock(&path->dentry->d_inode->i_mutex);
-
if (IS_DEADDIR(path->dentry->d_inode))
-
goto out_unlock;
-
-
err = security_sb_check_sb(mnt, path);
-
if (err)
-
goto out_unlock;
-
-
err = -ENOENT;
-
if (!d_unlinked(path->dentry))
-
err = attach_recursive_mnt(mnt, path, NULL);
-
out_unlock:
-
mutex_unlock(&path->dentry->d_inode->i_mutex);
-
if (!err)
-
security_sb_post_addmount(mnt, path);
-
return err;
-
}
-
-
static int attach_recursive_mnt(struct vfsmount *source_mnt,
-
struct path *path, struct path *parent_path)
-
{
-
LIST_HEAD(tree_list);
-
struct vfsmount *dest_mnt = path->mnt;
-
struct dentry *dest_dentry = path->dentry;
-
struct vfsmount *child, *p;
-
int err;
-
-
if (IS_MNT_SHARED(dest_mnt)) {
-
err = invent_group_ids(source_mnt, true);
-
if (err)
-
goto out;
-
}
-
err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
-
if (err)
-
goto out_cleanup_ids;
-
-
if (IS_MNT_SHARED(dest_mnt)) {
-
for (p = source_mnt; p; p = next_mnt(p, source_mnt))
-
set_mnt_shared(p);
-
}
-
-
spin_lock(&vfsmount_lock);
-
if (parent_path) {
-
detach_mnt(source_mnt, parent_path);
-
attach_mnt(source_mnt, path);
-
touch_mnt_namespace(parent_path->mnt->mnt_ns);
-
} else {
-
-
-
-
mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
-
commit_tree(source_mnt);
-
}
-
-
list_for_each_entry_safe(child, p, &tree_list, mnt_hash) {
-
list_del_init(&child->mnt_hash);
-
-
-
commit_tree(child);
-
}
-
spin_unlock(&vfsmount_lock);
-
return 0;
-
-
out_cleanup_ids:
-
if (IS_MNT_SHARED(dest_mnt))
-
cleanup_group_ids(source_mnt, NULL);
-
out:
-
return err;
-
}
阅读(1886) | 评论(0) | 转发(0) |