f2fs学习四: f2fs文件系统挂载
一. 用户空间 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
结构组成,互为备份
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;
其中f2fs_sb_info是在init_sb_info函数中进行初始化的
struct f2fs_sb_info {struct super_block *sb; /* pointer to VFS super block */struct proc_dir_entry *s_proc; /* proc entry */struct f2fs_super_block *raw_super; /* raw super block pointer */struct rw_semaphore sb_lock; /* lock for raw super block */int valid_super_block; /* valid super block no */unsigned long s_flag; /* flags for sbi */struct mutex writepages; /* mutex for writepages() */#ifdef CONFIG_BLK_DEV_ZONEDunsigned int blocks_per_blkz; /* F2FS blocks per zone */unsigned int log_blocks_per_blkz; /* log2 F2FS blocks per zone */
#endif/* for node-related operations */struct f2fs_nm_info *nm_info; /* node manager */struct inode *node_inode; /* cache node blocks *//* for segment-related operations */struct f2fs_sm_info *sm_info; /* segment manager *//* for bio operations */struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios *//* keep migration IO order for LFS mode */struct rw_semaphore io_order_lock;mempool_t *write_io_dummy; /* Dummy pages *//* for checkpoint */struct f2fs_ckpt_cmd_control *ccc_info; /* for checkpoint cmd control */struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */int cur_cp_pack; /* remain current cp pack */spinlock_t cp_lock; /* for flag in ckpt */struct inode *meta_inode; /* cache meta blocks */struct mutex cp_mutex; /* checkpoint procedure lock */struct rw_semaphore cp_rwsem; /* blocking FS operations */struct rw_semaphore node_write; /* locking node writes */struct rw_semaphore node_change; /* locking node change */wait_queue_head_t cp_wait;unsigned long last_time[MAX_TIME]; /* to store time in jiffies */long interval_time[MAX_TIME]; /* to store thresholds */struct inode_management im[MAX_INO_ENTRY]; /* manage inode cache */spinlock_t fsync_node_lock; /* for node entry lock */struct list_head fsync_node_list; /* node list head */unsigned int fsync_seg_id; /* sequence id */unsigned int fsync_node_num; /* number of node entries *//* for orphan inode, use 0'th array */unsigned int max_orphans; /* max orphan inodes *//* for inode management */struct list_head inode_list[NR_INODE_TYPE]; /* dirty inode list */spinlock_t inode_lock[NR_INODE_TYPE]; /* for dirty inode list lock *//* for extent tree cache */struct radix_tree_root extent_tree_root;/* cache extent cache entries */struct mutex extent_tree_lock; /* locking extent radix tree */struct list_head extent_list; /* lru list for shrinker */spinlock_t extent_lock; /* locking extent lru list */atomic_t total_ext_tree; /* extent tree count */struct list_head zombie_list; /* extent zombie tree list */atomic_t total_zombie_tree; /* extent zombie tree count */atomic_t total_ext_node; /* extent info count *//* basic filesystem units */unsigned int log_sectors_per_block; /* log2 sectors per block */unsigned int log_blocksize; /* log2 block size */unsigned int blocksize; /* block size */unsigned int root_ino_num; /* root inode number*/unsigned int node_ino_num; /* node inode number*/unsigned int meta_ino_num; /* meta inode number*/unsigned int log_blocks_per_seg; /* log2 blocks per segment */unsigned int blocks_per_seg; /* blocks per segment */unsigned int segs_per_sec; /* segments per section */unsigned int secs_per_zone; /* sections per zone */unsigned int total_sections; /* total section count */unsigned int total_node_count; /* total node block count */unsigned int total_valid_node_count; /* valid node block count */loff_t max_file_blocks; /* max block index of file */int dir_level; /* directory level */int readdir_ra; /* readahead inode in readdir */block_t user_block_count; /* # of user blocks */block_t total_valid_block_count; /* # of valid blocks */block_t discard_blks; /* discard command candidats */block_t last_valid_block_count; /* for recovery */block_t reserved_blocks; /* configurable reserved blocks */block_t current_reserved_blocks; /* current reserved blocks *//* Additional tracking for no checkpoint mode */block_t unusable_block_count; /* # of blocks saved by last cp */unsigned int nquota_files; /* # of quota sysfile *//* # of pages, see count_type */atomic_t nr_pages[NR_COUNT_TYPE];/* # of allocated blocks */struct percpu_counter alloc_valid_block_count;/* writeback control */atomic_t wb_sync_req[META]; /* count # of WB_SYNC threads *//* valid inode count */struct percpu_counter total_valid_inode_count;struct f2fs_mount_info mount_opt; /* mount options *//* for cleaning operations */struct mutex gc_mutex; /* mutex for GC */struct f2fs_gc_kthread *gc_thread; /* GC thread */unsigned int cur_victim_sec; /* current victim section num */unsigned int gc_mode; /* current GC state */unsigned int next_victim_seg[2]; /* next segment in victim section *//* for skip statistic */unsigned int atomic_files; /* # of opened atomic file */unsigned long long skipped_atomic_files[2]; /* FG_GC and BG_GC */unsigned long long skipped_gc_rwsem; /* FG_GC only *//* threshold for gc trials on pinned files */u64 gc_pin_file_threshold;/* maximum # of trials to find a victim segment for SSR and GC */unsigned int max_victim_search;/* migration granularity of garbage collection, unit: segment */unsigned int migration_granularity;/** for stat information.* one is for the LFS mode, and the other is for the SSR mode.*/
#ifdef CONFIG_F2FS_STAT_FSstruct f2fs_stat_info *stat_info; /* FS status information */atomic_t meta_count[META_MAX]; /* # of meta blocks */unsigned int segment_count[2]; /* # of allocated segments */unsigned int block_count[2]; /* # of allocated blocks */atomic_t inplace_count; /* # of inplace update */atomic64_t total_hit_ext; /* # of lookup extent cache */atomic64_t read_hit_rbtree; /* # of hit rbtree extent node */atomic64_t read_hit_largest; /* # of hit largest extent node */atomic64_t read_hit_cached; /* # of hit cached extent node */atomic_t inline_xattr; /* # of inline_xattr inodes */atomic_t inline_inode; /* # of inline_data inodes */atomic_t inline_dir; /* # of inline_dentry inodes */atomic_t vw_cnt; /* # of volatile writes */atomic_t max_aw_cnt; /* max # of atomic writes */atomic_t max_vw_cnt; /* max # of volatile writes */int bg_gc; /* background gc calls */unsigned int io_skip_bggc; /* skip background gc for in-flight IO */unsigned int other_skip_bggc; /* skip background gc for other reasons */unsigned int ndirty_inode[NR_INODE_TYPE]; /* # of dirty inodes */
#endifspinlock_t stat_lock; /* lock for stat operations *//* For app/fs IO statistics */spinlock_t iostat_lock;unsigned long long write_iostat[NR_IO_TYPE];bool iostat_enable;/* For sysfs suppport */struct kobject s_kobj;struct completion s_kobj_unregister;/* For shrinker support */struct list_head s_list;int s_ndevs; /* number of devices */struct f2fs_dev_info *devs; /* for device list */unsigned int dirty_device; /* for checkpoint data flush */spinlock_t dev_lock; /* protect dirty_device */struct mutex umount_mutex;unsigned int shrinker_run_no;/* For write statistics */u64 sectors_written_start;u64 kbytes_written;/* Reference to checksum algorithm driver via cryptoapi */struct crypto_shash *s_chksum_driver;/* Precomputed FS UUID checksum for seeding other checksums */__u32 s_chksum_seed;struct f2fs_sec_stat_info sec_stat;struct f2fs_sec_fsck_info sec_fsck_stat;/* To gather information of fragmentation */unsigned int s_sec_part_best_extents;unsigned int s_sec_part_current_extents;unsigned int s_sec_part_score;unsigned int s_sec_defrag_writes_kb;unsigned int s_sec_num_apps;unsigned int s_sec_capacity_apps_kb;unsigned int s_sec_cond_fua_mode;#ifdef CONFIG_F2FS_SEC_BLOCK_OPERATIONS_DEBUGunsigned int s_sec_blkops_total;unsigned long long s_sec_blkops_max_elapsed;struct f2fs_sec_blkops_dbg s_sec_dbg_entries[F2FS_SEC_BLKOPS_ENTRIES];struct f2fs_sec_blkops_dbg s_sec_dbg_max_entry;
#endif
};
(3) struct super_block是VFS层描述超级块的结构体:
VFS描述文件系统使用超级块和inode 的方式,所谓超级块就是对所有文件系统的管理机构,每种文件系统都要把自己的信息挂到super_blocks这么一个全局链表上。
内核中是分成2个步骤完成:首先每个文件系统必须通过register_filesystem函数将自己的file_system_type挂接到file_systems这个全局变量上,
然后调用kern_mount函数把自己的文件相关操作函数集合表挂到super_blocks上。每种文件系统类型的读超级块的例程(get_sb)必须由自己实现。
文件系统由子目录和文件构成。每个子目录和文件只能由唯一的inode 描述。inode 是Linux管理文件系统的最基本单位,也是文件系统连接任何子目录、文件的桥梁。
VFS inode的内容取自物理设备上的文件系统,由文件系统指定的操作函数(i_op 属性指定)填写。VFS inode只存在于内存中,可通过inode缓存访问。
struct super_block {struct list_head s_list; /* Keep this first */dev_t s_dev; /* search index; _not_ kdev_t */unsigned char s_blocksize_bits;unsigned long s_blocksize;loff_t s_maxbytes; /* Max file size */struct file_system_type *s_type;const struct super_operations *s_op;const struct dquot_operations *dq_op;const struct quotactl_ops *s_qcop;const struct export_operations *s_export_op;unsigned long s_flags;unsigned long s_iflags; /* internal SB_I_* flags */unsigned long s_magic;struct dentry *s_root;struct rw_semaphore s_umount;int s_count;atomic_t s_active;
#ifdef CONFIG_SECURITYvoid *s_security;
#endifconst struct xattr_handler **s_xattr;
#ifdef CONFIG_FS_ENCRYPTIONconst struct fscrypt_operations *s_cop;
#endifstruct hlist_bl_head s_roots; /* alternate root dentries for NFS */struct list_head s_mounts; /* list of mounts; _not_ for fs use */struct block_device *s_bdev;struct backing_dev_info *s_bdi;struct mtd_info *s_mtd;struct hlist_node s_instances;unsigned int s_quota_types; /* Bitmask of supported quota types */struct quota_info s_dquot; /* Diskquota specific options */struct sb_writers s_writers;char s_id[32]; /* Informational name */uuid_t s_uuid; /* UUID */void *s_fs_info; /* Filesystem private info */unsigned int s_max_links;fmode_t s_mode;/* Granularity of c/m/atime in ns.Cannot be worse than a second */u32 s_time_gran;/** The next field is for VFS *only*. No filesystems have any business* even looking at it. You had been warned.*/struct mutex s_vfs_rename_mutex; /* Kludge *//** Filesystem subtype. If non-empty the filesystem type field* in /proc/mounts will be "type.subtype"*/char *s_subtype;const struct dentry_operations *s_d_op; /* default d_op for dentries *//** Saved pool identifier for cleancache (-1 means none)*/int cleancache_poolid;struct shrinker s_shrink; /* per-sb shrinker handle *//* Number of inodes with nlink == 0 but still referenced */atomic_long_t s_remove_count;/* Pending fsnotify inode refs */atomic_long_t s_fsnotify_inode_refs;/* Being remounted read-only */int s_readonly_remount;/* AIO completions deferred from interrupt context */struct workqueue_struct *s_dio_done_wq;struct hlist_head s_pins;/** Owning user namespace and default context in which to* interpret filesystem uids, gids, quotas, device nodes,* xattrs and security labels.*/struct user_namespace *s_user_ns;/** Keep the lru lists last in the structure so they always sit on their* own individual cachelines.*/struct list_lru s_dentry_lru ____cacheline_aligned_in_smp;struct list_lru s_inode_lru ____cacheline_aligned_in_smp;struct rcu_head rcu;struct work_struct destroy_work;struct mutex s_sync_lock; /* sync serialisation lock *//** Indicates how deep in a filesystem stack this SB is*/int s_stack_depth;/* s_inode_list_lock protects s_inodes */spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp;struct list_head s_inodes; /* all inodes */spinlock_t s_inode_wblist_lock;struct list_head s_inodes_wb; /* writeback inodes */
} __randomize_layout;
所有的super_block都存在于 super_blocks(VFS管理层) 链表中:
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);
static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
{struct f2fs_sb_info *sbi;struct f2fs_super_block *raw_super;struct inode *root;int err;bool skip_recovery = false, need_fsck = false;char *options = NULL;char *orig_data = kstrdup(data, GFP_KERNEL);int recovery, i, valid_super_block;struct curseg_info *seg_i;int retry_cnt = 1;try_onemore:err = -EINVAL;raw_super = NULL;valid_super_block = -1;recovery = 0;/* allocate memory for f2fs-specific super block info */sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);if (!sbi)return -ENOMEM;sbi->sb = sb;/* Load the checksum driver */sbi->s_chksum_driver = crypto_alloc_shash("crc32", 0, 0);if (IS_ERR(sbi->s_chksum_driver)) {f2fs_msg(sb, KERN_ERR, "Cannot load crc32 driver.");err = PTR_ERR(sbi->s_chksum_driver);sbi->s_chksum_driver = NULL;goto free_sbi;}/* set a block size */if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) {f2fs_msg(sb, KERN_ERR, "unable to set blocksize");goto free_sbi;}err = read_raw_super_block(sbi, &raw_super, &valid_super_block,&recovery, retry_cnt);if (err)goto free_sbi;sb->s_fs_info = sbi;sbi->raw_super = raw_super;/* precompute checksum seed for metadata */if (f2fs_sb_has_inode_chksum(sbi))sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid,sizeof(raw_super->uuid));/** The BLKZONED feature indicates that the drive was formatted with* zone alignment optimization. This is optional for host-aware* devices, but mandatory for host-managed zoned block devices.*/
#ifndef CONFIG_BLK_DEV_ZONEDif (f2fs_sb_has_blkzoned(sbi)) {f2fs_msg(sb, KERN_ERR,"Zoned block device support is not enabled");err = -EOPNOTSUPP;goto free_sb_buf;}
#endifdefault_options(sbi, false);/* parse mount options */options = kstrdup((const char *)data, GFP_KERNEL);if (data && !options) {err = -ENOMEM;goto free_sb_buf;}err = parse_options(sb, options);if (err)goto free_options;sbi->max_file_blocks = max_file_blocks();sb->s_maxbytes = sbi->max_file_blocks <<le32_to_cpu(raw_super->log_blocksize);sb->s_max_links = F2FS_LINK_MAX;#ifdef CONFIG_QUOTAsb->dq_op = &f2fs_quota_operations;sb->s_qcop = &f2fs_quotactl_ops;sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;if (f2fs_sb_has_quota_ino(sbi)) {for (i = 0; i < MAXQUOTAS; i++) {if (f2fs_qf_ino(sbi->sb, i))sbi->nquota_files++;}}
#endifsb->s_op = &f2fs_sops;
#ifdef CONFIG_FS_ENCRYPTIONsb->s_cop = &f2fs_cryptops;
#endifsb->s_xattr = f2fs_xattr_handlers;sb->s_export_op = &f2fs_export_ops;sb->s_magic = F2FS_SUPER_MAGIC;sb->s_time_gran = 1;sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |(test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0);memcpy(&sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));sb->s_iflags |= SB_I_CGROUPWB;/* init f2fs-specific super block info */sbi->valid_super_block = valid_super_block;mutex_init(&sbi->gc_mutex);mutex_init(&sbi->writepages);mutex_init(&sbi->cp_mutex);init_rwsem(&sbi->node_write);init_rwsem(&sbi->node_change);/* disallow all the data/node/meta page writes */set_sbi_flag(sbi, SBI_POR_DOING);spin_lock_init(&sbi->stat_lock);/* init iostat info */spin_lock_init(&sbi->iostat_lock);sbi->iostat_enable = false;for (i = 0; i < NR_PAGE_TYPE; i++) {int n = (i == META) ? 1: NR_TEMP_TYPE;int j;sbi->write_io[i] =f2fs_kmalloc(sbi,array_size(n,sizeof(struct f2fs_bio_info)),GFP_KERNEL);if (!sbi->write_io[i]) {err = -ENOMEM;goto free_bio_info;}for (j = HOT; j < n; j++) {init_rwsem(&sbi->write_io[i][j].io_rwsem);sbi->write_io[i][j].sbi = sbi;sbi->write_io[i][j].bio = NULL;spin_lock_init(&sbi->write_io[i][j].io_lock);INIT_LIST_HEAD(&sbi->write_io[i][j].io_list);}}init_rwsem(&sbi->cp_rwsem);init_waitqueue_head(&sbi->cp_wait);init_sb_info(sbi);err = init_percpu_info(sbi);if (err)goto free_bio_info;if (F2FS_IO_SIZE(sbi) > 1) {sbi->write_io_dummy =mempool_create_page_pool(2 * (F2FS_IO_SIZE(sbi) - 1), 0);if (!sbi->write_io_dummy) {err = -ENOMEM;goto free_percpu;}}/* get an inode for meta space */sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));if (IS_ERR(sbi->meta_inode)) {f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode");err = PTR_ERR(sbi->meta_inode);goto free_io_dummy;}err = f2fs_get_valid_checkpoint(sbi);if (err) {f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint");goto free_meta_inode;}if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_QUOTA_NEED_FSCK_FLAG))set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_DISABLED_QUICK_FLAG)) {set_sbi_flag(sbi, SBI_CP_DISABLED_QUICK);sbi->interval_time[DISABLE_TIME] = DEF_DISABLE_QUICK_INTERVAL;}/* Initialize device list */err = f2fs_scan_devices(sbi);if (err) {f2fs_msg(sb, KERN_ERR, "Failed to find devices");goto free_devices;}sbi->total_valid_node_count =le32_to_cpu(sbi->ckpt->valid_node_count);percpu_counter_set(&sbi->total_valid_inode_count,le32_to_cpu(sbi->ckpt->valid_inode_count));sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);sbi->total_valid_block_count =le64_to_cpu(sbi->ckpt->valid_block_count);sbi->last_valid_block_count = sbi->total_valid_block_count;sbi->reserved_blocks = 0;sbi->current_reserved_blocks = 0;limit_reserve_root(sbi);for (i = 0; i < NR_INODE_TYPE; i++) {INIT_LIST_HEAD(&sbi->inode_list[i]);spin_lock_init(&sbi->inode_lock[i]);}f2fs_init_extent_cache_info(sbi);f2fs_init_ino_entry_info(sbi);f2fs_init_fsync_node_info(sbi);/* setup checkpoint_cmd_control */err = f2fs_create_checkpoint_cmd_control(sbi);if (err) {f2fs_msg(sb, KERN_ERR,"Failed to initialize F2FS checkpoint_cmd_control");goto free_ccc;}/* setup f2fs internal modules */err = f2fs_build_segment_manager(sbi);if (err) {f2fs_msg(sb, KERN_ERR,"Failed to initialize F2FS segment manager");goto free_sm;}err = f2fs_build_node_manager(sbi);if (err) {f2fs_msg(sb, KERN_ERR,"Failed to initialize F2FS node manager");goto free_nm;}/* For write statistics */if (sb->s_bdev->bd_part)sbi->sectors_written_start =(u64)part_stat_read(sb->s_bdev->bd_part,sectors[STAT_WRITE]);/* Read accumulated write IO statistics if exists */seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE);if (__exist_node_summaries(sbi))sbi->kbytes_written =le64_to_cpu(seg_i->journal->info.kbytes_written);f2fs_build_gc_manager(sbi);err = f2fs_build_stats(sbi);if (err)goto free_nm;/* get an inode for node space */sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));if (IS_ERR(sbi->node_inode)) {f2fs_msg(sb, KERN_ERR, "Failed to read node inode");err = PTR_ERR(sbi->node_inode);goto free_stats;}/* read root inode and dentry */root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));if (IS_ERR(root)) {f2fs_msg(sb, KERN_ERR, "Failed to read root inode");err = PTR_ERR(root);goto free_node_inode;}if (!S_ISDIR(root->i_mode) || !root->i_blocks ||!root->i_size || !root->i_nlink) {iput(root);err = -EINVAL;goto free_node_inode;}sb->s_root = d_make_root(root); /* allocate root dentry */if (!sb->s_root) {err = -ENOMEM;goto free_node_inode;}err = f2fs_register_sysfs(sbi);if (err)goto free_root_inode;#ifdef CONFIG_QUOTA/* Enable quota usage during mount */if (f2fs_sb_has_quota_ino(sbi) && !f2fs_readonly(sb)) {err = f2fs_enable_quotas(sb);if (err)f2fs_msg(sb, KERN_ERR,"Cannot turn on quotas: error %d", err);}
#endif/* if there are nt orphan nodes free them */err = f2fs_recover_orphan_inodes(sbi);if (err)goto free_meta;if (unlikely(is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)))goto reset_checkpoint;/* recover fsynced data */if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {/** mount should be failed, when device has readonly mode, and* previous checkpoint was not done by clean system shutdown.*/if (f2fs_hw_is_readonly(sbi)) {if (!is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {err = -EROFS;f2fs_msg(sb, KERN_ERR,"Need to recover fsync data, but ""write access unavailable");goto free_meta;}f2fs_msg(sbi->sb, KERN_INFO, "write access ""unavailable, skipping recovery");goto reset_checkpoint;}if (need_fsck)set_sbi_flag(sbi, SBI_NEED_FSCK);if (skip_recovery)goto reset_checkpoint;err = f2fs_recover_fsync_data(sbi, false);if (err < 0) {if (err != -ENOMEM)skip_recovery = true;need_fsck = true;f2fs_msg(sb, KERN_ERR,"Cannot recover all fsync data errno=%d", err);goto free_meta;}} else {err = f2fs_recover_fsync_data(sbi, true);if (!f2fs_readonly(sb) && err > 0) {err = -EINVAL;f2fs_msg(sb, KERN_ERR,"Need to recover fsync data");goto free_meta;}}
reset_checkpoint:/* f2fs_recover_fsync_data() cleared this already */clear_sbi_flag(sbi, SBI_POR_DOING);if (test_opt(sbi, DISABLE_CHECKPOINT)) {err = f2fs_disable_checkpoint(sbi);if (err)goto sync_free_meta;} else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) {f2fs_enable_checkpoint(sbi);}/** If filesystem is not mounted as read-only then* do start the gc_thread.*/if (test_opt(sbi, BG_GC) && !f2fs_readonly(sb)) {/* After POR, we can run background GC thread.*/err = f2fs_start_gc_thread(sbi);if (err)goto sync_free_meta;}kvfree(options);/* recover broken superblock */if (recovery) {err = f2fs_commit_super(sbi, true);f2fs_msg(sb, KERN_INFO,"Try to recover %dth superblock, ret: %d",sbi->valid_super_block ? 1 : 2, err);}f2fs_join_shrinker(sbi);f2fs_tuning_parameters(sbi);f2fs_msg(sbi->sb, KERN_NOTICE, "Mounted with checkpoint version = %llx""Opts: %s", cur_cp_version(F2FS_CKPT(sbi)), orig_data);kfree(orig_data);f2fs_update_time(sbi, CP_TIME);f2fs_update_time(sbi, REQ_TIME);clear_sbi_flag(sbi, SBI_CP_DISABLED_QUICK);return 0;sync_free_meta:/* safe to flush all the data */sync_filesystem(sbi->sb);retry_cnt = 0;free_meta:
#ifdef CONFIG_QUOTAf2fs_truncate_quota_inode_pages(sb);if (f2fs_sb_has_quota_ino(sbi) && !f2fs_readonly(sb))f2fs_quota_off_umount(sbi->sb);
#endif/** Some dirty meta pages can be produced by f2fs_recover_orphan_inodes()* failed by EIO. Then, iput(node_inode) can trigger balance_fs_bg()* followed by f2fs_write_checkpoint() through f2fs_write_node_pages(), which* falls into an infinite loop in f2fs_sync_meta_pages().*/truncate_inode_pages_final(META_MAPPING(sbi));/* evict some inodes being cached by GC */evict_inodes(sb);f2fs_unregister_sysfs(sbi);
free_root_inode:dput(sb->s_root);sb->s_root = NULL;
free_node_inode:f2fs_release_ino_entry(sbi, true);truncate_inode_pages_final(NODE_MAPPING(sbi));iput(sbi->node_inode);sbi->node_inode = NULL;
free_stats:f2fs_destroy_stats(sbi);
free_nm:f2fs_destroy_node_manager(sbi);
free_sm:f2fs_destroy_segment_manager(sbi);
free_ccc:f2fs_destroy_checkpoint_cmd_control(sbi, true);
free_devices:destroy_device_list(sbi);kvfree(sbi->ckpt);
free_meta_inode:make_bad_inode(sbi->meta_inode);iput(sbi->meta_inode);sbi->meta_inode = NULL;
free_io_dummy:mempool_destroy(sbi->write_io_dummy);
free_percpu:destroy_percpu_info(sbi);
free_bio_info:for (i = 0; i < NR_PAGE_TYPE; i++)kvfree(sbi->write_io[i]);
free_options:
#ifdef CONFIG_QUOTAfor (i = 0; i < MAXQUOTAS; i++)kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
#endifkvfree(options);
free_sb_buf:kvfree(raw_super);
free_sbi:if (sbi->s_chksum_driver)crypto_free_shash(sbi->s_chksum_driver);kvfree(sbi);/* give only one another chance */if (retry_cnt > 0 && skip_recovery) {retry_cnt--;shrink_dcache_sb(sb);goto try_onemore;}kfree(orig_data);return err;
}
f2fs学习四: f2fs文件系统挂载相关推荐
- linux虚拟文件系统(四)-文件系统挂载操作分析
ext4文件系统挂载 大家可以使用以下命令挂载一个u盘到 /mnt目录下: mount -t ext4 /dev/sda1 /mnt 其中mount这个应用程序就是使用了mount函数进行系统调用,其 ...
- f2fs学习笔记 - 2. f2fs基础实验环境搭建
1.前言 本文主要记录如何搭建f2fs的环境,用于f2fs文件系统的学习.我们选用了f2fs第一个补丁提交前的内核版本:linux3.7.0.然后通过提取出f2fs的最小补丁来学习f2fs文件系统,这 ...
- Linux学习笔记1--Linux文件系统之CentOS7挂载U盘
Linux学习笔记(一) CentOS7挂载U盘 插入U盘连接虚拟机 打开终端 创建U盘目录 挂载U盘 卸载U盘 可能出现的bug Linux文件系统与Windows文件系统之比 二者文件系统具体 二 ...
- linux 内核 f2fs,f2fs系列之一:实战f2fs 下载、编译和挂载
f2fs (Flash-Friendly File System)有很多对SSD友好的特性,主要特性包括: 基于日志结构 聚焦于优化日志结构中的wander tree的雪崩效应和清除代价 此外,它还充 ...
- f2fs学习二:预分配
1. F2FS预分配介绍 F2FS Write分为direct io和buffer io, 下文内容均以direct io方式说明. F2FS在Write的时候,会进行预分配Data分区的logica ...
- Zynq-Linux移植学习笔记之32-SPI FLASH文件系统挂载
1.背景介绍 板上zynq通过spi-1连接一片SPI FLASH,型号为n25q128a11.示意图如下: 由于之前都是通过EMC挂载NOR FLASH,这是第一次使用SPI FLASH挂载文件系统 ...
- 【无标题】STM32F407VGT6文件系统挂载TF卡学习笔记CUBEMXKEIL5
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一.CUBEMX配置 二.添加代码main.c文件 1.main函数定义变量 2.文件系统函数 三.调试结果 总结 前言 ...
- Docker学习四:Docker 网络
前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...
- SigmaStar SSD202 openwrt 系统下ubi根文件系统挂载过程
关于UBI介绍可以参考官方文档 http://www.linux-mtd.infradead.org/doc/ubifs.html 下面是一张简介图,大概的介绍就是UBIFS依赖kernel UBI子 ...
- Qt SD卡 文件系统挂载、文件预览
/*********************************************************************************** Qt SD卡 文件系统挂载.文 ...
最新文章
- 升序排列python_Python3基础 sort 将一个列表中的值升序排列
- 【论文解读】Knowledge Review:知识蒸馏新解法
- 在使用Gradle构建的Spring Boot应用程序中覆盖Spring Framework版本
- 小程序原生组件调用mpvue父组件方法
- 云服务已一步一步“入侵”我们生活
- 三国中最精辟的十句话
- java 内核驱动程序_内核第三讲,进入ring0,以及编写第一个内核驱动程序.
- 运算符 python
- AI开发者看过来,主流移动端深度学习框架大盘点
- 59. Event 例子
- Unity3D之Json序列化
- 小小方法,问题锦集。
- matlab 安装教程:matlab 2016a(matlab R2016a)
- ElementUI中前端分页的实现
- 英语时态=时间+状态
- 学会忘记其实是一种美德
- Ansible主机清单—inventory主机清单
- 解读BLM业务领先模型中的业务设计
- java中pack什么意思_java – .pack()做什么?
- 数据仓库系列(3):数据的价值如何体现
热门文章
- 日记html模板,【精选】初二日记模板集锦7篇
- NI Multisim 14.0蜂鸣器为什么不响_Multisim软件操作介绍及记分电路的绘制
- 读文献--《机器学习隐私保护研究综述》
- 华为手机热点无法连接_华为手机开热点,连不上怎么破
- FFmpeg拼接文件常见问题
- #金项奖获奖项目专题# | 京东闪付---快人一步
- 中南天坑专业到武大计算机的考研分享~
- linux dump备份svn,svnadmin dump+load库中的某个目录用svndumpfilter 可实现
- EAGLE layout 拼板方法
- C++第三方库管理工具vcpkg使用教程