f2fs学习笔记 - 4. f2fs文件系统组件说明

1. 前言

本文主要是以f2fs文件系统为例来说明文件系统编程模式,要实现一个文件系统,需要实现哪些组件,以及如何被使用的。

2. 文件系统组件说明

2.1 定义文件系统类型(fs/f2fs/super.c)

static struct file_system_type f2fs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "f2fs",
        .mount          = f2fs_mount,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
};

任何具体的文件系统都需要定义file_system_type 结构体,它最主要的是指定了f2fs_mount的mount回调,通过init_f2fs_fs初始化函数中调用register_filesystem来完成文件系统注册

module_init(init_f2fs_fs)
  |--static int __init init_f2fs_fs(void)
       |--register_filesystem(&f2fs_fs_type);

2.2 定义超级块结构与操作集(fs/f2fs/super.c)

struct f2fs_super_block {    
        __le32 magic;                   /* Magic Number */   
        __le16 major_ver;               /* Major Version */  
        __le16 minor_ver;               /* Minor Version */  
        __le32 log_sectorsize;          /* log2 sector size in bytes */
        __le32 log_sectors_per_block;   /* log2 # of sectors per block */
        __le32 log_blocksize;           /* log2 block size in bytes */
        __le32 log_blocks_per_seg;      /* log2 # of blocks per segment */
        __le32 segs_per_sec;            /* # of segments per section */
        __le32 secs_per_zone;           /* # of sections per zone */
        __le32 checksum_offset;         /* checksum offset inside super block */
        __le64 block_count;             /* total # of user blocks */
        __le32 section_count;           /* total # of sections */
        __le32 segment_count;           /* total # of segments */
        __le32 segment_count_ckpt;      /* # of segments for checkpoint */
        __le32 segment_count_sit;       /* # of segments for SIT */
        __le32 segment_count_nat;       /* # of segments for NAT */
        __le32 segment_count_ssa;       /* # of segments for SSA */
        __le32 segment_count_main;      /* # of segments for main area */
        __le32 segment0_blkaddr;        /* start block address of segment 0 */
        __le32 cp_blkaddr;              /* start block address of checkpoint */
        __le32 sit_blkaddr;             /* start block address of SIT */
        __le32 nat_blkaddr;             /* start block address of NAT */
        __le32 ssa_blkaddr;             /* start block address of SSA */
        __le32 main_blkaddr;            /* start block address of main area */
        __le32 root_ino;                /* root inode number */
        __le32 node_ino;                /* node inode number */
        __le32 meta_ino;                /* meta inode number */
        __u8 uuid[16];                  /* 128-bit uuid for volume */
        __le16 volume_name[MAX_VOLUME_NAME];    /* volume name */
        __le32 extension_count;         /* # of extensions below */
        __u8 extension_list[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN];/* extension array */
        __le32 cp_payload;   
        __u8 version[VERSION_LEN];      /* the kernel version */
        __u8 init_version[VERSION_LEN]; /* the initial kernel version */
        __le32 feature;                 /* defined features */
        __u8 encryption_level;          /* versioning level for encryption */
        __u8 encrypt_pw_salt[16];       /* Salt used for string2key algorithm */
        struct f2fs_device devs[MAX_DEVICES];   /* device list */
        __le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */
        __u8 hot_ext_count;             /* # of hot file extension */
        __le16  s_encoding;             /* Filename charset encoding */
        __le16  s_encoding_flags;       /* Filename charset encoding flags */
        __u8 reserved[306];             /* valid reserved region */
        __le32 crc;                     /* checksum of superblock */
} __packed;

文件系统需要实现super_operations结构体变量,它定义了操作inode相关的一系列回调。

static const struct super_operations f2fs_sops = {
        .alloc_inode    = f2fs_alloc_inode,
        .free_inode     = f2fs_free_inode,
        .drop_inode     = f2fs_drop_inode,
        .write_inode    = f2fs_write_inode,
        .dirty_inode    = f2fs_dirty_inode,
        .show_options   = f2fs_show_options,
#ifdef CONFIG_QUOTA
        .quota_read     = f2fs_quota_read,
        .quota_write    = f2fs_quota_write,
        .get_dquots     = f2fs_get_dquots,
#endif
        .evict_inode    = f2fs_evict_inode,
        .put_super      = f2fs_put_super,
        .sync_fs        = f2fs_sync_fs,
        .freeze_fs      = f2fs_freeze,
        .unfreeze_fs    = f2fs_unfreeze,
        .statfs         = f2fs_statfs,
        .remount_fs     = f2fs_remount,
};

