Registration, installation and removal of the Linux file system

Registration 8.4.1 File System 

When the kernel is compiled, it has been determined which file systems can support these file systems, be registered in the VFS when the system boots. If the file system as a kernel loadable module, the register in the actual installation, and log off when the module is unloaded. Each file system has an initialization routine, its role is registered in the VFS, i.e., called a fill data structure file_system_type, which contains the name of the file system structure and a point corresponding to the VFS superblock read routine address, file_system_type structure of all registered file systems to form a linked list, another list is behind the difference will say to the mounted file system formed, we put this list called registration list. 8.7 is shown in FIG. File_system_type kernel list, specified by the list head file_systems variable. 

Figure 8.7 is already installed in the system only three file systems Ext2, proc, which file_system_type list structure formed iso9660 schematically illustrated. Of course, the system actually installed file system to be more. 

file_system_type fs.h data structures are defined as follows: 
struct {file_system_type 
const char * name; 
int fs_flags; 
struct the super_block * (* read_super for) (struct the super_block *, void *, int); 
struct * Module1 owner; 
struct * Next file_system_type ; 
struct the list_head fs_supers; 
};

Description of several of the following fields: 

· Name: Type the name of the file system, in the form of a string. 
· Fs_flags: some features indicate specific file system, the relevant definitions in fs.h sign in: 
/ * flags for public file_system_type * / 
#define FS_REQUIRES_DEV 1 
#define FS_NO_DCACHE 2 / * Only dcache at The Necessary Things * /. 
#Define FS_NO_PRELIM 4 / * Prevent preloading of DEntries, the even IF 
* Not FS_NO_DCACHE IS SET. 
* / 
#define FS_SINGLE. 8 / * CAN that have have only the Filesystem One Superblock * / 
#define FS_NOMOUNT 16 / * from the userland Never Mount * / 
#define FS_LITTER 32 / * at The Tree in dcache * Keeps / 
#define FS_ODD_RENAME 32768 / * the Temporary Stuff; by Will Soon Go Away AS 
* AS nfs_rename () by Will BE Cleaned up 
* /

Description of some common signs are as follows: 

(1) Some virtual file systems, such as pipe, shared memory, etc., did not allow calls mount through the system by the user process () to install. FS_NOMOUNT flag its fs_flags in such a file system is 1. 

(2) file system types generally require a physical device as a material basis, FS_REQUIRES_DEV fs_flags its flag is 1, the file systems such as Ext2, Minix, ufs like. 

(3) Some virtual file system and install the same type of the first "device" to create a data structure super_block its superblock, when installing other devices to share the same type of super_block structure that already exists, no longer have their own super-block structure. At this time FS_SINGLE fs_flags flag is 1, that the entire file system is only a super block, rather than as a general file system types, each super block has a specific device. 

· Read_super: This is the file system to read the various super block its function pointers. Because of its various different file system superblock, so the read function is different. 
· Owner: If the file system is represented by file_system_type achieved mountable module, the module pointer points to represent the specific structure of the module. If the file system is statically linked into the kernel, then the field is NULL. In fact, you only need to set this field THIS_MODLUE (this is a macro), it can automatically complete the work. 
· Next: all the file_system_type structural links to individual list link pointer variable file_systems point to this list. This list is a critical resource, file_systems_lock spin read-write lock protected. 
· Fs_supers: This field is Linux2.4.10 future kernel releases new addition, which is a doubly linked list. Is the list, in the superblock structure. As said above, each file system has a super block, but some file systems may be mounted on different devices, and each device has a particular superblock, superblock which form a doubly linked list. 

After each field understand this data structure, it is easy to understand the following registration function register_filesystem is (), the function is defined in the FS / super.c: 
/ ** 
* register_filesystem is - A new new filesystem Register 
* @fs: The File System Structure 

* Adds-The File System passed to The List of File Systems The Kernel 
* IS Aware of for Mount and OTHER syscalls. Returns 0 ON Success, 
* or A negative errno code ON AN error. 

* of The & struct file_system_type that IS passed IS linked The Kernel INTO 
* Not MUST BE Structures and File System The Freed has been an until 
* Unregistered. 
* / 
int register_filesystem is (struct file_system_type * FS) 

int RES = 0; 
struct file_system_type ** P; 
IF (FS!) 
return -EINVAL; 
if (fs->next) 
return -EBUSY; 
INIT_LIST_HEAD(&fs->fs_supers); 
write_lock(&file_systems_lock); 
p = find_filesystem(fs->name); 
if (*p) 
res = -EBUSY; 
else 
*p = fs; 
write_unlock(&file_systems_lock); 
return res; 

