[f2fs-dev] [PATCH 1/2] lib, mkfs: fix endian conversion for crc calculation
From 860da681961e6891d625abffa02d6df7dea4f5b2 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim jaegeuk@samsung.com Date: Wed, 19 Jun 2013 20:49:47 +0900 Subject: [PATCH 1/2] lib, mkfs: fix endian conversion for crc calculation Cc: linux-fsde...@vger.kernel.org, linux-ker...@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net Let's store the crc value for the checkpoint blocks with __le32. Signed-off-by: Jaegeuk Kim jaegeuk@samsung.com --- include/f2fs_fs.h | 1 + mkfs/f2fs_format.c | 19 --- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index b4ac876..ad10815 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -124,6 +124,7 @@ #define PAGE_CACHE_SIZE4096 #define BITS_PER_BYTE 8 #define F2FS_SUPER_MAGIC 0xF2F52010 /* F2FS Magic Number */ +#define CHECKSUM_OFFSET4092 /* for mkfs */ #define F2FS_MIN_VOLUME_SIZE 104857600 diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 8e49ed4..9115520 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -525,7 +525,7 @@ static int f2fs_write_check_point_pack(void) } /* 1. cp page 1 of checkpoint pack 1 */ - ckp-checkpoint_ver = 1; + ckp-checkpoint_ver = cpu_to_le64(1); ckp-cur_node_segno[0] = cpu_to_le32(config.cur_seg[CURSEG_HOT_NODE]); ckp-cur_node_segno[1] = @@ -578,12 +578,11 @@ static int f2fs_write_check_point_pack(void) ((le32_to_cpu(super_block.segment_count_nat) / 2) le32_to_cpu(super_block.log_blocks_per_seg)) / 8); - ckp-checksum_offset = cpu_to_le32(4092); + ckp-checksum_offset = cpu_to_le32(CHECKSUM_OFFSET); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, - le32_to_cpu(ckp-checksum_offset)); - *((u_int32_t *)((unsigned char *)ckp + - le32_to_cpu(ckp-checksum_offset))) = crc; + crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET); + *((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) = + cpu_to_le32(crc); blk_size_bytes = 1 le32_to_cpu(super_block.log_blocksize); cp_seg_blk_offset = le32_to_cpu(super_block.segment0_blkaddr); @@ -690,11 +689,9 @@ static int f2fs_write_check_point_pack(void) */ ckp-checkpoint_ver = 0; - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, - le32_to_cpu(ckp-checksum_offset)); - *((u_int32_t *)((unsigned char *)ckp + - le32_to_cpu(ckp-checksum_offset))) = crc; - + crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET); + *((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) = + cpu_to_le32(crc); cp_seg_blk_offset = (le32_to_cpu(super_block.segment0_blkaddr) + config.blks_per_seg) * blk_size_bytes; -- 1.8.3.1.437.g0dbd812 -- Jaegeuk Kim Samsung -- This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH] f2fs: fix crc endian conversion
From ed1e92d596f5356ff2f8f8af2818d36ca31f5cf1 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim jaegeuk@samsung.com Date: Wed, 19 Jun 2013 20:47:19 +0900 Subject: [PATCH] f2fs: fix crc endian conversion Cc: linux-fsde...@vger.kernel.org, linux-ker...@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net While calculating CRC for the checkpoint block, we use __u32, but when storing the crc value to the disk, we use __le32. Let's fix the inconsistency. Signed-off-by: Jaegeuk Kim jaegeuk@samsung.com --- fs/f2fs/checkpoint.c | 12 ++-- fs/f2fs/f2fs.h | 19 +++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 9a77509..66a6b85 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -357,8 +357,8 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, unsigned long blk_size = sbi-blocksize; struct f2fs_checkpoint *cp_block; unsigned long long cur_version = 0, pre_version = 0; - unsigned int crc = 0; size_t crc_offset; + __u32 crc = 0; /* Read the 1st cp block in this CP pack */ cp_page_1 = get_meta_page(sbi, cp_addr); @@ -369,7 +369,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, if (crc_offset = blk_size) goto invalid_cp1; - crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset); + crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); if (!f2fs_crc_valid(crc, cp_block, crc_offset)) goto invalid_cp1; @@ -384,7 +384,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, if (crc_offset = blk_size) goto invalid_cp2; - crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset); + crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); if (!f2fs_crc_valid(crc, cp_block, crc_offset)) goto invalid_cp2; @@ -648,7 +648,7 @@ 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; + __u32 crc32 = 0; void *kaddr; int i; @@ -717,8 +717,8 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt-checksum_offset)); - *(__le32 *)((unsigned char *)ckpt + - le32_to_cpu(ckpt-checksum_offset)) + *((__le32 *)((unsigned char *)ckpt + + le32_to_cpu(ckpt-checksum_offset))) = cpu_to_le32(crc32); start_blk = __start_cp_addr(sbi); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 863a5e91..467d42d 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -47,14 +47,25 @@ struct f2fs_mount_info { unsigned intopt; }; -static inline __u32 f2fs_crc32(void *buff, size_t len) +#define CRCPOLY_LE 0xedb88320 + +static inline __u32 f2fs_crc32(void *buf, size_t len) { - return crc32_le(F2FS_SUPER_MAGIC, buff, len); + unsigned char *p = (unsigned char *)buf; + __u32 crc = F2FS_SUPER_MAGIC; + int i; + + while (len--) { + crc ^= *p++; + for (i = 0; i 8; i++) + crc = (crc 1) ^ ((crc 1) ? CRCPOLY_LE : 0); + } + return crc; } -static inline bool f2fs_crc_valid(__u32 blk_crc, void *buff, size_t buff_size) +static inline bool f2fs_crc_valid(__u32 blk_crc, void *buf, size_t buf_size) { - return f2fs_crc32(buff, buff_size) == blk_crc; + return f2fs_crc32(buf, buf_size) == blk_crc; } /* -- 1.8.3.1.437.g0dbd812 -- Jaegeuk Kim Samsung -- This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] Kernel BUG when writing to f2fs drive, PowerPC, SD card, USB3
Hi, I tried your patches and they seem to work :) I fixed umount flag yesterday but the CRC was the keypoint. Thanks. I will now stress-test the SD card on my board and let you know the results. Best regards, Oded On 06/19/2013 03:43 PM, Jaegeuk Kim wrote: Hi, Could you test the following three patches sent right after this email? For f2fs-tools: 1. store crc as __le32 2. store checkpoint flags as __le32 For f2fs: 1. handle crc as __le32 I suspect that: 1. mount failure is able to be occurred due to the crc endian error. 2. update_sit_entry bug_on is caused by the endian problem on the checkpoint flags. If wrong checkpoint flag is got at mount time, we cannot build the latest sit entries correctly. Thanks, 2013-06-18 (화), 15:10 +0300, Oded Gabbay: Hi, I printed also the segment no. and it appears that every time that segment 187 is written to, which is assigned to the HOT data, the system crashes. BTW, even if I just do echo oded /mnt/file and then just wait for about 30-45 seconds, the crash occurs I got the following prints when I did the echo thing: REMOVE_ME update_sit_entry(202): offset = 0, segoff = 3584, blkaddr = 4096, segno = 0 REMOVE_ME update_sit_entry(202): offset = 1, segoff = 99329, blkaddr = 99841, segno = 187 REMOVE_ME update_sit_entry(202): offset = 0, segoff = 99328, blkaddr = 99840, segno = 187 [ cut here ] kernel BUG at /home/ogabbay/views/r5.xcj/software/os-software/powerpc/usr/src/linux-3.9.6-adva/fs/f2fs/segment.c:217! Here is the print from the debugfs. You can see segment 187 is allocated to HOT data: [cj:~] # cat /sys/kernel/debug/f2fs/status =[ partition info(loop0). #0 ]= [SB: 1] [CP: 2] [SIT: 2] [NAT: 2] [SSA: 1] [MAIN: 192(OverProv:55 Resv:48)] Utilization: 0% (4 valid blocks) - Node: 2 (Inode: 2, Other: 0) - Data: 2 Main area: 192 segs, 192 secs 192 zones - COLD data: 0, 0, 0 - WARM data: 1, 1, 1 - HOT data: 187, 187, 187 - Dir dnode: 190, 190, 190 - File dnode: 189, 189, 189 - Indir nodes: 188, 188, 188 - Valid: 6 - Dirty: 0 - Prefree: 0 - Free: 186 (186) GC calls: 0 (BG: 0) - data segments : 0 - node segments : 0 Try to move 0 blocks - data blocks : 0 - node blocks : 0 Extent Hit Ratio: 0 / 0 Balancing F2FS Async: - nodes1 in2 - dents1 in dirs: 1 - meta0 in 21 - NATs 2 29120 - SITs: 0 - free_nids: 2270 Distribution of User Blocks: [ valid | invalid | free ] [|---|---] SSR: 0 blocks in 0 segments LFS: 0 blocks in 0 segments BDF: 100, avg. vblocks: 0 Memory: 154 KB = static: 60 + cached: 94 On 06/18/2013 12:44 PM, Oded Gabbay wrote: Hi, I would like to share additional information I have from pr_err I put into the update_sit_entry function. The following is the printout from the terminal. This is only the end of the printout. The start was with segoff = 3584 and it went sequentially up until 9215, where then it jumped to 99329 and after that 99328 - which is the entry that caused the crash. Each time I repeated the experiment I got exactly the same results. I put the pr_err after the line: offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) (sbi-blocks_per_seg - 1); where segoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) Hope this helps. REMOVE_ME update_sit_entry(202): offset = 0, segoff = 3584, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 1, segoff = 3585, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 2, segoff = 3586, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 3, segoff = 3587, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 4, segoff = 3588, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 5, segoff = 3589, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 6, segoff = 3590, sbi-blocks_per_seg = 512 ::: REMOVE_ME update_sit_entry(202): offset = 502, segoff = 9206, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 503, segoff = 9207, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 504, segoff = 9208, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 505, segoff = 9209, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 506, segoff = 9210, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 507, segoff = 9211, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 508, segoff = 9212, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 509, segoff = 9213, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 510, segoff = 9214, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 511, segoff = 9215, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 1, segoff = 99329,
Re: [f2fs-dev] Kernel BUG when writing to f2fs drive, PowerPC, SD card, USB3
Hi, After stress-testing the F2FS on SD card and iNAND, and doing multiple mounts/umounts, I believe I can say the fix is working for the powerpc. Thanks for all the help Oded. On 06/19/2013 03:43 PM, Jaegeuk Kim wrote: Hi, Could you test the following three patches sent right after this email? For f2fs-tools: 1. store crc as __le32 2. store checkpoint flags as __le32 For f2fs: 1. handle crc as __le32 I suspect that: 1. mount failure is able to be occurred due to the crc endian error. 2. update_sit_entry bug_on is caused by the endian problem on the checkpoint flags. If wrong checkpoint flag is got at mount time, we cannot build the latest sit entries correctly. Thanks, 2013-06-18 (화), 15:10 +0300, Oded Gabbay: Hi, I printed also the segment no. and it appears that every time that segment 187 is written to, which is assigned to the HOT data, the system crashes. BTW, even if I just do echo oded /mnt/file and then just wait for about 30-45 seconds, the crash occurs I got the following prints when I did the echo thing: REMOVE_ME update_sit_entry(202): offset = 0, segoff = 3584, blkaddr = 4096, segno = 0 REMOVE_ME update_sit_entry(202): offset = 1, segoff = 99329, blkaddr = 99841, segno = 187 REMOVE_ME update_sit_entry(202): offset = 0, segoff = 99328, blkaddr = 99840, segno = 187 [ cut here ] kernel BUG at /home/ogabbay/views/r5.xcj/software/os-software/powerpc/usr/src/linux-3.9.6-adva/fs/f2fs/segment.c:217! Here is the print from the debugfs. You can see segment 187 is allocated to HOT data: [cj:~] # cat /sys/kernel/debug/f2fs/status =[ partition info(loop0). #0 ]= [SB: 1] [CP: 2] [SIT: 2] [NAT: 2] [SSA: 1] [MAIN: 192(OverProv:55 Resv:48)] Utilization: 0% (4 valid blocks) - Node: 2 (Inode: 2, Other: 0) - Data: 2 Main area: 192 segs, 192 secs 192 zones - COLD data: 0, 0, 0 - WARM data: 1, 1, 1 - HOT data: 187, 187, 187 - Dir dnode: 190, 190, 190 - File dnode: 189, 189, 189 - Indir nodes: 188, 188, 188 - Valid: 6 - Dirty: 0 - Prefree: 0 - Free: 186 (186) GC calls: 0 (BG: 0) - data segments : 0 - node segments : 0 Try to move 0 blocks - data blocks : 0 - node blocks : 0 Extent Hit Ratio: 0 / 0 Balancing F2FS Async: - nodes1 in2 - dents1 in dirs: 1 - meta0 in 21 - NATs 2 29120 - SITs: 0 - free_nids: 2270 Distribution of User Blocks: [ valid | invalid | free ] [|---|---] SSR: 0 blocks in 0 segments LFS: 0 blocks in 0 segments BDF: 100, avg. vblocks: 0 Memory: 154 KB = static: 60 + cached: 94 On 06/18/2013 12:44 PM, Oded Gabbay wrote: Hi, I would like to share additional information I have from pr_err I put into the update_sit_entry function. The following is the printout from the terminal. This is only the end of the printout. The start was with segoff = 3584 and it went sequentially up until 9215, where then it jumped to 99329 and after that 99328 - which is the entry that caused the crash. Each time I repeated the experiment I got exactly the same results. I put the pr_err after the line: offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) (sbi-blocks_per_seg - 1); where segoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) Hope this helps. REMOVE_ME update_sit_entry(202): offset = 0, segoff = 3584, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 1, segoff = 3585, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 2, segoff = 3586, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 3, segoff = 3587, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 4, segoff = 3588, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 5, segoff = 3589, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 6, segoff = 3590, sbi-blocks_per_seg = 512 ::: REMOVE_ME update_sit_entry(202): offset = 502, segoff = 9206, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 503, segoff = 9207, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 504, segoff = 9208, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 505, segoff = 9209, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 506, segoff = 9210, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 507, segoff = 9211, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 508, segoff = 9212, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 509, segoff = 9213, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 510, segoff = 9214, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 511, segoff = 9215, sbi-blocks_per_seg = 512 REMOVE_ME update_sit_entry(202): offset = 1, segoff = 99329, sbi-blocks_per_seg = 512 REMOVE_ME