f2fs: fix endian conversion bugs reported by sparse
authorJaegeuk Kim <jaegeuk.kim@samsung.com>
Wed, 28 Nov 2012 07:12:41 +0000 (16:12 +0900)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Tue, 11 Dec 2012 04:43:42 +0000 (13:43 +0900)
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: Jaegeuk Kim <jaegeuk.kim@samsung.com>
12 files changed:
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/debug.c
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/hash.c
fs/f2fs/node.c
fs/f2fs/node.h
fs/f2fs/recovery.c
fs/f2fs/segment.c
fs/f2fs/super.c
include/linux/f2fs_fs.h

index ab743f92ee06ab141c8e4096892526731b2031ea..7c18f8efaadc3ea9723e4191b4afd4246f322074 100644 (file)
@@ -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);
index c2fd0a80db16ef2d824eba571aa9ba5e52f5f4f1..5635cc5a9d4dc06cf1e2fb9ee3abecd5ad68c0a1 100644 (file)
@@ -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;
index a56181c1b28b1e40af69fd250fcd70197b65bc9b..fb62960a1dc196052355f0704ac90c7be55f0f8e 100644 (file)
@@ -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;
index 5975568d03dff4887464f17e6974ee8c0c266381..5ec7a06120e18abd33e523b04851c2426f360008 100644 (file)
@@ -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);
index d3f5a70e2a495b17443713ec30551d145fdbda68..8d7fde1bda1ef43128e6770b80294e9626d649c9 100644 (file)
@@ -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
index 098a1963d7c73a004176c1450355a17f999160ef..beb155e8d06d6d5f22c791c611c61029c5a51659 100644 (file)
@@ -92,7 +92,6 @@ f2fs_hash_t f2fs_dentry_hash(const char *name, int len)
        hash = buf[0];
        minor_hash = buf[1];
 
-       f2fs_hash = hash;
-       f2fs_hash &= ~F2FS_HASH_COL_BIT;
+       f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
        return f2fs_hash;
 }
index 216f04dc1177f5442f7c401f974ec26e2427b3f0..5d421fe225758945f9642850dba39b280dcdbf80 100644 (file)
@@ -1445,8 +1445,8 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
 
        memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i);
        dst->i.i_size = 0;
-       dst->i.i_blocks = 1;
-       dst->i.i_links = 1;
+       dst->i.i_blocks = cpu_to_le64(1);
+       dst->i.i_links = cpu_to_le32(1);
        dst->i.i_xattr_nid = 0;
 
        new_ni = old_ni;
index 5d525ed312ba7704d4202a5365dc0938120e0949..0ab92d6430520fa37fcaa620b693d54adf0e1fad 100644 (file)
@@ -177,7 +177,7 @@ static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr)
        void *kaddr = page_address(page);
        struct f2fs_node *rn = (struct f2fs_node *)kaddr;
        rn->footer.cp_ver = ckpt->checkpoint_ver;
-       rn->footer.next_blkaddr = blkaddr;
+       rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
 }
 
 static inline nid_t ino_of_node(struct page *node_page)
index 7a43df0b72c19a4b04190f5771c193b0115acb3a..222a7bb922140120d648a6f3439191b7a6398228 100644 (file)
@@ -81,7 +81,7 @@ static int recover_inode(struct inode *inode, struct page *node_page)
        struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
        struct f2fs_inode *raw_inode = &(raw_node->i);
 
-       inode->i_mode = le32_to_cpu(raw_inode->i_mode);
+       inode->i_mode = le16_to_cpu(raw_inode->i_mode);
        i_size_write(inode, le64_to_cpu(raw_inode->i_size));
        inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
        inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
index ed7c079cfc7fc796c47b0ccfb0c32072757e7cbf..d973c56e8bd6a4b0e4e5b537b38ab69bc84d87fc 100644 (file)
@@ -630,7 +630,7 @@ static void f2fs_end_io_write(struct bio *bio, int err)
                        SetPageError(page);
                        if (page->mapping)
                                set_bit(AS_EIO, &page->mapping->flags);
-                       p->sbi->ckpt->ckpt_flags |= CP_ERROR_FLAG;
+                       set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG);
                        set_page_dirty(page);
                }
                end_page_writeback(page);