find_filesystem()函数在同一个文件中定义如下: 
static struct file_system_type **find_filesystem(const char *name) 

struct file_system_type **p; 
for (p=&file_systems; *p; p=&(*p)->next) 
if (strcmp((*p)->name,name) == 0) 
break; 
return p; 

Note that the operation of the registration of the list must be mutually exclusive manner, therefore, find the list plus a write lock write_lock. 

After registering the file system, you can also revoke the registration is deleted from the registration list a file_system_type structure, after which the system is no longer the kind of file system support. fs / super.c in unregister_filesystem () function is to play this role, it returns 0, if already registered in the list does not specify the structure to be deleted after performing successful, -1 is returned, its code is as follows: 
/ * * 
* unregister_filesystem - the unregister A File System 
* @fs: filesystem to the unregister 

* the Remove A File System that successfully WAS of Previously Registered 
* An error with at The Kernel returned IS IS IF at The File System not found.. 
* Zero returned IS ON A Success . 

* Once the this function has returned struct & file_system_type The Structure 
* On May BE Freed or the Reused. 
* / 
IT unregister_filesystem (struct file_system_type * FS) 

struct file_system_type ** tmp; 
write_lock (& file_systems_lock); 
tmp = & the file_systems; 
the while (* tmp) { 
IF (FS == * tmp) { 
* tmp = fs-> Next; 
fs-> Next = NULL; 
write_unlock (& file_systems_lock); 
return 0; 

tmp = & (* tmp) -> the Next; 

write_unlock (& file_systems_lock); 
return -EINVAL; 

install the 8.4.2 file system 
you want to use a file system that is not only registered, but also the file system must be installed. When you install Linux, Ext2 file system has a partition installed on the hard disk, it is as a root file system, the root file system is installed automatically on startup. In fact, you can see the file system after system startup and is installed at startup. If you need your own (usually super-user) installation file system, you need to specify three pieces of information: the name of the file system, mount point physical block devices, file system containing a file system in an existing file system. For example: 
$ Mount -t iso9660 / dev / HDC / mnt / cdrom 

Wherein, the file system name is ISO9660, / dev / hdc physical block device comprising a file system, / mnt / cdrom is the directory to be installed, i.e., the installation point. As can be seen from this example, a file system is actually installed to install a physical device. 

Use to the main data structure is a file system (or device) is mounted to a directory point vfsmount, defined in the include / linux / mount.h in: 
struct vfsmount 

struct the list_head mnt_hash; 
struct vfsmount * mnt_parent; / * FS WE are Mounted ON * / 
struct dentry * mnt_mountpoint; / * dentry of the mountpoint * / 
struct dentry * mnt_root; / * the root of The Mounted Tree * / 
struct the super_block * mnt_sb; / * pointer to Superblock * / 
struct the list_head mnt_mounts; / * List of Children, anchored here Wallpaper * / 
struct the list_head mnt_child; / * and going through Their mnt_child * / 
atomic_t mnt_count; 
int mnt_flags; 
char * mnt_devname; / * the Name of Device EG / dev / DSK / hda1 * / 
struct the list_head mnt_list; 
} ;

Next, the structure of the main field to provide further explanation: 

· In order to install all points in the system to quickly find, put them in the kernel hash table to organize, mnt_hash queue pointer is the formation of a hash table. 
· Mnt_mountpoint pointer is pointing to the installation point dentry structure. The pointer to the installation point dentry dentry directory tree root directory. 
· Mnt_parent is mounted on one point pointer pointing. If the current point is not installed on one mounting point (such as root), then the pointer is NULL. Meanwhile, there mnt_mounts vfsmount structure and two mnt_child queue head, as long as the presence of a layer structure vfsmount, put on the current configuration vfsmount mnt_child links vfsmount mnt_mounts one queue structure. This creates a tree structure installation, starting from a queue mnt_mounts vfsmount structure, all other devices can be found directly or indirectly mounted on the mounting points. 

· Mnt_sb point superblock structure super_blaock installed equipment. 
· Mnt_list vfsmount structure is a pointer to the list head pointer is formed. 

Further, the system defines vfsmntlist variable point mnt_list queue. This data structure is further appreciated that the specific implementation look behind the mounted file system. 

文件系统的安装选项,也就是vfsmount结构中的安装标志mnt_flags在linux/fs.h中定义如下: 
/* 
* These are the fs-independent mount-flags: up to 32 flags are supported 
*/ 
#define MS_RDONLY 1 /* Mount read-only */ 
#define MS_NOSUID 2 /* Ignore suid and sgid bits */ 
#define MS_NODEV 4 /* Disallow access to device special files */ 
#define MS_NOEXEC 8 /* Disallow program execution */ 
#define MS_SYNCHRONOUS 16 /* Writes are synced at once */ 
#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ 
#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ 
#define MS_NOATIME 1024 /* Do not update access times. */ 
#define MS_NODIRATIME 2048 /* Do not update directory access times */ 
MS_BIND 4096 #define 
#define MS_MOVE 8192 
#define MS_REC 16384 
#define MS_VERBOSE 32768 
#define MS_ACTIVE (30 <<. 1) 
#define MS_NOUSER (31 is <<. 1) 
can be seen from the definition, each corresponding to a 32-bit flag in . Logo is installed for all files of the entire file system. For example, if MS_NOSUID flag is 1, then the entire file system suid flag all executable files are ineffective. Other specific meanings of the flag described later is mounted do_mount () describes further a function code. 

1. Mount the root file system 

Each file system has its own root directory, if a file system (such as Ext2) root directory is the root system of the tree, then the file system known as the root file system. While other file systems can be installed in a directory tree of the system, the file system that you want to insert the directory is called the mount point. 

When the system boots, it is necessary to find the main disk contains the root file system code in the variable ROOT_DEV in. When a suitable compiler options transmitted to the kernel or loader initial startup, the root file system can be specified as / dev file in a device directory. Similarly, the install flag stored in the root file system root_mountflags variable. Users can specify these flags, it is through the implementation of / sbin / rdev outside programs compiled kernel image, or pass an appropriate option to initial start-loader to achieve. Root file system is mounted as a function mount_root (). 

2. Install a regular file system 

Once the root file system installed on the system, you can install other file systems. A directory for each file system can be installed in a directory tree on the system. 

In front of us the way to the command to mount the file system, the user program to install a file system you can call the mount () system call. Mount () system call to the kernel function implemented sys_mount (), which codes fs / namespace.c in. 
the asmlinkage Long the sys_mount (char * dev_name, char * dir_name, char * type, 
unsigned Long the flags, void * Data) 

int retval; 
unsigned Long Data_Page; 
unsigned Long type_page; 
unsigned Long dev_page; 
char * dir_page; 
retval = copy_mount_options (type, & type_page); 
IF (retval <0) 
return retval; 
dir_page = getName (dir_name); 
retval = PTR_ERR (dir_page); 
IF (IS_ERR (dir_page)) 
GOTO OUT1 of; 
retval = copy_mount_options (dev_name, & dev_page); 
IF (retval <0 ) 
GOTO OUT2; 
retval = copy_mount_options (data, &data_page); 
if (retval <0) 
goto out3; 
lock_kernel(); 
retval = do_mount((char*)dev_page, dir_page, (char*)type_page, 
flags, (void*)data_page); 
unlock_kernel(); 
free_page(data_page); 
out3: 
free_page(dev_page); 
out2: 
putname(dir_page); 
out1: 
free_page(type_page); 
return retval; 

Further explanation is given below: 

* Parameter dev_name pathname to be installed where the device file system, if not, then it is empty (e.g., when to be installed is a network-based file systems); dir_name is mounting point (idle directory) path name; type is the type of file system, the name string must be registered file system (e.g., "Ext2", "MSDOS" and the like); installation mode is the flags, as described above. Data associated with the file system points to a data structure (may be NULL). 

· copy_mount_options()和getname()函数将结构形式或字符串形式的参数值从用户空间拷贝到内核空间;这些参数值的长度均以一个 页面为限,但是getname()在复制时遇到字符串结尾符“\0”就停止,并返回指向该字符串的指针;而copy_mount_options()则拷 贝整个页面,并返回该页面的起始地址。 

The main function of the function call is do_mount (), do_mount () to add kernel lock during execution, but this is a lock for SMP, we will not consider. do_mount () implementation code in fs / namespace.c in: 
Long do_mount (dev_name char *, char * dir_name, type_page * char, 
unsigned Long the flags, * Data_Page void) 

struct nameidata Nd; 
int retval = 0; 
int = mnt_flags 0; 
/ * Discard Magic * / 
IF ((the flags & MS_MGC_MSK) == MS_MGC_VAL) 
the flags & = ~ MS_MGC_MSK; 
/ * Basic Sanity Checks * / 
IF (* dir_name dir_name || || memchr (dir_name, 0, PAGE_SIZE!!! )) 
return -EINVAL; 
IF (dev_name && memchr (dev_name, 0, PAGE_SIZE))! 
return -EINVAL; 
/ * The per-Separate the mountpoint the flags * / 
IF (the flags & MS_NOSUID) 
mnt_flags | = MNT_NOSUID; 
if (flags &MS_NODEV) 
mnt_flags |= MNT_NODEV; 
if (flags &MS_NOEXEC) 
mnt_flags |= MNT_NOEXEC; 
flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); 
/* ... and get the mountpoint */ 
if (path_init(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd)) 
retval = path_walk(dir_name, &nd); 
if (retval) 
return retval; 
if (flags &MS_REMOUNT) 
retval = do_remount(&nd, flags &~MS_REMOUNT, mnt_flags, 
data_page); 
else if (flags &MS_BIND) 
retval = do_loopback(&nd, dev_name, flags &MS_REC); 
else if (flags &MS_MOVE) 
retval = do_move_mount(&nd, dev_name); 
else 
retval = do_add_mount(&nd, type_page, flags,mnt_flags, 
dev_name, Data_Page); 
path_release (& Nd); 
return retval; 
Next, the function to give an explanation of the main code: 

