文章目录
  1. 1. filesystem
    1. 1.1. filesystem register
      1. 1.1.1. file_system_type
      2. 1.1.2. filesystem register
    2. 1.2. Filesystem Handling
    3. 1.3. Namespaces
    4. 1.4. Filesystem Mounting

filesystem

Special filesystems are not bound to physical block devices.
However, the kernel assigns to each mounted special filesystem a fictitious(虚构的) block device that has the value 0 as major number and an arbitrary value (different for each special filesystem) as a minor number.

ls -F /sys/dev/block/ #ubuntu 14.04

设备号作用:

  1. 主设备号用来标识与设备文件相连的驱动程序(主设备号用来反映设备类型 )。
  2. 次编号被驱动程序用来辨别操作的是哪个设备(次设备号用来区分同类型的设备)。

filesystem register

file_system_type

Each registered filesystem is represented as a file_system_type object



struct file_system_type {
    //filesystem name
    const char *name;
    //FS_REQUIRES_DEV: Every filesystem of this type must be located on a physical disk device.
    //FS_BINARY_MOUNTDATA: The filesystem uses binary mount data.
    //FS_REVAL_DOT: Always revalidate the “.” and “..” paths in the dentry cache (for network filesystems).
    //FS_ODD_RENAME: “Rename” operations are “move” operations (for network filesystems).
    int fs_flags;
    // allocates a new superblock object and initializes it
    // if necessary, by reading a disk
    int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *);
    //method for removing a superblock
    void (*kill_sb) (struct super_block *);
    // pointer to the module implementint the filesystem
    struct module *owner;
    // pointer to the next element in the list of filesystem types
    struct file_system_type * next;
    // head of a list of superblock objects having the same filesystem type
    struct list_head fs_supers;
    struct lock_class_key s_lock_key;
    struct lock_class_key s_umount_key;
};

filesystem register

During system initialization, the register_filesystem( ) function is invoked for
every filesystem specified at compile time;
the function inserts the corresponding file_system_type object into the filesystem-type list.

The register_filesystem( ) function is also invoked when a module implementing a filesystem is loaded.
In this case, the filesystem may also be unregistered (by invoking the unregister_filesystem( ) function) when the module is unloaded.


static int __init init_ramfs_fs(void)
{
    return register_filesystem(&ramfs_fs_type);
}

static void __exit exit_ramfs_fs(void)
{
    unregister_filesystem(&ramfs_fs_type);
}

Filesystem Handling

Linux makes use of a system’s root filesystem:
it is the filesystem that is directly mounted by the kernel during the booting phase and
that holds the system initialization scripts and the most essential system programs.

Other filesystems can be mounted—either by the initialization scripts or directly by the users—on directories of already mounted filesystems.
Being a tree of directories, every filesystem has its own root directory.
The directory on which a filesystem is mounted is called the mount point.
A mounted filesystem is a child of the mounted filesystem to which the mount point directory belongs.
For instance, the /proc virtual filesystem is a child of the system’s root filesystem (and the system’s root filesystem is the parent of /proc).
The root directory of a mounted filesystem hides the content of the mount point directory of the parent filesystem, as well as the whole subtree of the parent filesystem below the mount point.

Namespaces

In a traditional Unix system, there is only one tree of mounted filesystems:
starting from the system’s root filesystem, each process can potentially access every file in a mounted filesystem by specifying the proper pathname.
In this respect, Linux 2.6 is more refined: every process might have its own tree of mounted filesystems—the so-called namespace of the process.

The root directory of a filesystem can be different from the root directory of a process:
the process’s root directory is the directory corresponding to the “ / ” pathname.
By default, the process’ root directory coincides with the root directory of the system’s root filesystem, but it can be changed by invoking the chroot() system call.

When a process mounts or unmounts a filesystem, it only modifies its namespace.
The namespace of a process is represented by a namespace structure pointed to by the namespace field of the process descriptor.


struct namespace {
    //usage counter(how many processes share the namespace)
    atomic_t     count;
    //represents the root of the tree of mounted filesystems of this namespace
    struct vfsmount *    root;
    //the head of a doubly linked circular list collecting all mounted filesystem that belong to the namespace.
    struct list_head    list;
    wait_queue_head_t poll;
    int event;
};

Filesystem Mounting

Linux is possible to mount the same filesystem several times.
Of course, if a filesystem is mounted n times, its root directory can be accessed through n mount points, one per mount peration.
Although the same filesystem can be accessed by using different mount points, it is really unique.
Thus, there is only one superblock object for all of them, no matter of how many times it has been mounted.

mount -t ext2 /dev/fd0 /flp

Mounted filesystems form a hierarchy(层级):
the mount point of a filesystem might be a directory of a second filesystem, which in turn is already mounted over a third file-system, and so on.

It is also possible to stack multiple mounts on a single mount point.
Each new mount on the same mount point hides the previously mounted filesystem,
although processes already using the files and directories under the old mount can continue to do so.
When the topmost mounting is removed, then the next lower mount is once more made visible.

ubuntu 14.04
mount -t ramfs /dev/block/1:0 /flp
touch /flp/hello;mkdir /flp/mnt
mount -t ramfs /dev/block/1:0 /flp/mnt
touch /flp/world
mount -t ramfs /dev/block/1:0 /flp/mnt
ls /flp/mnt #看一下输出是什么
umount /flp/mnt
ls /flp/mnt #看一下输出是什么
umount /flp/mnt
ls /flp/mnt #看一下输出是什么
ls /flp #看一下输出是什么

As you can imagine, keeping track of mounted filesystems can quickly become a nightmare.
For each mount operation, the kernel must save in memory the mount point and the mount flags,
as well as the relationships between the filesystem to be mounted and the other mounted filesystems.
Such information is stored in a mounted filesystem descriptor of type vfsmount .


struct vfsmount {
    //pointers for the hash table list
    struct list_head mnt_hash;
    //pointers to the parent filesystem on which this filesystem is mounted
    struct vfsmount *mnt_parent;    /* fs we are mounted on */
    //pointers to the dentry of the mount point directory where the filesystem
    //is mounted
    struct dentry *mnt_mountpoint;    /* dentry of mountpoint */
    //pointers to the dentry of the root directory of this filesystem
    struct dentry *mnt_root;    /* root of the mounted tree */
    //pointers to the superblock object of this filesystem
    struct super_block *mnt_sb;    /* pointer to superblock */
    //head of a list including all filesystem descriptors mounted on directories
    //of this filesystem
    struct list_head mnt_mounts;    /* list of children, anchored here */
    //pointers for the mnt_mounts list of mounted filesystem descriptors
    struct list_head mnt_child;    /* and going through their mnt_child */
    //usage counter(increased to forbid filesystem unmounting)
    atomic_t mnt_count;
    int mnt_flags;
    //flag set to true if the filesystem is marked as expired
    //(the filesystem can be automatically umounted if the flag is set and no
    //one is using it)
    int mnt_expiry_mark;     /* true if marked for expiry */
    char *mnt_devname;     /* Name of device e.g. /dev/dsk/hda1 */
    //pointers for namespace's list of mounted filesystem descriptors
    struct list_head mnt_list;
    struct list_head mnt_expire;    /* link in fs-specific expiry list */
    struct list_head mnt_share;    /* circular list of shared mounts */
    struct list_head mnt_slave_list;/* list of slave mounts */
    struct list_head mnt_slave;    /* slave list entry */
    struct vfsmount *mnt_master;    /* slave is on master->mnt_slave_list */
    //pointer to the namespace of the process that a mounted the filesystem
    struct namespace *mnt_namespace; /* containing namespace */
    int mnt_pinned;
};