它主要会在文件系统类型file_system_type的mount回调中使用,用于初始化super_blcok的s_op

static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,...,void *data)
  |--mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super);
     |--struct super_block *s
     |  //~~~创建vfs超级块 super_block
     |--s = sget(fs_type, test_bdev_super, set_bdev_super, flags | SB_NOSEC, bdev)
     |--f2fs_fill_super(s, data, flags & SB_SILENT ? 1 : 0)
           |--struct f2fs_sb_info *sbi
           |--struct f2fs_super_block *raw_super;
           |  //~~~创建具体文件系统超级块信息 f2fs_sb_info
           |--sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL)
           |--read_raw_super_block(sbi, &raw_super, &valid_super_block,...)
           |     |--struct f2fs_super_block *super
           |     |  //~~~创建具体文件系统超级块 f2fs_super_block
           |     |--super = kzalloc(sizeof(struct f2fs_super_block), GFP_KERNEL)
           |     |--*raw_super = super
           |  //~~~将具体文件系统超级块信息初始化给VFS超级块
           |--s->s_fs_info = sbi
              //~~~将具体文件系统超级块初始化给具体文件系统超级块信息
              sbi->raw_super = raw_super
              //~~~将创建的具体文件系统超级块操作函数集 给super_block的s_op
              s->s_op = &f2fs_sops

2.3 定义inode结构(include/linux/f2fs_fs.h)

struct f2fs_inode {
        __le16 i_mode;                  /* file mode */
        __u8 i_advise;                  /* file hints */
        __u8 i_inline;                  /* file inline flags */
        __le32 i_uid;                   /* user ID */
        __le32 i_gid;                   /* group ID */
        __le32 i_links;                 /* links count */
        __le64 i_size;                  /* file size in bytes */
        __le64 i_blocks;                /* file size in blocks */
        __le64 i_atime;                 /* access time */
        __le64 i_ctime;                 /* change time */
        __le64 i_mtime;                 /* modification time */
        __le32 i_atime_nsec;            /* access time in nano scale */
        __le32 i_ctime_nsec;            /* change time in nano scale */
        __le32 i_mtime_nsec;            /* modification time in nano scale */
        __le32 i_generation;            /* file version (for NFS) */
        union {
                __le32 i_current_depth; /* only for directory depth */
                __le16 i_gc_failures;   /*
                                         * # of gc failures on pinned file.
                                         * only for regular files.
                                         */
        };
        __le32 i_xattr_nid;             /* nid to save xattr */
        __le32 i_flags;                 /* file attributes */
        __le32 i_pino;                  /* parent inode number */
        __le32 i_namelen;               /* file name length */
        __u8 i_name[F2FS_NAME_LEN];     /* file name for SPOR */
        __u8 i_dir_level;               /* dentry_level for large dir */

        struct f2fs_extent i_ext;       /* caching a largest extent */

        union {
                struct {
                        __le16 i_extra_isize;   /* extra inode attribute size */
                        __le16 i_inline_xattr_size;     /* inline xattr size, unit: 4 bytes */
                        __le32 i_projid;        /* project id */
                        __le32 i_inode_checksum;/* inode meta checksum */
                        __le64 i_crtime;        /* creation time */
                        __le32 i_crtime_nsec;   /* creation time in nano scale */
                        __le64 i_compr_blocks;  /* # of compressed blocks */
                        __u8 i_compress_algorithm;      /* compress algorithm */
                        __u8 i_log_cluster_size;        /* log of cluster size */
                        __le16 i_padding;               /* padding */
                        __le32 i_extra_end[0];  /* for attribute size calculation */
                } __packed;
                __le32 i_addr[DEF_ADDRS_PER_INODE];     /* Pointers to data blocks */
        };
        __le32 i_nid[DEF_NIDS_PER_INODE];       /* direct(2), indirect(2),
                                                double_indirect(1) node id */
} __packed;

2.4 定义inode操作函数集

在f2fs_iget时会初始化inode操作函数集,而在通过inode号来获取inode时均会调用到此函数

  • 常规文件的inode操作函数集
