Skip to content

VFS Superblock 管理

1. 模块架构

1.1 功能概述

Superblock 是文件系统的元数据结构,包含文件系统的整体信息(如块大小、总块数、 inode 数量等)。每个挂载的文件系统都有一个 super_block 结构。

1.2 关键源文件

文件作用
fs/super.csuperblock 管理实现
include/linux/fs/super_types.hsuperblock 类型定义
include/linux/fs.hsuper_operations
fs/sync.c文件系统同步

2. 核心数据结构

2.1 struct super_block

c
// include/linux/fs/super_types.h:132
struct super_block {
    struct list_head        s_list;         // 全局链表
    dev_t                   s_dev;          // 设备号
    unsigned char           s_blocksize_bits;
    unsigned long           s_blocksize;     // 块大小
    loff_t                  s_maxbytes;     // 最大文件大小
    struct file_system_type *s_type;       // 文件系统类型
    const struct super_operations *s_op;   // superblock 操作
    struct dentry           *s_root;        // 根目录 dentry
    struct rw_semaphore     s_umount;       // 卸载信号量
    int                     s_count;         // 引用计数
    atomic_t                s_active;        // 活跃计数
    unsigned long           s_flags;        // 挂载标志
    unsigned long           s_magic;        // 文件系统魔数
    void                    *s_fs_info;     // 文件系统私有数据
    struct block_device     *s_bdev;        // 块设备
    struct backing_dev_info *s_bdi;         // 回写设备信息
    struct list_head        s_inodes;       // inode 链表
    struct list_head        s_dirty;        // 脏 inode 链表
    struct list_head        s_io;           // 正在回写的 inode
    struct list_head        s_more_io;     // 更多 I/O
    struct list_lru         s_dentry_lru;   // dentry LRU
    struct list_lru         s_inode_lru;   // inode LRU
    // ...
};

2.2 struct super_operations

c
// include/linux/fs/super_types.h:83
struct super_operations {
    struct inode *(*alloc_inode)(struct super_block *sb);
    void (*destroy_inode)(struct inode *inode);
    void (*free_inode)(struct inode *inode);
    void (*dirty_inode)(struct inode *inode, int flags);
    int (*write_inode)(struct inode *inode, struct writeback_control *wbc);
    int (*drop_inode)(struct inode *inode);
    void (*evict_inode)(struct inode *inode);
    void (*put_super)(struct super_block *sb);
    int (*sync_fs)(struct super_block *sb, int wait);
    int (*freeze_super)(struct super_block *sb, ...);
    int (*thaw_super)(struct super_block *sb, ...);
    int (*statfs)(struct dentry *dentry, struct kstatfs *kstatfs);
    void (*umount_begin)(struct super_block *sb);
    int (*show_options)(struct seq_file *seq, struct dentry *dentry);
    long (*nr_cached_objects)(struct super_block *sb,
                              struct shrink_control *sc);
    long (*free_cached_objects)(struct super_block *sb,
                                struct shrink_control *sc);
};

2.3 struct file_system_type

c
// include/linux/fs.h:1400
struct file_system_type {
    const char *name;                   // 文件系统名称
    int fs_flags;                       // 文件系统标志
    int (*read_super)(struct super_block *sb, ...);
    struct file_system_type *next;      // 链表
    struct list_head fs_supers;         // superblock 链表
    struct lock_class_key s_lock_key;
    struct lock_class_key s_umount_key;
    // ...
};

3. Superblock 分配

3.1 alloc_super()

c
// fs/super.c:200
static struct super_block *alloc_super(struct file_system_type *type,
                                       int user_flags)
{
    struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER);

    if (s) {
        // 初始化信号量
        init_rwsem(&s->s_umount);
        // 初始化锁
        spin_lock_init(&s->s_lock);
        // 初始化引用计数
        atomic_set(&s->s_active, 1);
        // 初始化 LRU
        list_lru_init(&s->s_dentry_lru);
        list_lru_init(&s->s_inode_lru);
        // 初始化链表
        INIT_LIST_HEAD(&s->s_inodes);
        INIT_LIST_HEAD(&s->s_dirty);
        INIT_LIST_HEAD(&s->s_io);
        // 设置文件系统类型
        s->s_type = type;
        s->s_flags = user_flags;
    }

    return s;
}

3.2 sget()

