Linux Virtual File System Installation (sys_mount ())

Source: Internet
Author: User
For the call of the mount system involved in the installation of the preceding root directory file system, we consider that a file system will be installed on an installed file system, that is, call the mount system call implementation. The mount system call is used to install a common file system. its... for the call of the mount system involved in the installation of the preceding root directory file system, we consider that a file system will be installed on an installed file system, that is, call the mount system call implementation. The mount system call is used to install a common file system. its service routine is sys_mount ().
 
/* Sys_mount system call */
/* Dev_name is the path name of the device to be installed;
Dir_name is the installed path name;
Type is a string that represents the file system 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;
/* Copy from user space to system space */
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;
/* Copy the user space to the system space and the entire page */
Ret = copy_mount_options (data, & data_page );
If (ret <0)
Goto out_data;
/* Operator */
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;
}
The following is the subject implementation
 
Long do_mount (char * dev_name, char * dir_name, char * type_page,
Unsigned long flags, void * data_page)
{
Struct 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 */
/* Obtain the installation path structure */
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)
/* Modify the existing file system parameters, that is, change the super block object s_flags.
Field installation flag */
Retval = do_remount (& path, flags &~ MS_REMOUNT, mnt_flags,
Data_page );
Else if (flags & MS_BIND)
/* Files or directories must be visible at another installation point in the system directory tree */
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)
/* Change the installation point of the installed file */
/* 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 */
/* When the user requires to install a special file system or store it in a disk partition
*/
Retval = do_new_mount (& path, type_page, flags, mnt_flags,
Dev_name, data_page );
Dput_out:
Path_put (& path );
Return retval;
}
 
/*
* Create a new mount for userspace and request it to be added into
* 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;
 
If (! Type)
Return-EINVAL;
 
/* We need capabilities ...*/
If (! Capable (CAP_SYS_ADMIN ))
Return-EPERM;
 
Lock_kernel ();
/* Handle the actual installation operation and return a new installation file system
Descriptor address. use get_fs_type to scan the linked list of registered file systems.
Find the matching file_system_type instance. Then allocate or obtain the sb structure
And associated with mnt, initialize mnt and return */
*/
Mnt = do_kern_mount (type, flags, name, data );
Unlock_kernel ();
If (IS_ERR (mnt ))
Return PTR_ERR (mnt );
/* Handle the necessary lock operations to ensure that a file system will not be loaded
Integrate the file system into the system at the same location */
Return do_add_mount (mnt, path, mnt_flags, NULL );
}
The do_kern_mount function has been introduced in the previous initialization. The following describes how to use the do_add_mount function to integrate the file system into the system.
 
 
/*
* Add a mount into a namespace's mount tree
*-Provide the option of adding the new mount to an expiration list
*/
Int do_add_mount (struct vfsmount * newmnt, struct path * path,
Int mnt_flags, struct list_head * fslist)
{
Int err;
 
Down_write (& namespace_sem );
/* Something was mounted here while we slept */
While (d_mountpoint (path-> dentry )&&
Follow_down (path ))
;
Err =-EINVAL;
/* Verify whether the file system recently installed on the reinstallation point points
Current namespace */
If (! (Mnt_flags & MNT_SHRINKABLE )&&! Check_mnt (path-> mnt ))
Goto unlock;
 
/* Refuse the same filesystem on the same mount point */
Err =-EBUSY;
/* If the file system to be installed has been installed in a parameter called by the system
The specified installation point */
If (path-> mnt-> mnt_sb = newmnt-> mnt_sb &&
Path-> mnt-> mnt_root = path-> dentry)
Goto unlock;
 
Err =-EINVAL;
/* This installation point is a symbolic link */
If (S_ISLNK (newmnt-> mnt_root-> d_inode-> I _mode ))
Goto unlock;
 
Newmnt-> mnt_flags = mnt_flags;
/* Insert the newly installed file system object to the namespace linked list,
Hash list and sub-linked list of the parent file system */
If (err = graft_tree (newmnt, path )))
Goto unlock;
 
If (fslist)/* add to the specified expiration list */
List_add_tail (& newmnt-> mnt_expire, fslist );
 
Up_write (& namespace_sem );
Return 0;
 
Unlock:
Up_write (& namespace_sem );
Mntput (newmnt );
Return err;
}
The newly installed file system object is linked to the system tree.
 
 
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)/* Add to tree */
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;
}
 
/* Add the file system to the namespace of the parent file system */
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 = 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 {
/* Ensure that the mnt_parent member of the new vfsmount instance points to the parent file system
And mnt_mountpoint points to the parent file.
Dentry instance in the system */
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 );
/* Add the new mnt to the global hash and the parent file system mnt instance.
Sub-file system linked list */
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;
}

Bullbat column
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.