# fs/f2fs/file.c
const struct inode_operations f2fs_file_inode_operations = {
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
        .listxattr      = f2fs_listxattr,
        .fiemap         = f2fs_fiemap,
};
  • 目录文件的inode操作函数集
# fs/f2fs/namei.c
const struct inode_operations f2fs_dir_inode_operations = {
        .create         = f2fs_create,
        .lookup         = f2fs_lookup,
        .link           = f2fs_link,
        .unlink         = f2fs_unlink,
        .symlink        = f2fs_symlink,
        .mkdir          = f2fs_mkdir,
        .rmdir          = f2fs_rmdir,
        .mknod          = f2fs_mknod,
        .rename         = f2fs_rename2,
        .tmpfile        = f2fs_tmpfile,
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
        .listxattr      = f2fs_listxattr,
        .fiemap         = f2fs_fiemap,
}
  • 加密链接的inode操作函数集
const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
        .get_link       = f2fs_encrypted_get_link,
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .listxattr      = f2fs_listxattr,
};
  • 普通链接的inode操作函数集
const struct inode_operations f2fs_symlink_inode_operations = {
        .get_link       = f2fs_get_link,
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .listxattr      = f2fs_listxattr,
};
  • 特殊文件(字符设备/块设备/管道文件)的inode操作函数集
const struct inode_operations f2fs_special_inode_operations = {
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
        .listxattr      = f2fs_listxattr,
};

2.5 定义inode文件操作函数集

在f2fs_iget时会初始化inode文件操作函数集,而在通过inode号来获取inode时均会调用到此函数

  • 常规文件的inode文件操作函数集
# fs/f2fs/file.c
const struct file_operations f2fs_file_operations = {                                                                                                                                
        .llseek         = f2fs_llseek,
        .read_iter      = f2fs_file_read_iter,
        .write_iter     = f2fs_file_write_iter,                                                                                                                                      
        .open           = f2fs_file_open,
        .release        = f2fs_release_file,                                                                                                                                         
        .mmap           = f2fs_file_mmap,
        .flush          = f2fs_file_flush,                                                                                                                                           
        .fsync          = f2fs_sync_file,                                                                                                                                            
        .fallocate      = f2fs_fallocate,                                                                                                                                            
        .unlocked_ioctl = f2fs_ioctl,                                                                                                                                                
#ifdef CONFIG_COMPAT
        .compat_ioctl   = f2fs_compat_ioctl,                                                                                                                                         
#endif  
        .splice_read    = generic_file_splice_read,                                                                                                                                  
        .splice_write   = iter_file_splice_write,                                                                                                                                    
};
  • 目录文件的inode文件操作函数集
const struct file_operations f2fs_dir_operations = {                                                                                                                                 
        .llseek         = generic_file_llseek,                                                                                                                                       
        .read           = generic_read_dir,                                                                                                                                          
        .iterate_shared = f2fs_readdir,
        .fsync          = f2fs_sync_file,                                                                                                                                            
        .open           = f2fs_dir_open,                                                                                                                                             
        .unlocked_ioctl = f2fs_ioctl,                                                                                                                                                
#ifdef CONFIG_COMPAT
        .compat_ioctl   = f2fs_compat_ioctl,                                                                                                                                         
#endif                                                                                                                                                                               
};
  • 特殊文件的inode文件操作函数集
    字符设备
# fs/char_dev.c 
const struct file_operations def_chr_fops = {                                                                                                                                        
        .open = chrdev_open,                                                                                                                                                         
        .llseek = noop_llseek,                                                                                                                                                       
}

块设备

# fs/block_dev.c 
const struct file_operations def_blk_fops = {                                                                                                                                        
        .open           = blkdev_open,
        .release        = blkdev_close,                                                                                                                                              
        .llseek         = block_llseek,
        .read_iter      = blkdev_read_iter,
        .write_iter     = blkdev_write_iter,                                                                                                                                         
        .iopoll         = blkdev_iopoll,
        .mmap           = generic_file_mmap,                                                                                                                                         
        .fsync          = blkdev_fsync,                                                                                                                                              
        .unlocked_ioctl = block_ioctl,                                                                                                                                               
#ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,                                                                                                                                       
#endif  
        .splice_read    = generic_file_splice_read,                                                                                                                                  
        .splice_write   = iter_file_splice_write,                                                                                                                                    
        .fallocate      = blkdev_fallocate,                                                                                                                                          
};

