示例#1
0
static int validate_superblock(struct super_block *sb,
		struct f2fs_super_block **raw_super,
		struct buffer_head **raw_super_buf, sector_t block)
{
	const char *super = (block == 0 ? "first" : "second");

	/* read f2fs raw super block */
	*raw_super_buf = sb_bread(sb, block);
	if (!*raw_super_buf) {
		f2fs_msg(sb, KERN_ERR, "unable to read %s superblock",
				super);
		return -EIO;
	}

	*raw_super = (struct f2fs_super_block *)
		((char *)(*raw_super_buf)->b_data + F2FS_SUPER_OFFSET);

	/* sanity checking of raw super */
	if (!sanity_check_raw_super(sb, *raw_super))
		return 0;

	f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem "
				"in %s superblock", super);
	return -EINVAL;
}
示例#2
0
/*
 * Read f2fs raw super block.
 * Because we have two copies of super block, so read the first one at first,
 * if the first one is invalid, move to read the second one.
 */
static int read_raw_super_block(struct super_block *sb,
			struct f2fs_super_block **raw_super,
			int *valid_super_block, int *recovery)
{
	int block = 0;
	struct buffer_head *bh;
	struct f2fs_super_block *super, *buf;
	int err = 0;

	super = kzalloc(sizeof(struct f2fs_super_block), GFP_KERNEL);
	if (!super)
		return -ENOMEM;
retry:
	bh = sb_bread(sb, block);
	if (!bh) {
		*recovery = 1;
		f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock",
				block + 1);
		err = -EIO;
		goto next;
	}

	buf = (struct f2fs_super_block *)(bh->b_data + F2FS_SUPER_OFFSET);

	/* sanity checking of raw super */
	if (sanity_check_raw_super(sb, buf)) {
		brelse(bh);
		*recovery = 1;
		f2fs_msg(sb, KERN_ERR,
			"Can't find valid F2FS filesystem in %dth superblock",
								block + 1);
		err = -EINVAL;
		goto next;
	}

	if (!*raw_super) {
		memcpy(super, buf, sizeof(*super));
		*valid_super_block = block;
		*raw_super = super;
	}
	brelse(bh);

next:
	/* check the validity of the second superblock */
	if (block == 0) {
		block++;
		goto retry;
	}

	/* No valid superblock */
	if (!*raw_super) {
		kfree(super);
		return err;
	}

	return 0;
}
示例#3
0
/*
 * Read f2fs raw super block.
 * Because we have two copies of super block, so read both of them
 * to get the first valid one. If any one of them is broken, we pass
 * them recovery flag back to the caller.
 */
static int read_raw_super_block(struct super_block *sb,
			struct f2fs_super_block **raw_super,
			int *valid_super_block, int *recovery)
{
	int block;
	struct buffer_head *bh;
	struct f2fs_super_block *super, *buf;
	int err = 0;

	super = kzalloc(sizeof(struct f2fs_super_block), GFP_KERNEL);
	if (!super)
		return -ENOMEM;

	for (block = 0; block < 2; block++) {
		bh = sb_bread(sb, block);
		if (!bh) {
			f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock",
				block + 1);
			err = -EIO;
			continue;
		}

		buf = (struct f2fs_super_block *)
				(bh->b_data + F2FS_SUPER_OFFSET);

		/* sanity checking of raw super */
		if (sanity_check_raw_super(sb, buf)) {
			f2fs_msg(sb, KERN_ERR,
				"Can't find valid F2FS filesystem in %dth superblock",
				block + 1);
			err = -EINVAL;
			brelse(bh);
			continue;
		}

		if (!*raw_super) {
			memcpy(super, buf, sizeof(*super));
			*valid_super_block = block;
			*raw_super = super;
		}
		brelse(bh);
	}

	/* Fail to read any one of the superblocks*/
	if (err < 0)
		*recovery = 1;

	/* No valid superblock */
	if (!*raw_super)
		kfree(super);
	else
		err = 0;

	return err;
}
/*
 * Read f2fs raw super block.
 * Because we have two copies of super block, so read the first one at first,
 * if the first one is invalid, move to read the second one.
 */
static int read_raw_super_block(struct super_block *sb,
			struct f2fs_super_block **raw_super,
			struct buffer_head **raw_super_buf)
{
	int block = 0;

retry:
	*raw_super_buf = sb_bread(sb, block);
	if (!*raw_super_buf) {
		f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock",
				block + 1);
		if (block == 0) {
			block++;
			goto retry;
		} else {
			return -EIO;
		}
	}

	*raw_super = (struct f2fs_super_block *)
		((char *)(*raw_super_buf)->b_data + F2FS_SUPER_OFFSET);

	/* sanity checking of raw super */
	if (sanity_check_raw_super(sb, *raw_super)) {
		brelse(*raw_super_buf);
		f2fs_msg(sb, KERN_ERR,
			"Can't find valid F2FS filesystem in %dth superblock",
								block + 1);
		if (block == 0) {
			block++;
			goto retry;
		} else {
			return -EINVAL;
		}
	}

	return 0;
}
示例#5
0
/*
 * Read f2fs raw super block.
 * Because we have two copies of super block, so read the first one at first,
 * if the first one is invalid, move to read the second one.
 */