c
// fs/super.c:300
struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *, void *),
                        int (*set)(struct super_block *, void *),
                        int flags, void *data)
{
    struct super_block *s = NULL;
    struct super_block *old;
    int err;

    // 查找已存在的 superblock
    spin_lock(&sb_lock);
    list_for_each_entry(old, &type->fs_supers, s_instance) {
        if (!test(old, data))
            continue;

        if (user_flags && old->s_flags != user_flags)
            continue;

        // 增加引用计数
        if (!atomic_inc_not_zero(&old->s_active))
            continue;

        spin_unlock(&sb_lock);
        return old;
    }
    spin_unlock(&sb_lock);

    // 分配新的 superblock
    s = alloc_super(type, flags & ~MS_SUBMOUNT);
    if (!s)
        return ERR_PTR(-ENOMEM);

    err = set(s, data);
    if (err) {
        deactivate_super(s);
        return ERR_PTR(err);
    }

    // 加入全局链表
    spin_lock(&sb_lock);
    list_add_tail(&s->s_list, &type->fs_supers);
    spin_unlock(&sb_lock);

    return s;
}

4. Superblock 卸载

4.1 deactivate_locked_super()

c
// fs/super.c:500
void deactivate_locked_super(struct super_block *s)
{
    struct file_system_type *fs = s->s_type;

    // 如果还有活跃引用,等待
    if (atomic_dec_and_test(&s->s_active)) {
        // 同步文件系统
        sync_filesystem(s);
        // 杀死所有 inode
        evict_inodes(s->s_root->d_sb);
        // 刷新脏数据
        sync_filesystem(s);
        // 调用文件系统的 put_super
        if (fs->put_super)
            fs->put_super(s);
        // 释放根 dentry
        dput(s->s_root);
        // 释放块设备
        blkdev_put(s->s_bdev, BDEVFS_TYPE);
    }
}

4.2 generic_shutdown_super()

c
// fs/super.c:450
void generic_shutdown_super(struct super_block *sb)
{
    // 杀死所有 inode
    evict_inodes(sb);

    // 刷新并释放根 dentry
    if (sb->s_root) {
        dput(sb->s_root);
        sb->s_root = NULL;
    }

    // 调用文件系统的 put_super
    if (sb->s_op->put_super)
        sb->s_op->put_super(sb);

    // 从哈希表移除
    spin_lock(&sb_lock);
    hlist_del_init_rcu(&sb->s_instances);
    spin_unlock(&sb_lock);

    // 释放 s_umount 信号量
    up_write(&sb->s_umount);
}

5. Superblock 同步

5.1 sync_filesystem()

c
// fs/sync.c:200
void sync_filesystem(struct super_block *sb)
{
    // 同步所有脏数据
    if (sb->s_op->sync_fs)
        sb->s_op->sync_fs(sb, 0);

    // 同步所有 inode
    sync_inodes_sb(sb);

    // 同步超级块
    if (sb->s_op->write_super && sb->s_dirt)
        sb->s_op->write_super(sb);
}

5.2 sync_inodes_sb()

c
// fs/sync.c:250
void sync_inodes_sb(struct super_block *sb)
{
    struct inode *inode;

    spin_lock(&sb->s_inode_list_lock);
    list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
        if (inode->i_state & I_DIRTY)
            write_inode(inode, NULL);
    }
    spin_unlock(&sb->s_inode_list_lock);
}

6. Superblock 冻结

6.1 freeze_super()

c
// fs/super.c:600
int freeze_super(struct super_block *sb)
{
    int ret;

    // 获取 s_umount 写锁
    down_write(&sb->s_umount);

    // 如果已经冻结,直接返回
    if (sb->s_writers.frozen >= SB_FREEZE_COMPLETE) {
        ret = -EBUSY;
        goto out;
    }

    // 同步文件系统
    sync_filesystem(sb);

    // 冻结
    ret = sb->s_op->freeze_super(sb, SB_FREEZE_WRITE);
    if (ret)
        goto out;

    // 等待所有进程退出
    sb->s_writers.frozen = SB_FREEZE_WRITE;
    wake_up(&sb->s_writer_wq);
    wait_event(sb->s_writer_wq, sb->s_writers.sumo_writes == 0);

    ret = sb->s_op->freeze_super(sb, SB_FREEZE_PAGEFAULT);
    if (ret)
        goto out;

    ret = sb->s_op->freeze_super(sb, SB_FREEZE_FS);
    if (ret)
        goto out;

    sb->s_writers.frozen = SB_FREEZE_COMPLETE;

out:
    up_write(&sb->s_umount);
    return ret;
}

6.2 thaw_super()