管道设备

# fs/pipe.c
const struct file_operations pipefifo_fops = {                                                                                                                                       
        .open           = fifo_open,                                                                                                                                                 
        .llseek         = no_llseek,                                                                                                                                                 
        .read_iter      = pipe_read,                                                                                                                                                 
        .write_iter     = pipe_write,                                                                                                                                                
        .poll           = pipe_poll,                                                                                                                                                 
        .unlocked_ioctl = pipe_ioctl,                                                                                                                                                
        .release        = pipe_release,                                                                                                                                              
        .fasync         = pipe_fasync,                                                                                                                                               
}

2.6 定义inode address_space操作函数集

在f2fs_iget时会初始化inode address_space操作函数集,而在通过inode号来获取inode时均会调用到此函数

  • node info的inode address_space操作函数集
# fs/f2fs/node.c
/*                                                                                                                                                                                   
 * Structure of the f2fs node operations                                                                                                                                             
 */                                                                                                                                                                                  
const struct address_space_operations f2fs_node_aops = {                                                                                                                             
        .writepage      = f2fs_write_node_page,                                                                                                                                      
        .writepages     = f2fs_write_node_pages,                                                                                                                                     
        .set_page_dirty = f2fs_set_node_page_dirty,                                                                                                                                  
        .invalidatepage = f2fs_invalidate_page,                                                                                                                                      
        .releasepage    = f2fs_release_page,                                                                                                                                         
#ifdef CONFIG_MIGRATION                                                                                                                                                              
        .migratepage    = f2fs_migrate_page,                                                                                                                                         
#endif                                                                                                                                                                               
};
  • meta info的inode address_space操作函数集
# fs/f2fs/checkpoint.c
const struct address_space_operations f2fs_meta_aops = {                                                                                                                             
        .writepage      = f2fs_write_meta_page,                                                                                                                                      
        .writepages     = f2fs_write_meta_pages,                                                                                                                                     
        .set_page_dirty = f2fs_set_meta_page_dirty,                                                                                                                                  
        .invalidatepage = f2fs_invalidate_page,                                                                                                                                      
        .releasepage    = f2fs_release_page,                                                                                                                                         
#ifdef CONFIG_MIGRATION                                                                                                                                                              
        .migratepage    = f2fs_migrate_page,                                                                                                                                         
#endif                                                                                                                                                                               
};
  • 常规文件的inode address_space操作函数集
# fs/f2fs/data.c
const struct address_space_operations f2fs_dblock_aops = {                                                                                                                           
        .readpage       = f2fs_read_data_page,                                                                                                                                       
        .readahead      = f2fs_readahead,                                                                                                                                            
        .writepage      = f2fs_write_data_page,                                                                                                                                      
        .writepages     = f2fs_write_data_pages,                                                                                                                                     
        .write_begin    = f2fs_write_begin,                                                                                                                                          
        .write_end      = f2fs_write_end,                                                                                                                                            
        .set_page_dirty = f2fs_set_data_page_dirty,                                                                                                                                  
        .invalidatepage = f2fs_invalidate_page,                                                                                                                                      
        .releasepage    = f2fs_release_page,                                                                                                                                         
        .direct_IO      = f2fs_direct_IO,                                                                                                                                            
        .bmap           = f2fs_bmap,                                                                                                                                                 
        .swap_activate  = f2fs_swap_activate,                                                                                                                                        
        .swap_deactivate = f2fs_swap_deactivate,                                                                                                                                     
#ifdef CONFIG_MIGRATION                                                                                                                                                              
        .migratepage    = f2fs_migrate_page,                                                                                                                                         
#endif                                                                                                                                                                               
};
  • 目录文件的inode address_space操作函数集
# fs/f2fs/data.c
同常规文件
  • 链接文件的inode address_space操作函数集
# fs/f2fs/data.c
同常规文件

2.7 定义dentry操作函数集

# f2fs/dir.c
#ifdef CONFIG_UNICODE
const struct dentry_operations f2fs_dentry_ops = {
        .d_hash = generic_ci_d_hash,
        .d_compare = generic_ci_d_compare,
};
#endif
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值