Skip to contentSkip to conversation

fsck is broken on mips32 platform

PATCH In review [email protected] 2 participants 7 messages Nov 24, 2016 – Nov 26, 2016

lore
Share & tools
lore
#0 lore raw

Hi !

I'm using f2fs on router Dlink dir-825 with openwrt/LEDE firmware. Its mips32 rel 2 big endian cpu.

mkfs.f2fs - works
mount - works
fsck.f2fs - corrupts filesystem

# i'm trying to fsck valid empty mountable f2fs partition i have just mkfs'ed
fsck.f2fs /dev/sda2
Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 6508544 (3178 MB)
Info: MKFS version
"Linux version 4.4.0-21-generic (buildd@lgw01-21) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016"
Info: FSCK version
from "Linux version 4.4.0-21-generic (buildd@lgw01-21) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016"

    to "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: total FS sectors = 6508544 (3178 MB)
Info: CKPT version = 1
Info: checkpoint state = 5 : compacted_summary unmount [ASSERT] (sanity_check_nid: 356) --> nid is not valid. [0x3]

NID[0x3] is unreachable

[FSCK] Unreachable nat entries                        [Fail] [0x1]
[FSCK] SIT valid block bitmap checking                [Fail]
[FSCK] Hard link checking for regular file            [Ok..] [0x0]
[FSCK] valid_block_count matching with CP             [Fail] [0x0]
[FSCK] valid_node_count matcing with CP (de lookup)   [Fail] [0x0]
[FSCK] valid_node_count matcing with CP (nat lookup)  [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP              [Fail] [0x0]
[FSCK] free segment_count matched with CP             [Fail] [0x621]
[FSCK] next block offset is free                      [Ok..]

[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Fail]
[FIX] (nullify_nat_entry:1688) --> Remove nid [0x3] in nat journal

After failed mount attempt :

dmesg
F2FS-fs (sda2): Failed to read root inode

On x86 and ARM everything is ok

f2fs-tools 1.7.0
kernel 4.4.30

------------------------------------------------------------------------------

#1 lore raw

Hi,

Quoted 19 lines · On 11/25/2016 6:30 AM, [email protected] wrote:

Hi !

I'm using f2fs on router Dlink dir-825 with openwrt/LEDE firmware. Its mips32 rel 2 big endian cpu.

mkfs.f2fs - works
mount - works
fsck.f2fs - corrupts filesystem

# i'm trying to fsck valid empty mountable f2fs partition i have just mkfs'ed
fsck.f2fs /dev/sda2
Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 6508544 (3178 MB)
Info: MKFS version
"Linux version 4.4.0-21-generic (buildd@lgw01-21) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016"
Info: FSCK version
from "Linux version 4.4.0-21-generic (buildd@lgw01-21) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016"

Quoted 7 lines
    to "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: total FS sectors = 6508544 (3178 MB)
Info: CKPT version = 1
Info: checkpoint state = 5 : compacted_summary unmount [ASSERT] (sanity_check_nid: 356) --> nid is not valid. [0x3]

It seems that sanity_check_nid does not switch little endian value to big endian. I'm not sure if it is caused by this and if there are any other places have this endian switch issue, could you please test this.

thanks,
Sheng

======

fsck/f2fs.h +2 -2
index 39ff161..9dc832c 100644
@@ -370,7 +370,7 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
 static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
 {
        return (nid <= (NAT_ENTRY_PER_BLOCK *
-                       F2FS_RAW_SUPER(sbi)->segment_count_nat
+                       le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_nat)
                        << (sbi->log_blocks_per_seg - 1)));
 }
 