· MS_MGC_VAL 和 MS_MGC_MSK是在以前的版本中定义的安装标志和掩码,现在的安装标志中已经不使用这些魔数了,因此,当还有这个魔数时,则丢弃它。 
· 对参数dir_name和dev_name进行基本检查,注意“!dir_name ” 和“!*dir_name”之不同,前者指指向字符串的指针为不为空,而后者指字符串不为空。Memchr()函数在指定长度的字符串中寻找指定的字符, 如果字符串中没有结尾符“\0”,也是一种错误。前面以说过,对于基于网络的文件系统dev_name可以为空。 
· 把安装标志为MS_NOSUID、MS_NOEXEC和MS_NODEV的三个标志位从flags分离出来,放在局部安装标志变量mnt_flags中。 
· 函数path_init()和path_walk()寻找安装点的dentry数据结构,找到的dentry结构存放在局部变量nd的dentry域中。 
· 如果flags中的MS_REMOUNT标志位为1,就表示所要求的只是改变一个原已安装设备的安装方式,例如从“只读“安装方式改为“可写”安装方式, 这是通过调用do_remount()函数完成的。 · 如果flags中的MS_BIND标志位为1,就表示把一个“回接”设备捆绑到另一个对象上。回接设备是一种特殊的设备(虚拟设备),而实际上并不是一种 真正设备,而是一种机制,这种机制提供了把回接设备回接到某个可访问的常规文件或块设备的手段。通常在/dev目录中有/dev/loop0和/dev /loop1两个回接设备文件。调用do_loopback()来实现回接设备的安装。 
· 如果flags中的MS_MOVE标志位为1,就表示把一个已安装的设备可以移到另一个安装点,这是通过调用do_move_mount()函数来实现的。 
If not more than three cases, and that is the general installation request, so the installation point is added to the directory tree, this is done by calling do_add_mount () function, and do_add_mount () first calls do_kern_mount () function to form a mount point , the code for that function fs / super.c in: 
struct do_kern_mount vfsmount * (char * type, the flags int, char * name, * Data void) 

