您的位置:首页 > 其它

虚拟文件系统VFS---2

2016-05-26 16:22 330 查看
/*
* Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc).
*
* data is a (void *) that can point to any structure up to
* PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
* information (or be NULL).
*
* Pre-0.97 versions of mount() didn't have a flags word.
* When the flags word was introduced its top half was required
* to have the magic value 0xC0ED, and this remained so until 2.4.0-test9.
* Therefore, if this magic number is present, it carries no information
* and must be discarded.
*/
/* 以下几个函数将用户态参数拷贝至内核态,包括: 
    ** 1. kernel_type:挂载文件系统类型,如ext3 
    ** 2. kernel_dir:   挂载点路径 
    ** 3. dev_name:  设备名称 
    ** 4. data_pages: 选项信息 
    */  
/* 参数:   
** dev_name :   挂载设备名称 
** dir_name :   挂载点名称 
** type_page:   保存挂载的文件系统类型,如"ext3" 
** flags    :   挂载标志 
** data_page:   大部分情况下为NULL 
*/  
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;

/* ... and get the mountpoint */
<span style="white-space:pre">	/* 调用kern_path(),根据挂载点名称查找其dentry等信息 
    ** 参数:@dir_name     : 挂载点路径 
    **     :@LOOKUP_FOLLOW: 查找标志,遇到链接继续查找 
    **     :@path         : 查找结果保存与此结构中 
    */  </span>
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;

/* 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_BORN |
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);

if (flags & MS_REMOUNT)
<span style="white-space:pre">		</span>	 /*修改已经存在的文件系统参数,即改变超级块对象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))
retval = do_change_type(&path, flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&path, dev_name);/*改变已安装文件的安装点*/  
else
<span style="white-space:pre">		</span>	/*handles normal mount operations. This is the default situation, so no special  
      <span style="white-space:pre">	</span>      flags are required*/  
retval = do_new_mount(&path, type_page, flags, mnt_flags,
dev_name, data_page);  /*安装普通文件系统*/
dput_out:
path_put(&path);
return retval;
}

对于 :kern_path(dir_name, LOOKUP_FOLLOW, &path);

其中:

  /* 调用kern_path(),根据挂载点名称查找其dentry等信息 

    ** 参数:@dir_name     : 挂载点路径 

    **     :@LOOKUP_FOLLOW: 查找标志,遇到链接继续查找 

    **     :@path         : 查找结果保存与此结构中 

    */  

根据挂载点的路径名在内核中查找其内存目录项结构(struct
dentry),保存在path中;

关于do_path_lookup()函数下节分析

int kern_path(const char *name, unsigned int flags, struct path *path)
{
struct nameidata nd;
int res = do_path_lookup(AT_FDCWD, name, flags, &nd);
if (!res)
*path = nd.path;
return res;
}


对于do_new_mount(.......)分析;

/*
* create a new mount for userspace and request it to be added into the
* namespace's tree
*/
static int do_new_mount(struct path *path, char *type, int flags,
int mnt_flags, char *name, void *data)
{
struct vfsmount *mnt;
int err;

if (!type)
return -EINVAL;

/* we need capabilities... */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;

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

if (IS_ERR(mnt))
return PTR_ERR(mnt);

err = do_add_mount(real_mount(mnt), path, mnt_flags);
if (err)
mntput(mnt);
return err;
}


static 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);
if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
!mnt->mnt_sb->s_subtype)
mnt = fs_set_subtype(mnt, fstype);
put_filesystem(type);
return mnt;
}


      
struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
struct mount *mnt;
struct dentry *root;

if (!type)
return ERR_PTR(-ENODEV);

mnt = alloc_vfsmnt(name);
if (!mnt)
return ERR_PTR(-ENOMEM);

if (flags & MS_KERNMOUNT)
mnt->mnt.mnt_flags = MNT_INTERNAL;

root = mount_fs(type, flags, name, data);
if (IS_ERR(root)) {
free_vfsmnt(mnt);
return ERR_CAST(root);
}

mnt->mnt.mnt_root = root;
mnt->mnt.mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt;
br_write_lock(&vfsmount_lock);
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
br_write_unlock(&vfsmount_lock);
return &mnt->mnt;


/*
* add a mount into a namespace's mount tree
*/
static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
{
int err;

mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);

err = lock_mount(path);
if (err)
return err;

err = -EINVAL;
if (unlikely(!check_mnt(real_mount(path->mnt)))) {
/* that's acceptable only for automounts done in private ns */
if (!(mnt_flags & MNT_SHRINKABLE))
goto unlock;
/* ... and for those we'd better have mountpoint still alive */
if (!real_mount(path->mnt)->mnt_ns)
goto unlock;
}

/* Refuse the same filesystem on the same mount point */
err = -EBUSY;
if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
path->mnt->mnt_root == path->dentry)
goto unlock;

err = -EINVAL;
if (S_ISLNK(newmnt->mnt.mnt_root->d_inode->i_mode))
goto unlock;

newmnt->mnt.mnt_flags = mnt_flags;
err = graft_tree(newmnt, path);

unlock:
unlock_mount(path);
return err;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: