一. 用户空间 f2fs文件系统 Mount(挂载)
在挂载之前,我们需要使用mkfs.f2fs工具对块设备进行格式化为f2fs文件系统(如果在Mount之前不格式化成f2fs文件系统,后续Mount挂载的时候会报错,不识别f2fs文件系统)
mkfs.f2fs工具作用就是在块设备上建立f2fs文件系统
1. # mkfs.f2fs -l label /dev/block_device
将块设备挂载到/mnt/f2fs目录,挂载的文件系统格式为F2fs文件系统
2. # mount -t f2fs /dev/block_device /mnt/f2fs
二. 用户空间Mount 系统调用进入内核空间f2fs_mount
三. 内核空间f2fs文件系统Mount (f2fs_mount)
用户空间执行Mount命令---->系统调用 ---->内核空间f2fs文件系统 f2fs_mount
1. f2fs文件系统 f2fs_fs_type 结构体含有 mount成员,当用户在用户空间执行mount操作时,会回调到这个mount位置,由f2fs_mount 执行接下去的Mount动作,
static struct file_system_type f2fs_fs_type = {
.owner = THIS_MODULE,
.name = "f2fs",
.mount = f2fs_mount,
.kill_sb = kill_f2fs_super,
.fs_flags = FS_REQUIRES_DEV,
};
2. f2fs_mount是针对块设备挂载成f2fs文件系统的函数
static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data)
{
return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super);
}
f2fs_fill_super:填充f2fs super block信息
3.mount_bdev是针对块设备挂载时使用的函数,执行块设备挂载,这里块设备指的时 /dev/block_device ,此外还有mount_nodev, mount_single等函数,分别用于不同的挂载情况
struct dentry *mount_bdev(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int))
{
struct block_device *bdev;
struct super_block *s;
fmode_t mode = FMODE_READ | FMODE_EXCL;
int error = 0;
if (!(flags & SB_RDONLY))
mode |= FMODE_WRITE;
/* 打开由dev_name/mode/fs_type描述的块设备*/
bdev = blkdev_get_by_path(dev_name, mode, fs_type);
if (IS_ERR(bdev))
return ERR_CAST(bdev);
/*
* once the super is inserted into the list by sget, s_umount
* will protect the lockfs code from trying to start a snapshot
* while we are mounting
*/
mutex_lock(&bdev->bd_fsfreeze_mutex);
if (bdev->bd_fsfreeze_count > 0) {
mutex_unlock(&bdev->bd_fsfreeze_mutex);
error = -EBUSY;
goto error_bdev;
}
/* find or create a superblock */
s = sget(fs_type, test_bdev_super, set_bdev_super, flags | SB_NOSEC,
bdev);
mutex_unlock(&bdev->bd_fsfreeze_mutex);
if (IS_ERR(s))
goto error_s;
if (s->s_root) {
if ((flags ^ s->s_flags) & SB_RDONLY) {
deactivate_locked_super(s);
error = -EBUSY;
goto error_bdev;
}
/*
* s_umount nests inside bd_mutex during
* __invalidate_device(). blkdev_put() acquires
* bd_mutex and can't be called under s_umount. Drop
* s_umount temporarily. This is safe as we're
* holding an active reference.
*/
up_write(&s->s_umount);
blkdev_put(bdev, mode);
down_write(&s->s_umount);
} else {
s->s_mode = mode;
snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
sb_set_blocksize(s, block_size(bdev));
/* 填充f2fs super block信息*/
error = fill_super(s, data, flags & SB_SILENT ? 1 : 0);
if (error) {
deactivate_locked_super(s);
goto error;
}
s->s_flags |= SB_ACTIVE;
bdev->bd_super = s;
}
return dget(s->s_root);
error_s:
error = PTR_ERR(s);
error_bdev:
blkdev_put(bdev, mode);
error:
return ERR_PTR(error);
}
EXPORT_SYMBOL(mount_bdev);
4. f2fs_fill_super是填充f2fs super block信息
Superblock区域
Superblock保存了F2FS的核心元数据的结构,包括磁盘大小,元区域的各个部分的起始地址等。
Superblock在元数据区域的物理结构
Superblock区域是由两个struct f2fs_super_block
结构组成,互为备份
(1)Superblock物理存放区域结构
struct f2fs_super_block
是F2FS对Superblock的具体数据结构实现,它保存在磁盘的最开始的位置,F2FS进行挂载时从磁盘的前端直接读取出来,然后转换为struct f2fs_super_block
结构。它的定义如下:
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 */
__u8 reserved[246]; /* valid reserved region */
__u8 mount_opts[64]; /* default mount option for SEC */
__le32 crc; /* checksum of superblock */
} __packed;
(2)Superblock内存管理结构:
f2fs_super_block在内存中的对应的结构是struct f2fs_sb_info,它除了包含了struct