@@ -1067,7 +1067,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
                segno = le32_to_cpu(ckpt->cur_data_segno[type]);
                blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
                                                        CURSEG_HOT_DATA]);
-               if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
+               if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
                        blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
                else
                        blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
@@ -1076,7 +1076,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
                                                        CURSEG_HOT_NODE]);
                blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type -
                                                        CURSEG_HOT_NODE]);
-               if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
+               if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
                        blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
                                                        type - CURSEG_HOT_NODE);
                else
@@ -1087,7 +1087,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
        sum = (struct f2fs_summary_block *)page_address(new);
 
        if (IS_NODESEG(type)) {
-               if (ckpt->ckpt_flags & CP_UMOUNT_FLAG) {
+               if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) {
                        struct f2fs_summary *ns = &sum->entries[0];
                        int i;
                        for (i = 0; i < sbi->blocks_per_seg; i++, ns++) {
@@ -1119,7 +1119,7 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
 {
        int type = CURSEG_HOT_DATA;
 
-       if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG) {
+       if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) {
                /* restore for compacted data summary */
                if (read_compacted_summaries(sbi))
                        return -EINVAL;
@@ -1208,7 +1208,7 @@ static void write_normal_summaries(struct f2fs_sb_info *sbi,
 
 void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
 {
-       if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG)
+       if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG))
                write_compacted_summaries(sbi, start_blk);
        else
                write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA);
@@ -1216,7 +1216,7 @@ void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
 
 void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
 {
-       if (sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG)
+       if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG))
                write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
        return;
 }
index 8661c93538af2c4dcc6d770dac84972322d0f219..878bf382f8481e6aec6596133f6832b57776fa51 100644 (file)
@@ -89,7 +89,7 @@ static void f2fs_i_callback(struct rcu_head *head)
        kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode));
 }
 
-void f2fs_destroy_inode(struct inode *inode)
+static void f2fs_destroy_inode(struct inode *inode)
 {
        call_rcu(&inode->i_rcu, f2fs_i_callback);
 }
@@ -445,7 +445,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        if (sanity_check_raw_super(raw_super))
                goto free_sb_buf;
 
-       sb->s_maxbytes = max_file_size(raw_super->log_blocksize);
+       sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize));
        sb->s_max_links = F2FS_LINK_MAX;
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
 
@@ -527,7 +527,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 
        /* if there are nt orphan nodes free them */
        err = -EINVAL;
-       if (!(sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG) &&
+       if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG) &&
                                recover_orphan_inodes(sbi))
                goto free_node_inode;
 
@@ -547,7 +547,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        /* recover fsynced data */
-       if (!(sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG) &&
+       if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG) &&
                                !test_opt(sbi, DISABLE_ROLL_FORWARD))
                recover_fsync_data(sbi);
 
index 1429ece7caab386ffa96e8ad803f56e4be7f4dbf..c2fbbc35c1e60cd732fe87a38f78502e62078a8c 100644 (file)
@@ -272,8 +272,8 @@ struct f2fs_sit_block {
  * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
  */
 #define ENTRIES_IN_SUM         512
-#define        SUMMARY_SIZE            (sizeof(struct f2fs_summary))
-#define        SUM_FOOTER_SIZE         (sizeof(struct summary_footer))
+#define        SUMMARY_SIZE            (7)     /* sizeof(struct summary) */
+#define        SUM_FOOTER_SIZE         (5)     /* sizeof(struct summary_footer) */
 #define SUM_ENTRY_SIZE         (SUMMARY_SIZE * ENTRIES_IN_SUM)
 
 /* a summary entry for a 4KB-sized block in a segment */
@@ -297,7 +297,7 @@ struct summary_footer {
        __u32 check_sum;                /* summary checksum */
 } __packed;
 
-#define SUM_JOURNAL_SIZE       (PAGE_CACHE_SIZE - SUM_FOOTER_SIZE -\
+#define SUM_JOURNAL_SIZE       (F2FS_BLKSIZE - SUM_FOOTER_SIZE -\
                                SUM_ENTRY_SIZE)
 #define NAT_JOURNAL_ENTRIES    ((SUM_JOURNAL_SIZE - 2) /\
                                sizeof(struct nat_journal_entry))