c
// fs/super.c:650
int thaw_super(struct super_block *sb)
{
    int ret;

    down_write(&sb->s_umount);

    if (sb->s_writers.frozen < SB_FREEZE_COMPLETE) {
        ret = -EINVAL;
        goto out;
    }

    ret = sb->s_op->thaw_super(sb);
    if (ret)
        goto out;

    sb->s_writers.frozen = SB_UNFROZEN;
    wake_up(&sb->s_writer_wq);

out:
    up_write(&sb->s_umount);
    return ret;
}

7. Superblock 查找

7.1 get_super()

c
// fs/super.c:150
struct super_block *get_super(struct block_device *bdev)
{
    struct super_block *s;

    // 遍历所有 superblock
    spin_lock(&sb_lock);
    list_for_each_entry(s, &super_blocks, s_list) {
        if (s->s_bdev == bdev) {
            // 增加引用计数
            if (atomic_inc_not_zero(&s->s_active))
                s->s_count++;
            spin_unlock(&sb_lock);
            return s;
        }
    }
    spin_unlock(&sb_lock);

    return NULL;
}

7.2 get_super_thawed()

c
// fs/super.c:180
struct super_block *get_super_thawed(struct block_device *bdev)
{
    struct super_block *s = get_super(bdev);

    if (!s)
        return NULL;

    // 等待冻结完成
    wait_event(s->s_writer_wq, s->s_writers.frozen < SB_FREEZE_WRITE);

    return s;
}

8. Superblock LRU

8.1 super_cache_scan()

c
// fs/super.c:800
static unsigned long super_cache_scan(struct shrink_control *sc)
{
    struct super_block *sb;
    unsigned long freed = 0;

    spin_lock(&sb_lock);
    list_for_each_entry(sb, &super_blocks, s_list) {
        struct dentry *dentry;

        // 尝试收缩 dentry LRU
        freed += list_lru_shrink_walk(&sb->s_dentry_lru, sc,
                                       &dentry_lru_isolate, NULL);

        // 如果已经满足要求,停止
        if (freed >= sc->nr_to_scan)
            break;
    }
    spin_unlock(&sb_lock);

    return freed;
}

9. 文件系统注册

9.1 register_filesystem()

c
// fs/filesystem.c:100
int register_filesystem(struct file_system_type *fs)
{
    int res = 0;
    struct file_system_type *p;

    // 检查是否已注册
    list_for_each_entry(p, &file_systems, list) {
        if (strcmp(p->name, fs->name) == 0) {
            res = -EBUSY;
            goto out;
        }
    }

    // 加入链表
    list_add_tail(&fs->list, &file_systems);

out:
    return res;
}

9.2 unregister_filesystem()

c
// fs/filesystem.c:150
int unregister_filesystem(struct file_system_type *fs)
{
    int res = 0;

    spin_lock(&file_systems_lock);
    if (!list_empty(&fs->fs_supers))
        res = -EBUSY;
    else
        list_del(&fs->list);
    spin_unlock(&file_systems_lock);

    return res;
}

10. 挂载流程

用户: mount("/dev/sda1", "/mnt", "ext4", MS_MGC_VAL, NULL)

内核路径:
1. do_mount()
   |
   2. do_new_mount()
      |
      3. vfs_kern_mount()
         |
      4. alloc_vfsmnt()
         |  分配 struct vfsmount
         |
      5. type->read_super() 或 get_sb_bdev()
         |  读取/创建 super_block
         |
      6. sget()
         |  查找或分配 superblock
         |
      7. ext4_fill_super()
         |  初始化 ext4 特定数据
         |
      8. set_anon_super()
         |  设置匿名 superblock
         |
      9. graft_tree()
         |  将 vfsmount 加入挂载树

11. Superblock 标志

c
// include/linux/fs.h
#define MS_RDONLY       (1 << 0)    // 只读
#define MS_NOSUID       (1 << 1)    // 不执行 setuid
#define MS_NODEV        (1 << 2)    // 不允许访问设备
#define MS_NOEXEC       (1 << 3)    // 不允许执行
#define MS_SYNCHRONOUS  (1 << 4)    // 同步 I/O
#define MS_REMOUNT      (1 << 5)    // 重新挂载
#define MS_MANDLOCK     (1 << 6)    // 强制锁
#define MS_DIRSYNC      (1 << 7)    // 目录同步
#define MS_NOATIME      (1 << 10)   // 不更新 atime
#define MS_NODIRATIME   (1 << 11)   // 不更新目录 atime
#define MS_BIND         (1 << 12)   // 绑定挂载
#define MS_MOVE         (1 << 13)   // 移动挂载
#define MS_REC          (1 << 14)   // 递归
#define MS_SILENT       (1 << 15)   // 静默

基于 VitePress 构建