ILD

overlayfs(2)
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2025-3-23 站点:Inside Linux Development

前一篇,分析了overlayfs的初始化过程。本篇对overlayfs的具体运行进行分析。


super operations

overlayfs的super operations,定义在fs/overlay/super.c

static const struct super_operations ovl_super_operations = {
        .alloc_inode    = ovl_alloc_inode,
        .free_inode     = ovl_free_inode,
        .destroy_inode  = ovl_destroy_inode,
        .drop_inode     = generic_delete_inode,
        .put_super      = ovl_put_super,
        .sync_fs        = ovl_sync_fs,
        .statfs         = ovl_statfs,
        .show_options   = ovl_show_options,
};


实现了几类接口:

1 inode分配、释放、摧毁等接口。

2 super block释放接口

3 文件系统统计接口

4 sync接口

5 显示参数接口


inode operation

alloc inode

static struct inode *ovl_alloc_inode(struct super_block *sb)
{
        struct ovl_inode *oi = alloc_inode_sb(sb, ovl_inode_cachep, GFP_KERNEL);
        
        if (!oi)        
                return NULL;

        oi->cache = NULL;
        oi->redirect = NULL;
        oi->version = 0;
        oi->flags = 0;
        oi->__upperdentry = NULL;
        oi->lowerdata_redirect = NULL;
        oi->oe = NULL;
        mutex_init(&oi->lock);
        
        return &oi->vfs_inode; 
}

相当简单,就是从kmem_cache分配内存,然后初始化私有成员,最后返回内嵌的inode指针。


free inode

static void ovl_free_inode(struct inode *inode)
{
        struct ovl_inode *oi = OVL_I(inode);

        kfree(oi->redirect);
        kfree(oi->oe);
        mutex_destroy(&oi->lock);
        kmem_cache_free(ovl_inode_cachep, oi);
}

释放也相当简单,释放私有数据,然后将内存返还给kmem_cache


destroy inode

根据参考手册,是这个操作是释放alloc inode接口中分配的东西,overlay fs用来释放底层的一些东西

static void ovl_destroy_inode(struct inode *inode)
{
        struct ovl_inode *oi = OVL_I(inode);
        
        dput(oi->__upperdentry);
        ovl_stack_put(ovl_lowerstack(oi->oe), ovl_numlower(oi->oe));
        if (S_ISDIR(inode->i_mode))
                ovl_dir_cache_free(inode);
        else
                kfree(oi->lowerdata_redirect);
}


drop inode

这个接口在inode的引用计数为0的时候调用。它只能有2个接口,要么是NULL,要么是generic_delete_inode,它表示删除inode。


put super

在卸载文件系统的时候调用,用来释放所有的资源。

inode、dentry已经提前释放?不走这个接口,这个接口只是释放文件系统私有的数据。


static void ovl_put_super(struct super_block *sb)
{
        struct ovl_fs *ofs = OVL_FS(sb);

        if (ofs)
                ovl_free_fs(ofs);
}


可以看到,它获得ovl_fs结构体,然后释放它。


sync fs

将dirty inode保存到disk。分为两种情况:

1 sync

2 syncfs


sync会同步所有的文件系统。所以这里就没有必要同步了。

syncfs就需要同步upper fs。


statfs

统计文件系统信息。它调用vfs_statfs来统计。


dentry operations

dentry operations保存在super block

sb->s_d_op = &ovl_dentry_operations


dentry有很多operation,overlayfs只实现了3个,其它都使用默认的。


d_real

union fs用这个接口返回底层的dentry。


d_revalidate/d_weak_revalidate

每当lookup找到一个dentry,就调用这个接口来验证dentry是否仍然有效。对于大多数文件系统,这个接口设置为NULL。

对于网络文件系统和union文件系统。dentry可能在别的地方被修改,所以需要实现这个接口。


返回正数表示dentry仍然有效,否则dentry无效。

d_revalidate可能在rcu-walk环境被调用,此时inode可能为空,此时应该返回-ECHILD


weak版本,表示只要检测inode是否有效即可。


参考

https://docs.kernel.org/6.12/filesystems/vfs.html


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.