static int read_raw_super_block(struct super_block *sb,
			struct f2fs_super_block **raw_super,
			struct buffer_head **raw_super_buf,
			int *recovery)
{
	int block = 0;
	struct buffer_head *buffer;
	struct f2fs_super_block *super;
	int err = 0;

retry:
	buffer = sb_bread(sb, block);
	if (!buffer) {
		*recovery = 1;
		f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock",
				block + 1);
		if (block == 0) {
			block++;
			goto retry;
		} else {
			err = -EIO;
			goto out;
		}
	}

	super = (struct f2fs_super_block *)
		((char *)(buffer)->b_data + F2FS_SUPER_OFFSET);

	/* sanity checking of raw super */
	if (sanity_check_raw_super(sb, super)) {
		brelse(buffer);
		*recovery = 1;
		f2fs_msg(sb, KERN_ERR,
			"Can't find valid F2FS filesystem in %dth superblock",
								block + 1);
		if (block == 0) {
			block++;
			goto retry;
		} else {
			err = -EINVAL;
			goto out;
		}
	}

	if (!*raw_super) {
		*raw_super_buf = buffer;
		*raw_super = super;
	} else {
		/* already have a valid superblock */
		brelse(buffer);
	}

	/* check the validity of the second superblock */
	if (block == 0) {
		block++;
		goto retry;
	}

out:
	/* No valid superblock */
	if (!*raw_super)
		return err;

	return 0;
}
示例#6
0
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 buffer_head *raw_super_buf;
	struct inode *root;
	int i;

	/* allocate memory for f2fs-specific super block info */
	sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;

	/* set a temporary block size */
	if (!sb_set_blocksize(sb, F2FS_BLKSIZE))
		goto free_sbi;

	/* read f2fs raw super block */
	raw_super_buf = sb_bread(sb, F2FS_SUPER_OFFSET);
	if (!raw_super_buf)
		goto free_sbi;
	raw_super = (struct f2fs_super_block *) ((char *)raw_super_buf->b_data);

	/* init some FS parameters */
	set_opt(sbi, BG_GC);

#ifdef CONFIG_F2FS_FS_XATTR
	set_opt(sbi, XATTR_USER);
#endif
#ifdef CONFIG_F2FS_FS_POSIX_ACL
	set_opt(sbi, POSIX_ACL);
#endif
	/* parse mount options */
	if (parse_options(sbi, (char *)data))
		goto free_sb_buf;

	/* sanity checking of raw super */
	if (sanity_check_raw_super(raw_super))
		goto free_sb_buf;

	sb->s_maxbytes = max_file_size(raw_super->log_blocksize);
	sb->s_op = &f2fs_sops;
	sb->s_xattr = f2fs_xattr_handlers;
	sb->s_magic = F2FS_SUPER_MAGIC;
	sb->s_fs_info = sbi;
	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
		(test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);

	/* init f2fs-specific super block info */
	sbi->sb = sb;
	sbi->raw_super = raw_super;
	sbi->raw_super_buf = raw_super_buf;
	mutex_init(&sbi->gc_mutex);
	mutex_init(&sbi->write_inode);
	mutex_init(&sbi->writepages);
	mutex_init(&sbi->cp_mutex);
	for (i = 0; i < NR_LOCK_TYPE; i++)
		mutex_init(&sbi->fs_lock[i]);
	sbi->por_doing = 0;
	spin_lock_init(&sbi->stat_lock);
	init_rwsem(&sbi->bio_sem);
	init_sb_info(sbi);

	/* get an inode for meta space */
	sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
	if (IS_ERR(sbi->meta_inode))
		goto free_sb_buf;

	if (get_valid_checkpoint(sbi))
		goto free_meta_inode;

	/* sanity checking of checkpoint */
	if (sanity_check_ckpt(raw_super, sbi->ckpt))
		goto free_cp;

	sbi->total_valid_node_count =
				le32_to_cpu(sbi->ckpt->valid_node_count);
	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->alloc_valid_block_count = 0;
	INIT_LIST_HEAD(&sbi->dir_inode_list);
	spin_lock_init(&sbi->dir_inode_lock);

	/* init super block */
	if (!sb_set_blocksize(sb, sbi->blocksize))
		goto free_cp;

	init_orphan_info(sbi);

	/* setup f2fs internal modules */
	if (build_segment_manager(sbi))
		goto free_sm;
	if (build_node_manager(sbi))
		goto free_nm;
	if (build_gc_manager(sbi))
		goto free_gc;

	/* get an inode for node space */
	sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
	if (IS_ERR(sbi->node_inode))
		goto free_gc;

	/* if there are nt orphan nodes free them */
	if (recover_orphan_inodes(sbi))
		goto free_node_inode;

	/* read root inode and dentry */
	root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
	if (IS_ERR(root))
		goto free_node_inode;
	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size)
		goto free_root_inode;

	sb->s_root = d_alloc_root(root); /* allocate root dentry */
	if (!sb->s_root)
		goto free_root_inode;

	/* recover fsynced data */
	if (!test_opt(sbi, DISABLE_ROLL_FORWARD))
		recover_fsync_data(sbi);

	/* After POR, we can run background GC thread */
	if (start_gc_thread(sbi))
		goto fail;

#ifdef CONFIG_F2FS_STAT_FS
	if (f2fs_proc_root) {
		sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
		if (f2fs_stat_init(sbi))
			goto fail;
	}
#endif
	return 0;
fail:
	stop_gc_thread(sbi);
free_root_inode:
	make_bad_inode(root);
	iput(root);
free_node_inode:
	make_bad_inode(sbi->node_inode);
	iput(sbi->node_inode);
free_gc:
	destroy_gc_manager(sbi);
free_nm:
	destroy_node_manager(sbi);
free_sm:
	destroy_segment_manager(sbi);
free_cp:
	kfree(sbi->ckpt);
free_meta_inode:
	make_bad_inode(sbi->meta_inode);
	iput(sbi->meta_inode);
free_sb_buf:
	brelse(raw_super_buf);
free_sbi:
	kfree(sbi);
	return -EINVAL;
}