@@ -378,7 +378,7 @@ static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
 {
        int i;
 
-       if (addr >= F2FS_RAW_SUPER(sbi)->block_count ||
+       if (addr >= le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count) ||
                                addr < SM_I(sbi)->main_blkaddr) {
                DBG(1, "block addr [0x%x]\n", addr);
                return 0;
Quoted 26 lines

NID[0x3] is unreachable

[FSCK] Unreachable nat entries                        [Fail] [0x1]
[FSCK] SIT valid block bitmap checking                [Fail]
[FSCK] Hard link checking for regular file            [Ok..] [0x0]
[FSCK] valid_block_count matching with CP             [Fail] [0x0]
[FSCK] valid_node_count matcing with CP (de lookup)   [Fail] [0x0]
[FSCK] valid_node_count matcing with CP (nat lookup)  [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP              [Fail] [0x0]
[FSCK] free segment_count matched with CP             [Fail] [0x621]
[FSCK] next block offset is free                      [Ok..]

[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Fail]
[FIX] (nullify_nat_entry:1688) --> Remove nid [0x3] in nat journal

After failed mount attempt :

dmesg
F2FS-fs (sda2): Failed to read root inode

On x86 and ARM everything is ok

f2fs-tools 1.7.0
kernel 4.4.30

Quoted 8 lines

------------------------------------------------------------------------------
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

.

------------------------------------------------------------------------------

#2 lore raw

Hi, Sheng.

A bit better but still fail. At least it does not corrupt fs and it mounts.

Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 204800 (100 MB)
Info: MKFS version
"Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"
Info: FSCK version
from "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

    to "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: total FS sectors = 204800 (100 MB)
Info: CKPT version = 3
Info: checkpoint state = 5 : compacted_summary unmount

[FSCK] Unreachable nat entries                        [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking                [Ok..]
[FSCK] Hard link checking for regular file            [Ok..] [0x0]
[FSCK] valid_block_count matching with CP             [Ok..] [0x2]
[FSCK] valid_node_count matcing with CP (de lookup)   [Ok..] [0x1]
[FSCK] valid_node_count matcing with CP (nat lookup)  [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP              [Ok..] [0x1]
[FSCK] free segment_count matched with CP             [Fail] [0x27]
[FSCK] next block offset is free                      [Ok..]

[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Fail]

....... at this point according to strace fsck does readv from descriptor 0 (stdin). Must interrupt it with ctrl+c

Quoted 54 lines

Hi,

Quoted 19 lines · On 11/25/2016 6:30 AM, [email protected] wrote:

Hi !

I'm using f2fs on router Dlink dir-825 with openwrt/LEDE firmware. Its mips32 rel 2 big endian cpu.

mkfs.f2fs - works
mount - works
fsck.f2fs - corrupts filesystem

# i'm trying to fsck valid empty mountable f2fs partition i have just mkfs'ed
fsck.f2fs /dev/sda2
Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 6508544 (3178 MB)
Info: MKFS version
"Linux version 4.4.0-21-generic (buildd@lgw01-21) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016"
Info: FSCK version
from "Linux version 4.4.0-21-generic (buildd@lgw01-21) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016"

Quoted 7 lines
    to "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: total FS sectors = 6508544 (3178 MB)
Info: CKPT version = 1
Info: checkpoint state = 5 : compacted_summary unmount [ASSERT] (sanity_check_nid: 356) --> nid is not valid. [0x3]

It seems that sanity_check_nid does not switch little endian value to big endian. I'm not sure if it is caused by this and if there are any other places have this endian switch issue, could you please test this.

thanks,
Sheng

======

fsck/f2fs.h +1 -1
index 39ff161..9dc832c 100644
@@ -370,7 +370,7 @@ static inline block_t sum_blk_addr(struct
 f2fs_sb_info *sbi, int base, int type)
 static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
 {
        return (nid <= (NAT_ENTRY_PER_BLOCK *
-                       F2FS_RAW_SUPER(sbi)->segment_count_nat
+                      
 le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_nat)
                        << (sbi->log_blocks_per_seg - 1)));

}

fsck/f2fs.h static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr) · line 379

Quoted 2 lines
fsck/f2fs.h +0 -0
@@ -378,7 +378,7 @@ static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
 {
        int i;

- if (addr >>= F2FS_RAW_SUPER(sbi)->block_count ||
+ if (addr >>= le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count) ||

Quoted 29 lines
fsck/f2fs.h +0 -0
                                addr < SM_I(sbi)->main_blkaddr) {
                DBG(1, "block addr [0x%x]\n", addr);
                return 0;
Quoted 26 lines

NID[0x3] is unreachable

[FSCK] Unreachable nat entries                        [Fail] [0x1]
[FSCK] SIT valid block bitmap checking                [Fail]
[FSCK] Hard link checking for regular file            [Ok..] [0x0]
[FSCK] valid_block_count matching with CP             [Fail] [0x0]
[FSCK] valid_node_count matcing with CP (de lookup)   [Fail] [0x0]
[FSCK] valid_node_count matcing with CP (nat lookup)  [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP              [Fail] [0x0]
[FSCK] free segment_count matched with CP             [Fail] [0x621]
[FSCK] next block offset is free                      [Ok..]

[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Fail]
[FIX] (nullify_nat_entry:1688) --> Remove nid [0x3] in nat journal

After failed mount attempt :

dmesg
F2FS-fs (sda2): Failed to read root inode

On x86 and ARM everything is ok

f2fs-tools 1.7.0
kernel 4.4.30

Quoted 8 lines
Quoted 8 lines

------------------------------------------------------------------------------
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

.

------------------------------------------------------------------------------

#3 lore raw

PATCH 1/2 fsck.f2fs: remove duplicated header files

---
 fsck/f2fs.h  | 2 --
 fsck/xattr.h | 1 -
 2 files changed, 3 deletions(-)
fsck/f2fs.h +0 -2
index fbb878a..1a0723c 100644
@@ -19,8 +19,6 @@
 #include <string.h>
 #include <errno.h>
 #include <mntent.h>
-#include <linux/types.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
fsck/xattr.h +0 -1
index 3ca9133..b414629 100644
@@ -16,7 +16,6 @@
 #ifndef _XATTR_H_
 #define _XATTR_H_
 
-#include <f2fs_fs.h>
 #include "f2fs.h"
 
 struct f2fs_xattr_header {
Signature · 4 lines
2.10.2


------------------------------------------------------------------------------
#4 lore raw

PATCH 2/2 fsck.f2fs: correct endianness

---
Hi, k

Could you please try this? I think I've correct all endianness issue. And can I have your reported-by and test-by?

thanks,
Sheng

---
 fsck/dir.c        |  6 +++---
 fsck/dump.c       | 10 +++++-----
 fsck/f2fs.h       |  4 ++--
 fsck/mount.c      | 12 ++++++------
 fsck/node.c       |  2 +-
 fsck/segment.c    |  3 ++-
 include/f2fs_fs.h |  8 +++++---
 7 files changed, 24 insertions(+), 21 deletions(-)
fsck/dir.c +3 -3
index 2009855..d817d27 100644
@@ -134,7 +134,7 @@ static int find_in_level(struct f2fs_sb_info *sbi,struct f2fs_node *dir,
 	struct dnode_of_data dn = {0};
 	void *dentry_blk;
 	int max_slots = 214;
-	nid_t ino = dir->footer.ino;
+	nid_t ino = le32_to_cpu(dir->footer.ino);
 	f2fs_hash_t namehash;
 	int ret = 0;
 
@@ -191,7 +191,7 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi,
 		return 0;
 	}
 
-	max_depth = dir->i.i_current_depth;
+	max_depth = le32_to_cpu(dir->i.i_current_depth);
 	for (level = 0; level < max_depth; level ++) {
 		if (find_in_level(sbi, dir, level, de))
 			return 1;
@@ -209,7 +209,7 @@ static void f2fs_update_dentry(nid_t ino, umode_t mode,
 	int i;
 
 	de = &d->dentry[bit_pos];
-	de->name_len = len;
+	de->name_len = cpu_to_le16(len);
 	de->hash_code = name_hash;
 	memcpy(d->filename[bit_pos], name, len);
 	d->filename[bit_pos][len] = 0;
fsck/dump.c +5 -5
index 8e7c85c..e9d442f 100644
@@ -81,7 +81,7 @@ void nat_dump(struct f2fs_sb_info *sbi)
 						"nid:%5u\tino:%5u\toffset:%5u"
 						"\tblkaddr:%10u\tpack:%d\n",
 						ni.nid, ni.ino,
-						node_block->footer.flag >>
+						le32_to_cpu(node_block->footer.flag) >>
 							OFFSET_BIT_SHIFT,
 						ni.blk_addr, pack);
 					ret = write(fd, buf, strlen(buf));
@@ -100,7 +100,7 @@ void nat_dump(struct f2fs_sb_info *sbi)
 					"nid:%5u\tino:%5u\toffset:%5u"
 					"\tblkaddr:%10u\tpack:%d\n",
 					ni.nid, ni.ino,
-					node_block->footer.flag >>
+					le32_to_cpu(node_block->footer.flag) >>
 						OFFSET_BIT_SHIFT,
 					ni.blk_addr, pack);
 				ret = write(fd, buf, strlen(buf));
@@ -335,13 +335,13 @@ static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 	for (i = 0; i < 5; i++) {
 		if (i == 0 || i == 1)
 			dump_node_blk(sbi, TYPE_DIRECT_NODE,
-					node_blk->i.i_nid[i], &ofs);
+					le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
 		else if (i == 2 || i == 3)
 			dump_node_blk(sbi, TYPE_INDIRECT_NODE,
-					node_blk->i.i_nid[i], &ofs);
+					le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
 		else if (i == 4)
 			dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
-					node_blk->i.i_nid[i], &ofs);
+					le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
 		else
 			ASSERT(0);
 	}
fsck/f2fs.h +2 -2
index 1a0723c..0650d10 100644
@@ -359,7 +359,7 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
 static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
 {
 	return (nid <= (NAT_ENTRY_PER_BLOCK *
-			F2FS_RAW_SUPER(sbi)->segment_count_nat
+			le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_nat)
 			<< (sbi->log_blocks_per_seg - 1)));
 }
 
@@ -367,7 +367,7 @@ static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
 {
 	int i;
 
-	if (addr >= F2FS_RAW_SUPER(sbi)->block_count ||
+	if (le64_to_cpu(addr >= F2FS_RAW_SUPER(sbi)->block_count) ||
 				addr < SM_I(sbi)->main_blkaddr) {
 		DBG(1, "block addr [0x%x]\n", addr);
 		return 0;
fsck/mount.c +6 -6
index 21a96a7..d5a91a5 100644
@@ -1375,12 +1375,12 @@ void build_sit_area_bitmap(struct f2fs_sb_info *sbi)
 		ptr += SIT_VBLOCK_MAP_SIZE;
 
 		if (se->valid_blocks == 0x0) {
-			if (sbi->ckpt->cur_node_segno[0] == segno ||
-					sbi->ckpt->cur_data_segno[0] == segno ||
-					sbi->ckpt->cur_node_segno[1] == segno ||
-					sbi->ckpt->cur_data_segno[1] == segno ||
-					sbi->ckpt->cur_node_segno[2] == segno ||
-					sbi->ckpt->cur_data_segno[2] == segno) {
+			if (le32_to_cpu(sbi->ckpt->cur_node_segno[0]) == segno ||
+				le32_to_cpu(sbi->ckpt->cur_data_segno[0]) == segno ||
+				le32_to_cpu(sbi->ckpt->cur_node_segno[1]) == segno ||
+				le32_to_cpu(sbi->ckpt->cur_data_segno[1]) == segno ||
+				le32_to_cpu(sbi->ckpt->cur_node_segno[2]) == segno ||
+				le32_to_cpu(sbi->ckpt->cur_data_segno[2]) == segno) {
 				continue;
 			} else {
 				free_segs++;
fsck/node.c +1 -1
index c2f83b8..fe923e5 100644
@@ -78,7 +78,7 @@ block_t new_node_block(struct f2fs_sb_info *sbi,
 
 	type = CURSEG_COLD_NODE;
 	if (IS_DNODE(node_blk)) {
-		if (S_ISDIR(f2fs_inode->i.i_mode))
+		if (S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode)))
 			type = CURSEG_HOT_NODE;
 		else
 			type = CURSEG_WARM_NODE;
fsck/segment.c +2 -1
index 9ce8bf5..6b2f6c1 100644
@@ -80,7 +80,8 @@ static void f2fs_write_block(struct f2fs_sb_info *sbi, nid_t ino, void *buffer,
 	ret = dev_read_block(inode, ni.blk_addr);
 	ASSERT(ret >= 0);
 
-	if (S_ISDIR(inode->i.i_mode) || S_ISLNK(inode->i.i_mode))
+	if (S_ISDIR(le16_to_cpu(inode->i.i_mode)) ||
+			S_ISLNK(le16_to_cpu(inode->i.i_mode)))
 		ASSERT(0);
 
 	off_in_block = offset & ((1 << F2FS_BLKSIZE_BITS) - 1);
include/f2fs_fs.h +5 -3
index 78ea939..ef34ca2 100644
@@ -170,15 +170,17 @@ static inline uint64_t bswap_64(uint64_t val)
 #define DISP_u32(ptr, member)						\
 	do {								\
 		assert(sizeof((ptr)->member) <= 4);			\
-		printf("%-30s" "\t\t[0x%8x : %u]\n",		\
-			#member, ((ptr)->member), ((ptr)->member));	\
+		printf("%-30s" "\t\t[0x%8x : %u]\n",			\
+			#member, le32_to_cpu(((ptr)->member)),		\
+			le32_to_cpu(((ptr)->member)));			\
 	} while (0)
 
 #define DISP_u64(ptr, member)						\
 	do {								\
 		assert(sizeof((ptr)->member) == 8);			\
 		printf("%-30s" "\t\t[0x%8llx : %llu]\n",		\
-			#member, ((ptr)->member), ((ptr)->member));	\
+			#member, le64_to_cpu(((ptr)->member)),		\
+			le64_to_cpu(((ptr)->member)));			\
 	} while (0)
 
 #define DISP_utf(ptr, member)						\
Signature · 4 lines
2.10.2


------------------------------------------------------------------------------
#5 lore raw

Re: [RFT PATCH 2/2] fsck.f2fs: correct endianness

The only thing I changed in your patch is :

- if (addr >= F2FS_RAW_SUPER(sbi)->block_count ||
+ if (le64_to_cpu(addr >= F2FS_RAW_SUPER(sbi)->block_count) ||

                                addr < SM_I(sbi)->main_blkaddr) {

You're passing boolean to le64_to_cpu which is obviously error. I changed that to :

        if (addr >= le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count) ||

And it worked without errors first on empty fs in a file, second on real sda partition with files.
I havent tested what happens if filesystem is damaged.

Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 204800 (100 MB)
Info: MKFS version
"Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"
Info: FSCK version
from "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

    to "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: total FS sectors = 204800 (100 MB)
Info: CKPT version = 1
Info: checkpoint state = 5 : compacted_summary unmount

[FSCK] Unreachable nat entries                        [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking                [Ok..]
[FSCK] Hard link checking for regular file            [Ok..] [0x0]
[FSCK] valid_block_count matching with CP             [Ok..] [0x2]
[FSCK] valid_node_count matcing with CP (de lookup)   [Ok..] [0x1]
[FSCK] valid_node_count matcing with CP (nat lookup)  [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP              [Ok..] [0x1]
[FSCK] free segment_count matched with CP             [Ok..] [0x24]
[FSCK] next block offset is free                      [Ok..]

[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Ok..]

Done.

Quoted 43 lines

---
Hi, k

Could you please try this? I think I've correct all endianness issue. And can I have your reported-by and test-by?

thanks,
Sheng

---
 fsck/dir.c        |  6 +++---
 fsck/dump.c       | 10 +++++-----
 fsck/f2fs.h       |  4 ++--
 fsck/mount.c      | 12 ++++++------
 fsck/node.c       |  2 +-
 fsck/segment.c    |  3 ++-
 include/f2fs_fs.h |  8 +++++---
 7 files changed, 24 insertions(+), 21 deletions(-)
fsck/dir.c +2 -2
index 2009855..d817d27 100644
@@ -134,7 +134,7 @@ static int find_in_level(struct f2fs_sb_info *sbi,struct f2fs_node *dir,
        struct dnode_of_data dn = {0};
        void *dentry_blk;
        int max_slots = 214;
-       nid_t ino = dir->footer.ino;
+       nid_t ino = le32_to_cpu(dir->footer.ino);
        f2fs_hash_t namehash;
        int ret = 0;
 
@@ -191,7 +191,7 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi,
                return 0;
        }
 
-       max_depth = dir->i.i_current_depth;
+       max_depth = le32_to_cpu(dir->i.i_current_depth);
        for (level = 0; level < max_depth; level ++) {
                if (find_in_level(sbi, dir, level, de))
                        return 1;

fsck/dir.c static void f2fs_update_dentry(nid_t ino, umode_t mode, · line 211

Quoted 3 lines
fsck/dir.c +0 -0
@@ -209,7 +209,7 @@ static void f2fs_update_dentry(nid_t ino, umode_t mode,
        int i;
 
        de = &d->dentry[bit_pos];

- de->>name_len = len;
+ de->>name_len = cpu_to_le16(len);

Quoted 63 lines
fsck/dir.c +0 -0
        de->hash_code = name_hash;
        memcpy(d->filename[bit_pos], name, len);
        d->filename[bit_pos][len] = 0;
fsck/dump.c +1 -1
index 8e7c85c..e9d442f 100644
@@ -81,7 +81,7 @@ void nat_dump(struct f2fs_sb_info *sbi)
                                                "nid:%5u\tino:%5u\toffset:%5u"
                                                "\tblkaddr:%10u\tpack:%d\n",
                                                ni.nid, ni.ino,
-                                               node_block->footer.flag >>
+                                              

le32_to_cpu(node_block->footer.flag) >>

                                                        OFFSET_BIT_SHIFT,
                                                ni.blk_addr, pack);
                                        ret = write(fd, buf, strlen(buf));
fsck/dump.c +1 -1
@@ -100,7 +100,7 @@ void nat_dump(struct f2fs_sb_info *sbi)
                                        "nid:%5u\tino:%5u\toffset:%5u"
                                        "\tblkaddr:%10u\tpack:%d\n",
                                        ni.nid, ni.ino,
-                                       node_block->footer.flag >>
+                                      

le32_to_cpu(node_block->footer.flag) >>

                                                OFFSET_BIT_SHIFT,
                                        ni.blk_addr, pack);
                                ret = write(fd, buf, strlen(buf));
fsck/dump.c +3 -3
@@ -335,13 +335,13 @@ static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
        for (i = 0; i < 5; i++) {
                if (i == 0 || i == 1)
                        dump_node_blk(sbi, TYPE_DIRECT_NODE,
-                                       node_blk->i.i_nid[i], &ofs);
+                                      
 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
                else if (i == 2 || i == 3)
                        dump_node_blk(sbi, TYPE_INDIRECT_NODE,
-                                       node_blk->i.i_nid[i], &ofs);
+                                      
 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
                else if (i == 4)
                        dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
-                                       node_blk->i.i_nid[i], &ofs);
+                                      
 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
                else
                        ASSERT(0);
        }
fsck/f2fs.h +1 -1
index 1a0723c..0650d10 100644
@@ -359,7 +359,7 @@ static inline block_t sum_blk_addr(struct
 f2fs_sb_info *sbi, int base, int type)
 static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
 {
        return (nid <= (NAT_ENTRY_PER_BLOCK *
-                       F2FS_RAW_SUPER(sbi)->segment_count_nat
+                      
 le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_nat)
                        << (sbi->log_blocks_per_seg - 1)));

}

fsck/f2fs.h static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr) · line 368

Quoted 2 lines
fsck/f2fs.h +0 -0
@@ -367,7 +367,7 @@ static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
 {
        int i;

- if (addr >>= F2FS_RAW_SUPER(sbi)->block_count ||

Quoted 90 lines
fsck/f2fs.h +1 -0
+       if (le64_to_cpu(addr >= F2FS_RAW_SUPER(sbi)->block_count) ||
                                addr < SM_I(sbi)->main_blkaddr) {
                DBG(1, "block addr [0x%x]\n", addr);
                return 0;
fsck/mount.c +0 -2
index 21a96a7..d5a91a5 100644
@@ -1375,12 +1375,12 @@ void build_sit_area_bitmap(struct f2fs_sb_info *sbi)
                ptr += SIT_VBLOCK_MAP_SIZE;
 
                if (se->valid_blocks == 0x0) {
-                       if (sbi->ckpt->cur_node_segno[0] == segno ||
-                                      

sbi->ckpt->cur_data_segno[0] == segno ||
-
sbi->ckpt->cur_node_segno[1] == segno ||
-
sbi->ckpt->cur_data_segno[1] == segno ||
-
sbi->ckpt->cur_node_segno[2] == segno ||
-
sbi->ckpt->cur_data_segno[2] == segno) {
+ if
(le32_to_cpu(sbi->ckpt->cur_node_segno[0]) == segno || +
le32_to_cpu(sbi->ckpt->cur_data_segno[0]) == segno || +
le32_to_cpu(sbi->ckpt->cur_node_segno[1]) == segno || +
le32_to_cpu(sbi->ckpt->cur_data_segno[1]) == segno || +
le32_to_cpu(sbi->ckpt->cur_node_segno[2]) == segno || +

le32_to_cpu(sbi->ckpt->cur_data_segno[2]) == segno) {
                                continue;
                        } else {
                                free_segs++;
fsck/node.c +1 -1
index c2f83b8..fe923e5 100644
@@ -78,7 +78,7 @@ block_t new_node_block(struct f2fs_sb_info *sbi,
 
        type = CURSEG_COLD_NODE;
        if (IS_DNODE(node_blk)) {
-               if (S_ISDIR(f2fs_inode->i.i_mode))
+               if (S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode)))
                        type = CURSEG_HOT_NODE;
                else
                        type = CURSEG_WARM_NODE;
fsck/segment.c +2 -1
index 9ce8bf5..6b2f6c1 100644
@@ -80,7 +80,8 @@ static void f2fs_write_block(struct f2fs_sb_info *sbi, nid_t ino, void *buffer,
        ret = dev_read_block(inode, ni.blk_addr);
        ASSERT(ret >= 0);
 
-       if (S_ISDIR(inode->i.i_mode) || S_ISLNK(inode->i.i_mode))
+       if (S_ISDIR(le16_to_cpu(inode->i.i_mode)) ||
+                       S_ISLNK(le16_to_cpu(inode->i.i_mode)))
                ASSERT(0);
 
        off_in_block = offset & ((1 << F2FS_BLKSIZE_BITS) - 1);
include/f2fs_fs.h +5 -3
index 78ea939..ef34ca2 100644
@@ -170,15 +170,17 @@ static inline uint64_t bswap_64(uint64_t val)
 #define DISP_u32(ptr, member)                                     
        do {                                                       
                assert(sizeof((ptr)->member) <= 4);                
-               printf("%-30s" "\t\t[0x%8x : %u]\n",            \
-                       #member, ((ptr)->member), ((ptr)->member));
+               printf("%-30s" "\t\t[0x%8x : %u]\n",               
+                       #member, le32_to_cpu(((ptr)->member)),     
+                       le32_to_cpu(((ptr)->member)));             
        } while (0)
 
 #define DISP_u64(ptr, member)                                     
        do {                                                       
                assert(sizeof((ptr)->member) == 8);                
                printf("%-30s" "\t\t[0x%8llx : %llu]\n",           
-                       #member, ((ptr)->member), ((ptr)->member));
+                       #member, le64_to_cpu(((ptr)->member)),     
+                       le64_to_cpu(((ptr)->member)));             
        } while (0)
 
 #define DISP_utf(ptr, member)                                     
Signature · 9 lines
С уважением,
 K                          mailto:[email protected]


------------------------------------------------------------------------------
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
#6 lore raw

Re: [RFT PATCH 2/2] fsck.f2fs: correct endianness

Quoted 11 lines · On 11/25/2016 11:55 PM, [email protected] wrote:

The only thing I changed in your patch is :

fsck/f2fs.h +1 -1
-       if (addr >= F2FS_RAW_SUPER(sbi)->block_count ||
+       if (le64_to_cpu(addr >= F2FS_RAW_SUPER(sbi)->block_count) ||
                                addr < SM_I(sbi)->main_blkaddr) {

You're passing boolean to le64_to_cpu which is obviously error. I changed that to :

        if (addr >= le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count) ||

Right. My bad. I'll fix this and send a version 2 :)

thanks,
Sheng

Quoted 144 lines

And it worked without errors first on empty fs in a file, second on real sda partition with files.
I havent tested what happens if filesystem is damaged.

Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 204800 (100 MB)
Info: MKFS version
"Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"
Info: FSCK version
from "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

    to "Linux version 4.4.30 (vasya@nowhere) (gcc version 5.4.0 (LEDE GCC 5.4.0 r2084) ) #0 PREEMPT Thu Nov 3 07:34:38 2016"

Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: total FS sectors = 204800 (100 MB)
Info: CKPT version = 1
Info: checkpoint state = 5 : compacted_summary unmount

[FSCK] Unreachable nat entries                        [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking                [Ok..]
[FSCK] Hard link checking for regular file            [Ok..] [0x0]
[FSCK] valid_block_count matching with CP             [Ok..] [0x2]
[FSCK] valid_node_count matcing with CP (de lookup)   [Ok..] [0x1]
[FSCK] valid_node_count matcing with CP (nat lookup)  [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP              [Ok..] [0x1]
[FSCK] free segment_count matched with CP             [Ok..] [0x24]
[FSCK] next block offset is free                      [Ok..]

[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Ok..]

Done.

Quoted 46 lines

---
Hi, k

Could you please try this? I think I've correct all endianness issue. And can I have your reported-by and test-by?

thanks,
Sheng

---
 fsck/dir.c        |  6 +++---
 fsck/dump.c       | 10 +++++-----
 fsck/f2fs.h       |  4 ++--
 fsck/mount.c      | 12 ++++++------
 fsck/node.c       |  2 +-
 fsck/segment.c    |  3 ++-
 include/f2fs_fs.h |  8 +++++---
 7 files changed, 24 insertions(+), 21 deletions(-)
fsck/dir.c +2 -2
index 2009855..d817d27 100644
@@ -134,7 +134,7 @@ static int find_in_level(struct f2fs_sb_info *sbi,struct f2fs_node *dir,
        struct dnode_of_data dn = {0};
        void *dentry_blk;
        int max_slots = 214;
-       nid_t ino = dir->footer.ino;
+       nid_t ino = le32_to_cpu(dir->footer.ino);
        f2fs_hash_t namehash;
        int ret = 0;
 
@@ -191,7 +191,7 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi,
                return 0;
        }
 
-       max_depth = dir->i.i_current_depth;
+       max_depth = le32_to_cpu(dir->i.i_current_depth);
        for (level = 0; level < max_depth; level ++) {
                if (find_in_level(sbi, dir, level, de))
                        return 1;
@@ -209,7 +209,7 @@ static void f2fs_update_dentry(nid_t ino, umode_t mode,
        int i;
 
        de = &d->dentry[bit_pos];
(quoted diff) +1 -1
-       de->>name_len = len;
+       de->>name_len = cpu_to_le16(len);
Quoted 61 lines
fsck/dir.c +0 -0
        de->hash_code = name_hash;
        memcpy(d->filename[bit_pos], name, len);
        d->filename[bit_pos][len] = 0;
fsck/dump.c +1 -1
index 8e7c85c..e9d442f 100644
@@ -81,7 +81,7 @@ void nat_dump(struct f2fs_sb_info *sbi)
                                                "nid:%5u\tino:%5u\toffset:%5u"
                                                "\tblkaddr:%10u\tpack:%d\n",
                                                ni.nid, ni.ino,
-                                               node_block->footer.flag >>
+                                              

le32_to_cpu(node_block->footer.flag) >>

                                                        OFFSET_BIT_SHIFT,
                                                ni.blk_addr, pack);
                                        ret = write(fd, buf, strlen(buf));
fsck/dump.c +1 -1
@@ -100,7 +100,7 @@ void nat_dump(struct f2fs_sb_info *sbi)
                                        "nid:%5u\tino:%5u\toffset:%5u"
                                        "\tblkaddr:%10u\tpack:%d\n",
                                        ni.nid, ni.ino,
-                                       node_block->footer.flag >>
+                                      

le32_to_cpu(node_block->footer.flag) >>

                                                OFFSET_BIT_SHIFT,
                                        ni.blk_addr, pack);
                                ret = write(fd, buf, strlen(buf));
fsck/dump.c +3 -3
@@ -335,13 +335,13 @@ static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
        for (i = 0; i < 5; i++) {
                if (i == 0 || i == 1)
                        dump_node_blk(sbi, TYPE_DIRECT_NODE,
-                                       node_blk->i.i_nid[i], &ofs);
+                                      
 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
                else if (i == 2 || i == 3)
                        dump_node_blk(sbi, TYPE_INDIRECT_NODE,
-                                       node_blk->i.i_nid[i], &ofs);
+                                      
 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
                else if (i == 4)
                        dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
-                                       node_blk->i.i_nid[i], &ofs);
+                                      
 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
                else
                        ASSERT(0);
        }
fsck/f2fs.h +1 -1
index 1a0723c..0650d10 100644
@@ -359,7 +359,7 @@ static inline block_t sum_blk_addr(struct
 f2fs_sb_info *sbi, int base, int type)
 static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
 {
        return (nid <= (NAT_ENTRY_PER_BLOCK *
-                       F2FS_RAW_SUPER(sbi)->segment_count_nat
+                      
 le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_nat)
                        << (sbi->log_blocks_per_seg - 1)));

}

Quoted 98 lines

fsck/f2fs.h static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr) · line 368

Quoted 3 lines
fsck/f2fs.h +0 -0
@@ -367,7 +367,7 @@ static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
 {
        int i;

- if (addr >>= F2FS_RAW_SUPER(sbi)->block_count ||

Quoted 90 lines
fsck/f2fs.h +1 -0
+       if (le64_to_cpu(addr >= F2FS_RAW_SUPER(sbi)->block_count) ||
                                addr < SM_I(sbi)->main_blkaddr) {
                DBG(1, "block addr [0x%x]\n", addr);
                return 0;
fsck/mount.c +0 -2
index 21a96a7..d5a91a5 100644
@@ -1375,12 +1375,12 @@ void build_sit_area_bitmap(struct f2fs_sb_info *sbi)
                ptr += SIT_VBLOCK_MAP_SIZE;
 
                if (se->valid_blocks == 0x0) {
-                       if (sbi->ckpt->cur_node_segno[0] == segno ||
-                                      

sbi->ckpt->cur_data_segno[0] == segno ||
-
sbi->ckpt->cur_node_segno[1] == segno ||
-
sbi->ckpt->cur_data_segno[1] == segno ||
-
sbi->ckpt->cur_node_segno[2] == segno ||
-
sbi->ckpt->cur_data_segno[2] == segno) {
+ if
(le32_to_cpu(sbi->ckpt->cur_node_segno[0]) == segno || +
le32_to_cpu(sbi->ckpt->cur_data_segno[0]) == segno || +
le32_to_cpu(sbi->ckpt->cur_node_segno[1]) == segno || +
le32_to_cpu(sbi->ckpt->cur_data_segno[1]) == segno || +
le32_to_cpu(sbi->ckpt->cur_node_segno[2]) == segno || +

le32_to_cpu(sbi->ckpt->cur_data_segno[2]) == segno) {
                                continue;
                        } else {
                                free_segs++;
fsck/node.c +1 -1
index c2f83b8..fe923e5 100644
@@ -78,7 +78,7 @@ block_t new_node_block(struct f2fs_sb_info *sbi,
 
        type = CURSEG_COLD_NODE;
        if (IS_DNODE(node_blk)) {
-               if (S_ISDIR(f2fs_inode->i.i_mode))
+               if (S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode)))
                        type = CURSEG_HOT_NODE;
                else
                        type = CURSEG_WARM_NODE;
fsck/segment.c +2 -1
index 9ce8bf5..6b2f6c1 100644
@@ -80,7 +80,8 @@ static void f2fs_write_block(struct f2fs_sb_info *sbi, nid_t ino, void *buffer,
        ret = dev_read_block(inode, ni.blk_addr);
        ASSERT(ret >= 0);
 
-       if (S_ISDIR(inode->i.i_mode) || S_ISLNK(inode->i.i_mode))
+       if (S_ISDIR(le16_to_cpu(inode->i.i_mode)) ||
+                       S_ISLNK(le16_to_cpu(inode->i.i_mode)))
                ASSERT(0);
 
        off_in_block = offset & ((1 << F2FS_BLKSIZE_BITS) - 1);
include/f2fs_fs.h +5 -3
index 78ea939..ef34ca2 100644
@@ -170,15 +170,17 @@ static inline uint64_t bswap_64(uint64_t val)
 #define DISP_u32(ptr, member)                                     
        do {                                                       
                assert(sizeof((ptr)->member) <= 4);                
-               printf("%-30s" "\t\t[0x%8x : %u]\n",            \
-                       #member, ((ptr)->member), ((ptr)->member));
+               printf("%-30s" "\t\t[0x%8x : %u]\n",               
+                       #member, le32_to_cpu(((ptr)->member)),     
+                       le32_to_cpu(((ptr)->member)));             
        } while (0)
 
 #define DISP_u64(ptr, member)                                     
        do {                                                       
                assert(sizeof((ptr)->member) == 8);                
                printf("%-30s" "\t\t[0x%8llx : %llu]\n",           
-                       #member, ((ptr)->member), ((ptr)->member));
+                       #member, le64_to_cpu(((ptr)->member)),     
+                       le64_to_cpu(((ptr)->member)));             
        } while (0)
 
 #define DISP_utf(ptr, member)                                     

------------------------------------------------------------------------------