Linux内核文件系统14

2021SC@SDUSC

super.c(1)

接下来分析另一个核心部分super.c文件。

这个文件中存的是文件系统里超级块(super_block)的相关函数,对于文件系统有极大的重要性。并且这个文件代码量也很大,还是分次进行介绍。

锁排序

注意i_mmap_sem (EXT4_I(inode)->i_mmap_sem)和i_mmap_rwsem (inode->i_mmap_rwsem)之间的区别

页面错误路径:

mmap_lock -> sb_start_pagefault -> i_mmap_sem (r) -> transaction start -> page lock -> i_data_sem (rw)

缓冲写路径:

sb_start_write -> i_mutex -> mmap_lock

b_start_write -> i_mutex -> transaction start -> page lock -> i_data_sem (rw)

截断:

sb_start_write -> i_mutex -> i_mmap_sem (w) -> i_mmap_rwsem (w) ->page lock

sb_start_write -> i_mutex -> i_mmap_sem (w) -> transaction start -> i_data_sem (rw)

直接输入输出:

sb_start_write -> i_mutex -> mmap_lock

b_start_write -> i_mutex -> transaction start -> i_data_sem (rw)

写页面:

transaction start -> page lock(s) -> i_data_sem (rw)

/* super.c里会使用到的函数的声明 */
static struct ext4_lazy_init *ext4_li_info;
static DEFINE_MUTEX(ext4_li_mtx);
static struct ratelimit_state ext4_mount_msg_ratelimit;

static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
			     unsigned long journal_devnum);
static int ext4_show_options(struct seq_file *seq, struct dentry *root);
static void ext4_update_super(struct super_block *sb);
static int ext4_commit_super(struct super_block *sb);
static int ext4_mark_recovery_complete(struct super_block *sb,
					struct ext4_super_block *es);
static int ext4_clear_journal_err(struct super_block *sb,
				  struct ext4_super_block *es);
static int ext4_sync_fs(struct super_block *sb, int wait);
static int ext4_remount(struct super_block *sb, int *flags, char *data);
static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
static int ext4_unfreeze(struct super_block *sb);
static int ext4_freeze(struct super_block *sb);
static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
		       const char *dev_name, void *data);
static inline int ext2_feature_set_ok(struct super_block *sb);
static inline int ext3_feature_set_ok(struct super_block *sb);
static int ext4_feature_set_ok(struct super_block *sb, int readonly);
static void ext4_destroy_lazyinit_thread(void);
static void ext4_unregister_li_request(struct super_block *sb);
static void ext4_clear_request_list(void);
static struct inode *ext4_get_journal_inode(struct super_block *sb,
					    unsigned int journal_inum);

/*
 *工作方式类似于__bread_gfp(),但它使用ERR_PTR作为错误返回。
 *目前使用sb_bread是不可能区分ENOMEM和EIO情况的(因为这两种情况都会导致NULL返回)。
 */
static struct buffer_head *__ext4_sb_bread_gfp(struct super_block *sb,
					       sector_t block, int op_flags,
					       gfp_t gfp)
{
	struct buffer_head *bh;
	int ret;

	bh = sb_getblk_gfp(sb, block, gfp);
	if (bh == NULL)
		return ERR_PTR(-ENOMEM);
	if (ext4_buffer_uptodate(bh))
		return bh;

	ret = ext4_read_bh_lock(bh, REQ_META | op_flags, true);
	if (ret) {
		put_bh(bh);
		return ERR_PTR(ret);
	}
	return bh;
}


/*
 del_gendisk()函数不初始化特定于磁盘的数据结构,包括bdi结构,而不告诉其他人。
 一旦发生这种情况,任何调用mark_buffer_dirty()的尝试(例如,通过ext4_commit_super)都将导致内核OOPS。
 在del_gendisk()中放入适当的钩子来通知VFS和文件系统层之前,这是一个防止出现这些错误的杂项。
 */
static int block_device_ejected(struct super_block *sb)
{
	struct inode *bd_inode = sb->s_bdev->bd_inode;
	struct backing_dev_info *bdi = inode_to_bdi(bd_inode);

	return bdi->dev == NULL;
}

static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
{
	struct super_block		*sb = journal->j_private;
	struct ext4_sb_info		*sbi = EXT4_SB(sb);
	int				error = is_journal_aborted(journal);
	struct ext4_journal_cb_entry	*jce;

	BUG_ON(txn->t_state == T_FINISHED);

	ext4_process_freed_data(sb, txn->t_tid);

	spin_lock(&sbi->s_md_lock);
	while (!list_empty(&txn->t_private_list)) {
		jce = list_entry(txn->t_private_list.next,
				 struct ext4_journal_cb_entry, jce_list);
		list_del_init(&jce->jce_list);
		spin_unlock(&sbi->s_md_lock);
		jce->jce_func(sb, jce, error);
		spin_lock(&sbi->s_md_lock);
	}
	spin_unlock(&sbi->s_md_lock);
}

/*
 *这个write_cache_pages()的write_cache_pages回调函数处理了一些页面清理后的情况。
 * write_cache_pages()已经检查脏页并调用clear_page_dirty_for_io(),这是我们想要的,写保护页。
 *然而,我们可能不得不重脏一个页面(见下面)。
 */
static int ext4_journalled_writepage_callback(struct page *page,
					      struct writeback_control *wbc,
					   
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值