Commit 25ca923b authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

f2fs: fix endian conversion bugs reported by sparse



This patch should resolve the bugs reported by the sparse tool.
Initial reports were written by "kbuild test robot" managed by fengguang.wu.

In my local machines, I've tested also by running:
> make C=2 CF="-D__CHECK_ENDIAN__"

Accordingly, I've found lots of warnings and bugs related to the endian
conversion. And I've fixed all at this moment.

Signed-off-by: default avatarJaegeuk Kim <jaegeuk.kim@samsung.com>
parent cf0e3a64
Loading
Loading
Loading
Loading
+17 −15
Original line number Diff line number Diff line
@@ -268,7 +268,7 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
{
	block_t start_blk, orphan_blkaddr, i, j;

	if (!(F2FS_CKPT(sbi)->ckpt_flags & CP_ORPHAN_PRESENT_FLAG))
	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
		return 0;

	sbi->por_doing = 1;
@@ -287,7 +287,7 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
		f2fs_put_page(page, 1);
	}
	/* clear Orphan Flag */
	F2FS_CKPT(sbi)->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
	clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG);
	sbi->por_doing = 0;
	return 0;
}
@@ -376,7 +376,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
	pre_version = le64_to_cpu(cp_block->checkpoint_ver);

	/* Read the 2nd cp block in this CP pack */
	cp_addr += le64_to_cpu(cp_block->cp_pack_total_block_count) - 1;
	cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
	cp_page_2 = get_meta_page(sbi, cp_addr);

	cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2);
@@ -605,8 +605,8 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
	block_t start_blk;
	struct page *cp_page;
	unsigned int data_sum_blocks, orphan_blocks;
	unsigned int crc32 = 0;
	void *kaddr;
	__u32 crc32 = 0;
	int i;

	/* Flush all the NAT/SIT pages */
@@ -646,33 +646,35 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
	/* 2 cp  + n data seg summary + orphan inode blocks */
	data_sum_blocks = npages_for_summary_flush(sbi);
	if (data_sum_blocks < 3)
		ckpt->ckpt_flags |= CP_COMPACT_SUM_FLAG;
		set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
	else
		ckpt->ckpt_flags &= (~CP_COMPACT_SUM_FLAG);
		clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);

	orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
					/ F2FS_ORPHANS_PER_BLOCK;
	ckpt->cp_pack_start_sum = 1 + orphan_blocks;
	ckpt->cp_pack_total_block_count = 2 + data_sum_blocks + orphan_blocks;
	ckpt->cp_pack_start_sum = cpu_to_le32(1 + orphan_blocks);

	if (is_umount) {
		ckpt->ckpt_flags |= CP_UMOUNT_FLAG;
		ckpt->cp_pack_total_block_count += NR_CURSEG_NODE_TYPE;
		set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
			data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE);
	} else {
		ckpt->ckpt_flags &= (~CP_UMOUNT_FLAG);
		clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
			data_sum_blocks + orphan_blocks);
	}

	if (sbi->n_orphans)
		ckpt->ckpt_flags |= CP_ORPHAN_PRESENT_FLAG;
		set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
	else
		ckpt->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
		clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);

	/* update SIT/NAT bitmap */
	get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
	get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));

	crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset));
	*(__u32 *)((unsigned char *)ckpt +
	*(__le32 *)((unsigned char *)ckpt +
				le32_to_cpu(ckpt->checksum_offset))
				= cpu_to_le32(crc32);

@@ -716,7 +718,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
	sbi->alloc_valid_block_count = 0;

	/* Here, we only have one bio having CP pack */
	if (sbi->ckpt->ckpt_flags & CP_ERROR_FLAG)
	if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))
		sbi->sb->s_flags |= MS_RDONLY;
	else
		sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
+1 −1
Original line number Diff line number Diff line
@@ -545,7 +545,7 @@ redirty_out:

#define MAX_DESIRED_PAGES_WP	4096

int f2fs_write_data_pages(struct address_space *mapping,
static int f2fs_write_data_pages(struct address_space *mapping,
			    struct writeback_control *wbc)
{
	struct inode *inode = mapping->host;
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
static LIST_HEAD(f2fs_stat_list);
static struct dentry *debugfs_root;

void update_general_status(struct f2fs_sb_info *sbi)
static void update_general_status(struct f2fs_sb_info *sbi)
{
	struct f2fs_stat_info *si = sbi->stat_info;
	int i;
+4 −4
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ static bool early_match_name(const char *name, int namelen,
	if (le16_to_cpu(de->name_len) != namelen)
		return false;

	if (le32_to_cpu(de->hash_code) != namehash)
	if (de->hash_code != namehash)
		return false;

	return true;
@@ -143,7 +143,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
	nbucket = dir_buckets(level);
	nblock = bucket_blocks(level);

	bidx = dir_block_index(level, namehash % nbucket);
	bidx = dir_block_index(level, le32_to_cpu(namehash) % nbucket);
	end_block = bidx + nblock;

	for (; bidx < end_block; bidx++) {
@@ -406,7 +406,7 @@ start:
	nbucket = dir_buckets(level);
	nblock = bucket_blocks(level);

	bidx = dir_block_index(level, (dentry_hash % nbucket));
	bidx = dir_block_index(level, (le32_to_cpu(dentry_hash) % nbucket));

	for (block = bidx; block <= (bidx + nblock - 1); block++) {
		mutex_lock_op(sbi, DENTRY_OPS);
@@ -437,7 +437,7 @@ add_dentry:
	wait_on_page_writeback(dentry_page);

	de = &dentry_blk->dentry[bit_pos];
	de->hash_code = cpu_to_le32(dentry_hash);
	de->hash_code = dentry_hash;
	de->name_len = cpu_to_le16(namelen);
	memcpy(dentry_blk->filename[bit_pos], name, namelen);
	de->ino = cpu_to_le32(inode->i_ino);
+23 −2
Original line number Diff line number Diff line
@@ -463,6 +463,26 @@ static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi)
	sbi->s_dirty = 0;
}

static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
{
	unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
	return ckpt_flags & f;
}

static inline void set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
{
	unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
	ckpt_flags |= f;
	cp->ckpt_flags = cpu_to_le32(ckpt_flags);
}

static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
{
	unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
	ckpt_flags &= (~f);
	cp->ckpt_flags = cpu_to_le32(ckpt_flags);
}

static inline void mutex_lock_op(struct f2fs_sb_info *sbi, enum lock_type t)
{
	mutex_lock_nested(&sbi->fs_lock[t], t);
@@ -577,7 +597,8 @@ static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
{
	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
	int offset = (flag == NAT_BITMAP) ? ckpt->sit_ver_bitmap_bytesize : 0;
	int offset = (flag == NAT_BITMAP) ?
			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
	return &ckpt->sit_nat_version_bitmap + offset;
}

@@ -587,7 +608,7 @@ static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
	unsigned long long ckpt_version = le64_to_cpu(ckpt->checkpoint_ver);

	start_addr = le64_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
	start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);

	/*
	 * odd numbered checkpoint should at cp segment 0
Loading