struct * file_system_type FStype; 
struct vfsmount mnt * = NULL; 
struct the super_block SB * ; 
IF (of the type || memchr (of the type, 0, PAGE_SIZE)!!) 
return ERR_PTR (-EINVAL); 
/ * WE need ... The Capabilities * / 
(! Capable (CAP_SYS_ADMIN)) IF 
return ERR_PTR (-EPERM); 
/ ... Driver ... * filesystem * / 
FStype = get_fs_type (of the type); 
IF (! FStype) 
return ERR_PTR (-ENODEV); 
/ * ... * ... allocated vfsmount / 
mnt = alloc_vfsmnt (); 
IF ( ! mnt) { 
mnt = ERR_PTR(-ENOMEM); 
goto fs_out; 

set_devname(mnt, name); 
/* get locked superblock */ 
if (fstype->fs_flags &FS_REQUIRES_DEV) 
sb = get_sb_bdev(fstype, name, flags, data); 
else if (fstype->fs_flags &FS_SINGLE) 
sb = get_sb_single(fstype, flags, data); 
else 
sb = get_sb_nodev(fstype, flags, data); 
if (IS_ERR(sb)) { 
free_vfsmnt(mnt); 
mnt = (struct vfsmount *)sb; 
goto fs_out; 

if (fstype->fs_flags &FS_NOMOUNT) 
sb->s_flags |= MS_NOUSER; 
mnt->mnt_sb = sb; 
mnt->mnt_root = dget(sb->s_root); 
mnt->mnt_mountpoint = mnt->mnt_root; 
mnt->mnt_parent = Rd; 
up_write (& sb-> s_umount); 
Fs_OUT: 
put_filesystem (FStype); 
return mnt; 

the function is explained as follows: 

· Only system administrators have authority to install a device, so we should first check whether the current process has such authority. 
· Get_fs_type () function to find the corresponding structure in file_system_file the list according to the type name specific file system. 
· Alloc_vfsmnt () function call to the type of dispenser Slab mnt allocate space for local variables vfsmount structure and the corresponding initialization. 
· Set_devname () function to set the device name. 
· A general file system types require a physical device as a material basis, if FS_REQUIRES_DEV fs_flags flag is 1, indicating that this is the normal file system type, such as Ext2, mnix like. For this file system type, by calling get_sb_bdev () is read from the super block which equipment to be installed. 
If FS_SINGLE flag fs_flags is 1, indicating that the entire file system has only one type, that is to say, this is a virtual file system type. After this the file type in the same type of a "device" is installed, create a super block structure super_block by calling get_sb_single (), then install the same type of equipment to share this data structure. However, as this type of file system on each Ext2 device has a particular super block. 
· Some file system types fs_flags in FS_NOMOUNT, FS_REUIRE_DEV and all FS_SINGLE flag is 0, then the so-called file system is actually a "virtual", usually just used to achieve some kind of mechanism or procedures, so there is no corresponding physical device. For such a type of file system is through get_sb_nodev () to generate a super_block structure. 
If the file type fs_flags FS_NOMOUNT flag is 1, indicating that the user did not have installed, therefore, the MS_NOUSER flag in the superblock position 1. 
· Mnt-> mnt_sb point superblock sb mounted equipment; mnt-> mnt_root toward its root superblock b-> s_root, dget () function to count the reference count dentry plus 1; mnt-> mnt_mountpoint also point superblock roots, and mnt-> mnt_parent point to themselves. So far, only the formation of a mount point, but not yet installed this mount point in the directory tree. 

下面我们来看do_add_mount()的代码: 
static int do_add_mount(struct nameidata *nd, char *type, int flags, 
int mnt_flags, char *name, void *data) 

struct vfsmount *mnt = do_kern_mount(type, flags, name, data); 
int err = PTR_ERR(mnt); 
if (IS_ERR(mnt)) 
goto out; 
down(&mount_sem); 
/* Something was mounted here while we slept */ 
while(d_mountpoint(nd->dentry) &&follow_down(&nd->mnt, &nd->dentry)) 

err = -EINVAL; 
if (!check_mnt(nd->mnt)) 
goo unlock; 
/* Refuse the same filesystem on the same mount point */ 
err = -EBUSY; 
if (nd->mnt->mnt_sb == mnt->mnt_sb &&nd->mnt->mnt_root == nd->dentry) 
goto unlock; 
mnt-> mnt_flags = mnt_flags; 
ERR = graft_tree (mnt, Nd); 
UNLOCK: 
up (& mount_sem); 
mntput (mnt); 
OUT: 
return ERR; 

The following is an explanation of the code above: 
· first checks do_kern_mount () is formed the mount point is valid. 
· In do_mount () function, path_init () and path_walk () function has found a dentry structure installation point, inode structure and vfsmount structure and store it in local variable of type nd nameidata in, in do_add_mount () by parameters passed over. 
· However, in do_kern_mount () function reads the superblock from the device process is a more lengthy process, the current process almost certainly have to sleep in the process of waiting to be read from the device into the super block, so there may be another process pre-empted the first to be installed into another device on the same mount point. d_mountpoint () function is to check whether this happens. If this does occur, its response is to call follow_down () advances to the root of the installed equipment, and further testing the new installation point by while loop until you find an empty until the installation point. 
If on the same mount point to install two of the same file system, an error. 
· Call graft_tree () to hook up the tree mnt and installation, complete the final installation. 

So far, equipment installation is complete.
 Uninstall 8.4.3 File System 

If the file in the file system currently in use, the file system can not be uninstalled. If the file system file or directory is in use, VFS inode cache may contain the corresponding VFS inode. The identifier of the device where the file system, inode checks whether there is a cache VFS inode from the file system, and if the usage count is greater than 0, it shows that the file system is being used, therefore, the file system can not It is unloaded. Otherwise, see the corresponding VFS superblock, if VFS superblock flag the file system is "dirty", it must be written back to disk superblock information. After the above process, the corresponding VFS super block is released, and is disconnected from the data structure vfsmount release vfsmntlist list. Specific implementation code fs / super.c in sysy_umount () function, which will not be discussed in detail.
 

Guess you like

Origin blog.csdn.net/qq_38971487/article/details/93064371