From cd1e4704d0cbf1cbb49b3f33c576566b4b1e296e Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 20 Aug 2013 18:05:56 +0900 Subject: fsck, lib: support inline xattr This patch adjusts the modification to handle inline xattrs. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 2 +- fsck/mount.c | 2 +- include/f2fs_fs.h | 17 ++++++++++++++--- lib/libf2fs.c | 7 +++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 6a5f659..d491a3d 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -334,7 +334,7 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt); /* check data blocks in inode */ - for (idx = 0; idx < ADDRS_PER_INODE; idx++) { + for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) { if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) { *blk_cnt = *blk_cnt + 1; ret = fsck_chk_data_blk(sbi, diff --git a/fsck/mount.c b/fsck/mount.c index d936600..7ab53b8 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -51,7 +51,7 @@ void print_inode_info(struct f2fs_inode *inode) DISP_u32(inode, i_addr[2]); /* Pointers to data blocks */ DISP_u32(inode, i_addr[3]); /* Pointers to data blocks */ - for (i = 4; i < ADDRS_PER_INODE; i++) { + for (i = 4; i < ADDRS_PER_INODE(inode); i++) { if (inode->i_addr[i] != 0x0) { printf("i_addr[0x%x] points data block\r\t\t\t\t[0x%4x]\n", i, inode->i_addr[i]); diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 7081e5e..c3cdea2 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -346,14 +346,25 @@ struct f2fs_extent { } __attribute__((packed)); #define F2FS_NAME_LEN 255 -#define ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ +#define F2FS_INLINE_XATTR_ADDRS 50 /* 200 bytes for inline xattrs */ +#define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ +#define ADDRS_PER_INODE(fi) addrs_per_inode(fi) #define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ #define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ +#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) +#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) +#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3) +#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4) +#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5) + +#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ +#define F2FS_INLINE_DATA 0x02 /* file inline data flag */ + struct f2fs_inode { __le16 i_mode; /* file mode */ __u8 i_advise; /* file hints */ - __u8 i_reserved; /* reserved */ + __u8 i_inline; /* file inline flags */ __le32 i_uid; /* user ID */ __le32 i_gid; /* group ID */ __le32 i_links; /* links count */ @@ -376,7 +387,7 @@ struct f2fs_inode { struct f2fs_extent i_ext; /* caching a largest extent */ - __le32 i_addr[ADDRS_PER_INODE]; /* Pointers to data blocks */ + __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ __le32 i_nid[5]; /* direct(2), indirect(2), double_indirect(1) node id */ diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 6947425..988c854 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -315,6 +315,13 @@ exit: return f2fs_hash; } +unsigned int addrs_per_inode(struct f2fs_inode *i) +{ + if (i->i_inline & F2FS_INLINE_XATTR) + return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS; + return DEF_ADDRS_PER_INODE; +} + /* * CRC32 */ -- cgit v1.2.3 From b155ea8e18a2de5a5d09d3c969cc6fd79a04cb1d Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Sat, 31 Aug 2013 08:41:31 +0900 Subject: f2fs-tools: discard is default but not set in config flash devices support discard therefore discard is default but not set in config Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- lib/libf2fs.c | 1 + mkfs/f2fs_format.c | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 988c854..3984697 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -371,6 +371,7 @@ void f2fs_init_configuration(struct f2fs_configuration *c) c->heap = 1; c->vol_label = ""; c->device_name = NULL; + c->trim = 1; } static int is_mounted(const char *mpt, const char *device) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 5b017c7..364bb46 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -917,6 +917,7 @@ int f2fs_trim_device() return -1; } + MSG(0, "Info: Discarding device\n"); if (S_ISREG(stat_buf.st_mode)) return 0; else if (S_ISBLK(stat_buf.st_mode)) { -- cgit v1.2.3 From 78b795e05d411e28f2480f78ad9225bd21e199fe Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 8 Oct 2013 18:17:33 +0900 Subject: fsck: skip to check block addresses in device files The device files use i_addr or i_nid fields for their rdev numbers. So, fsck should skip to check block addresses inside of them. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index d491a3d..d5efb63 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -333,6 +333,10 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt); + if (ftype & F2FS_FT_CHRDEV || ftype & F2FS_FT_BLKDEV || + ftype & F2FS_FT_FIFO || ftype & F2FS_FT_SOCK) + goto check; + /* check data blocks in inode */ for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) { if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) { @@ -373,7 +377,7 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, ASSERT(ret >= 0); } } - +check: if (ftype & F2FS_FT_DIR) DBG(1, "Directory Inode: ino: %x name: %s depth: %d child files: %d\n\n", le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, @@ -606,6 +610,7 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u8 ver) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + /* Is it reserved block? */ if (blk_addr == NEW_ADDR) { fsck->chk.valid_blk_cnt++; -- cgit v1.2.3 From 76a069430a295a27bf478d4a5d2fd71112a11a54 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 8 Oct 2013 18:46:55 +0900 Subject: fsck: fix to handle file types correctly The file type is based on the number, not bit operations. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 47 +++++++++++++++++++++++++++-------------------- include/f2fs_fs.h | 18 +++++++++--------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index d5efb63..68a2980 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -10,6 +10,17 @@ */ #include "fsck.h" +#define S_SHIFT 12 +static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = { + [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE, + [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR, + [S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV, + [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV, + [S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO, + [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK, + [S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK, +}; + char *tree_mark; int tree_mark_size = 256; @@ -258,6 +269,10 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, return 0; } +static enum FILE_TYPE get_de_type(unsigned short mode) +{ + return f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; +} int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, @@ -281,18 +296,14 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, fsck->chk.valid_inode_cnt++; /* Orphan node. i_links should be 0 */ - if (ftype & F2FS_FT_ORPHAN) { + if (ftype == F2FS_FT_ORPHAN) { ASSERT(i_links == 0); - - if (S_ISDIR(le16_to_cpu(node_blk->i.i_mode))) - ftype |= F2FS_FT_DIR; - else - ftype |= F2FS_FT_REG_FILE; + ftype = get_de_type(le16_to_cpu(node_blk->i.i_mode)); } else { ASSERT(i_links > 0); } - if (ftype & F2FS_FT_DIR) { + if (ftype == F2FS_FT_DIR) { /* not included '.' & '..' */ if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) != 0) { @@ -301,7 +312,7 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, } f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap); - } else if (ftype & F2FS_FT_REG_FILE) { + } else { if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) == 0x0) { f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap); @@ -325,16 +336,13 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, /* No need to go deep into the node */ goto out; - } - } else { - ASSERT(0); } fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt); - if (ftype & F2FS_FT_CHRDEV || ftype & F2FS_FT_BLKDEV || - ftype & F2FS_FT_FIFO || ftype & F2FS_FT_SOCK) + if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV || + ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK) goto check; /* check data blocks in inode */ @@ -378,11 +386,11 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, } } check: - if (ftype & F2FS_FT_DIR) + if (ftype == F2FS_FT_DIR) DBG(1, "Directory Inode: ino: %x name: %s depth: %d child files: %d\n\n", le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, le32_to_cpu(node_blk->i.i_current_depth), child_files); - if ((ftype & F2FS_FT_DIR && i_links != child_cnt) || + if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || (i_blocks != *blk_cnt)) { print_node_info(node_blk); DBG(1, "blk cnt [0x%x]\n", *blk_cnt); @@ -390,7 +398,7 @@ check: } ASSERT(i_blocks == *blk_cnt); - if (ftype & F2FS_FT_DIR) + if (ftype == F2FS_FT_DIR) ASSERT(i_links == child_cnt); out: return 0; @@ -553,12 +561,11 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, hash_code = f2fs_dentry_hash((const char *)name, name_len); ASSERT(le32_to_cpu(de_blk->dentry[i].hash_code) == hash_code); - ftype = F2FS_FT_REG_FILE; + ftype = de_blk->dentry[i].file_type; /* Becareful. 'dentry.file_type' is not imode. */ - if (de_blk->dentry[i].file_type == F2FS_FT_DIR) { + if (ftype == F2FS_FT_DIR) { *child_cnt = *child_cnt + 1; - ftype = F2FS_FT_DIR; if ((name[0] == '.' && name[1] == '.' && name_len == 2) || (name[0] == '.' && name_len == 1)) { i++; @@ -633,7 +640,7 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, fsck->chk.valid_blk_cnt++; - if ((ftype & F2FS_FT_DIR) && !(ftype & F2FS_FT_ORPHAN)) { + if (ftype == F2FS_FT_DIR) { fsck_chk_dentry_blk(sbi, inode, blk_addr, diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index c3cdea2..5db2808 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -618,16 +618,16 @@ struct f2fs_dentry_block { /* file types used in inode_info->flags */ enum FILE_TYPE { F2FS_FT_UNKNOWN, - F2FS_FT_REG_FILE = 0x1, - F2FS_FT_DIR = 0x2, - F2FS_FT_CHRDEV = 0x4, - F2FS_FT_BLKDEV = 0x8, - F2FS_FT_FIFO = 0x10, - F2FS_FT_SOCK = 0x20, - F2FS_FT_SYMLINK = 0x40, - F2FS_FT_MAX = 0x80, + F2FS_FT_REG_FILE, + F2FS_FT_DIR, + F2FS_FT_CHRDEV, + F2FS_FT_BLKDEV, + F2FS_FT_FIFO, + F2FS_FT_SOCK, + F2FS_FT_SYMLINK, + F2FS_FT_MAX, /* added for fsck */ - F2FS_FT_ORPHAN = 0x1000, + F2FS_FT_ORPHAN, }; /* from f2fs/segment.h */ -- cgit v1.2.3 From 465e4e7f10f59efba184fdd0788e92ea1488011c Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 8 Oct 2013 20:04:35 +0900 Subject: libf2fs: avoid warning of implicit declaration This patch adds extern declaration. Signed-off-by: Jaegeuk Kim --- include/f2fs_fs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 5db2808..fb7c94c 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -638,6 +638,7 @@ enum { extern void ASCIIToUNICODE(u_int16_t *, u_int8_t *); extern int log_base_2(u_int32_t); +extern unsigned int addrs_per_inode(struct f2fs_inode *); extern int get_bits_in_byte(unsigned char n); extern int set_bit(unsigned int nr,void * addr); -- cgit v1.2.3 From 8e678b2edfba95f3edbb1730c69da365d659e95d Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 16 Oct 2013 13:48:45 +0900 Subject: fsck: fix checking orphan inodes This patch fixes bugs in the orphan inode procedure. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 68a2980..cdf68ab 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -269,11 +269,6 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, return 0; } -static enum FILE_TYPE get_de_type(unsigned short mode) -{ - return f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; -} - int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, enum FILE_TYPE ftype, @@ -298,7 +293,6 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, /* Orphan node. i_links should be 0 */ if (ftype == F2FS_FT_ORPHAN) { ASSERT(i_links == 0); - ftype = get_de_type(le16_to_cpu(node_blk->i.i_mode)); } else { ASSERT(i_links > 0); } @@ -390,6 +384,10 @@ check: DBG(1, "Directory Inode: ino: %x name: %s depth: %d child files: %d\n\n", le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, le32_to_cpu(node_blk->i.i_current_depth), child_files); + if (ftype == F2FS_FT_ORPHAN) + DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %d\n\n", + le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, + i_blocks); if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || (i_blocks != *blk_cnt)) { print_node_info(node_blk); -- cgit v1.2.3 From 050e8712a60c7d982a7be8c076fb72452364dae4 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 17 Oct 2013 15:15:54 +0900 Subject: README: add description how to cross-compile This patch adds description for the cross-compilation. Signed-off-by: Jaegeuk Kim --- README | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README b/README index cbb492e..bf374fb 100644 --- a/README +++ b/README @@ -25,6 +25,20 @@ How to compile # ./configure # make +How to cross-compile (e.g., for ARM) +------------------------------------ + + 1. Add the below line into mkfs/Makefile.am: + mkfs_f2fs_LDFLAGS = -all-static + + 2. Add the below line into fsck/Makefile.am: + fsck_f2fs_LDFLAGS = -all-static + + 3. then, do: + # LDFLAGS=--static ./configure \ + --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi + # make + How to run by default --------------------- -- cgit v1.2.3 From 5b9f641c0608ad87f127b4cb766de91d7d80449a Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 17 Oct 2013 15:26:23 +0900 Subject: scripts: add some scripts 1. dumpf2fs.sh : to see internal device with hexdump 2. spo_test.sh : to run SPOR 3. tracepoint.sh : to turn on tracepoints Signed-off-by: Jaegeuk Kim --- scripts/dumpf2fs.sh | 61 ++++++++++++++++++++++++++++++++++++++++++++ scripts/spo_test.sh | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ scripts/tracepoint.sh | 59 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100755 scripts/dumpf2fs.sh create mode 100755 scripts/spo_test.sh create mode 100755 scripts/tracepoint.sh diff --git a/scripts/dumpf2fs.sh b/scripts/dumpf2fs.sh new file mode 100755 index 0000000..2c2a273 --- /dev/null +++ b/scripts/dumpf2fs.sh @@ -0,0 +1,61 @@ +#!/system/bin/sh +DEV=/dev/block/mmcblk0p16 + +CMD=$1 +BASE=0x200000 +BASE_MAIN=0xac00000 + +case $CMD in +cp1) + echo dump cp1 + let addr=$BASE + echo $addr + hexdump -s $addr -n 4096 $DEV;; +cp2) + echo dump cp2 + let addr=$BASE+0x200000 + hexdump -s $addr -n 4096 $DEV;; +cp) + echo dump cp1 and cp2 + let addr=$BASE + hexdump -s $addr -n 409 $DEV + let addr=$BASE+0x200000 + hexdump -s $addr -n 4096 $DEV;; +cp1_all) + echo dump cp1 all + let addr=$BASE + hexdump -s $addr -n 20480 $DEV;; +cp2_all) + echo dump cp2 all + let addr=$BASE+0x200000 + hexdump -s $addr -n 20480 $DEV;; +cp_all) + echo dump cp1 and cp2 all + let addr=$BASE + hexdump -s $addr -n 20480 $DEV + let addr=$BASE+0x200000 + hexdump -s $addr -n 20480 $DEV;; +blk) + let addr=$BASE_MAIN+$2*0x200000+$3*0x1000 + hexdump -s $addr -n 4096 $DEV + echo ;; +inode) + let addr=$BASE_MAIN+$2*0x200000+$3*0x1000 + for i in `seq $3 511` + do + hexdump -s $addr -n 8 $DEV + let end=$addr+0x0ff0 + hexdump -s $end -n 16 $DEV + let addr=$addr+0x1000 + done + echo ;; +*) + let addr=$1*0x1000 + let segno=$addr-$BASE_MAIN + let segno=$segno/0x200000 + let off=$addr-$BASE_MAIN + let off=$off%0x200000/0x1000 + echo $segno, $off + hexdump -s $addr -n 4096 $DEV + echo ;; +esac diff --git a/scripts/spo_test.sh b/scripts/spo_test.sh new file mode 100755 index 0000000..2191214 --- /dev/null +++ b/scripts/spo_test.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +MNT=/mnt/f2fs +DEV=/dev/sdb1 +USER_DIR=/home/zeus +F2FS_DIR=$USER_DIR/f2fs_test + +check_stop() { + stop=`cat /tmp/stop` + if [ $stop -eq 1 ]; then + exit + fi +} + +case $1 in +start) + echo 0 > /tmp/stop + umount /mnt/* + echo 3 > /proc/sys/vm/drop_caches + echo 8 > /proc/sys/kernel/printk + + date >> $USER_DIR/por_result + sync + + insmod $F2FS_DIR/src/fs/f2fs/f2fs.ko || exit + + echo Start checking F2FS without fsync + check_stop + fsck.f2fs $DEV -d 0 || exit + mount -t f2fs -o disable_roll_forward $DEV $MNT || exit + umount $MNT + echo 3 > /proc/sys/vm/drop_caches + + echo Start checking F2FS with fsync + check_stop + fsck.f2fs $DEV -d 0 || exit + mount -t f2fs $DEV $MNT || exit + umount $MNT + + check_stop + fsck.f2fs $DEV -d 0 || exit + mount -t f2fs $DEV $MNT || exit + + count=`cat $USER_DIR/por_time` + if [ $count -eq 20 ]; then + echo Start rm all + time rm -rf $MNT/* || exit + echo 0 > $USER_DIR/por_time + sync + else + echo $((count+1)) > $USER_DIR/por_time + fi + echo 8 > /proc/sys/kernel/printk + echo Start fsstress + date + $F2FS_DIR/stress_test/fsstress/fsstress -z -f link=0 -f mkdir=3 -f mknod=3 -f rmdir=2 -f symlink=3 -f truncate=4 -f write=10 -f creat=10 -f unlink=5 -f rename=5 -f fsync=10 -p 10 -n 10000 -l 0 -d $MNT & + RANDOM=`date '+%s'` + rand=$[($RANDOM % 540) + 60] + echo Start sleep: $rand seconds + sleep $rand + + echo Reboot now + check_stop + echo b > /proc/sysrq-trigger + ;; +stop) + killall -9 fsstress + echo 1 > /tmp/stop + ;; +esac diff --git a/scripts/tracepoint.sh b/scripts/tracepoint.sh new file mode 100755 index 0000000..b0d2fcb --- /dev/null +++ b/scripts/tracepoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +TRACE=/sys/kernel/debug/tracing/ +dev=$(((8<<20) + 17)) # sdb1 (8,17) + +echo 1 > tracing_on + +# block tracepoints +echo "dev == $dev" > $TRACE/events/block/block_rq_complete/filter +echo 1 > $TRACE/events/block/block_rq_complete/enable +echo 0 > $TRACE/events/block/block_bio_complete/enable + +# GC +G=0 +echo $G > $TRACE/events/f2fs/f2fs_get_victim/enable + +# block allocation +A=0 +echo $A > $TRACE/events/f2fs/f2fs_reserve_new_block/enable + +# block truncation +T=0 +echo $T > $TRACE/events/f2fs/f2fs_truncate/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_inode_blocks_enter/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_inode_blocks_exit/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_blocks_enter/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_blocks_exit/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_nodes_enter/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_nodes_exit/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_data_blocks_range/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_node/enable +echo $T > $TRACE/events/f2fs/f2fs_truncate_partial_nodes/enable + +# syscalls +S=0 +echo $S > $TRACE/events/f2fs/f2fs_unlink_enter/enable +echo $S > $TRACE/events/f2fs/f2fs_unlink_exit/enable +echo $S > $TRACE/events/f2fs/f2fs_fallocate/enable +echo $S > $TRACE/events/f2fs/f2fs_get_data_block/enable + +# IOs +R=0 +W=0 +echo $W > $TRACE/events/f2fs/f2fs_submit_write_page/enable +echo $W > $TRACE/events/f2fs/f2fs_do_submit_bio/enable +echo $R > $TRACE/events/f2fs/f2fs_readpage/enable + +# VFS interfaces +V=0 +echo $V > $TRACE/events/f2fs/f2fs_iget/enable +echo $V > $TRACE/events/f2fs/f2fs_iget_exit/enable +echo $V > $TRACE/events/f2fs/f2fs_new_inode/enable +echo $V > $TRACE/events/f2fs/f2fs_evict_inode/enable +echo $V > $TRACE/events/f2fs/f2fs_sync_file_enter/enable +echo $V > $TRACE/events/f2fs/f2fs_sync_file_exit/enable +echo $V > $TRACE/events/f2fs/f2fs_write_checkpoint/enable +echo $V > $TRACE/events/f2fs/f2fs_sync_fs/enable + +cat $TRACE/trace_pipe -- cgit v1.2.3 From 2ad1fcd800747851a1db9a84acc87086c621f54d Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 17 Oct 2013 17:28:15 +0900 Subject: mkfs: add two file extensions for android This patch adds two file extensions, jpeg and video, to identify cold files in android systems. Signed-off-by: Jaegeuk Kim --- mkfs/f2fs_format.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 364bb46..8234b00 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -130,6 +130,8 @@ const char *media_ext_lists[] = { "mpe", "rm", "ogg", + "jpeg", + "video", "apk", /* for android system */ NULL }; -- cgit v1.2.3 From 576cb469e73b9342f1d10ba5d0428bbce22cbc3b Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 25 Oct 2013 16:10:18 +0900 Subject: f2fs-tools: release 1.2.0 This version includes: - initial fsck and dump tools - libraries for f2fs - bug fixes - etc Signed-off-by: Jaegeuk Kim --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index a2cfa19..c3a3dd8 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -1.1.0 -2012-11-29 +1.2.0 +2013-10-25 -- cgit v1.2.3 From f1d452af4a353380483b916a3e1c44fc8eb796b7 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 30 Oct 2013 11:16:01 +0900 Subject: fsck: fix orphan node blocks Previously, fsck handles only the orphan inode block excpet its indirect node blocks. This causes false-alarm, unreachable nat entries [xxx]. This patch fixes to cover indirect node blocks in an orphan inode. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index cdf68ab..4c4e3c1 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -174,8 +174,11 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, IS_VALID_NID(sbi, nid); - if (ftype != F2FS_FT_ORPHAN) + if (ftype != F2FS_FT_ORPHAN || + f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0x0) f2fs_clear_bit(nid, fsck->nat_area_bitmap); + else + ASSERT_MSG(0, "nid duplicated [0x%x]\n", nid); ret = get_node_info(sbi, nid, &ni); ASSERT(ret >= 0); @@ -672,21 +675,7 @@ int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { nid_t ino = le32_to_cpu(orphan_blk->ino[j]); - DBG(3, "[%3ld] ino [0x%x]\n", i, ino); - - /* 1) 'fsck_init' build nat_bitmap - * 2) 'fsck_chk_node_blk' clear nat_bitmap if exist in dentry - * 3) if nat_bitmap is already cleared, it means that node exist in dentry, - */ - if (f2fs_test_bit(ino, fsck->nat_area_bitmap) != 0x0) { - f2fs_clear_bit(ino, fsck->nat_area_bitmap); - } else { - DBG(0, "orphan inode [0x%x] exist in dentry\n", ino); - ASSERT(0); - } - - DBG(1, "Orphan inode ino[0x%x]\n", ino); - + DBG(1, "[%3ld] ino [0x%x]\n", i, ino); blk_cnt = 1; ret = fsck_chk_node_blk(sbi, NULL, -- cgit v1.2.3 From ffbada4298c7aed059bb99a8d553d6dd555963c0 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 11 Nov 2013 13:29:11 +0900 Subject: mkfs: remove stale node blocks If the device does not support discard, we should write zero blocks to avoid roll-forward recovery. Reported-and-tested-by: Huajun Li Signed-off-by: Jaegeuk Kim --- mkfs/f2fs_format.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 8234b00..18ded79 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -788,7 +788,12 @@ static int f2fs_write_root_inode(void) memset(raw_node, 0xff, sizeof(struct f2fs_node)); - main_area_node_seg_blk_offset += F2FS_BLKSIZE; + /* avoid power-off-recovery based on roll-forward policy */ + main_area_node_seg_blk_offset = le32_to_cpu(super_block.main_blkaddr); + main_area_node_seg_blk_offset += config.cur_seg[CURSEG_WARM_NODE] * + config.blks_per_seg; + main_area_node_seg_blk_offset *= blk_size_bytes; + if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the raw_node to disk!!!\n"); return -1; -- cgit v1.2.3 From 11d187cdfa2dcf504aa25b5a1aab4228f19f22ff Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 16 Dec 2013 12:32:37 +0900 Subject: README: add libtool guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The f2fs-tools needs libtool package to compile sources. Suggested-by: Sérgio Benjamim Signed-off-by: Jaegeuk Kim --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index bf374fb..222cbc3 100644 --- a/README +++ b/README @@ -11,6 +11,7 @@ Your should install the following packages. - libuuid-devel or uuid-dev - pkg-config - autoconf + - libtool Initial compilation ------------------- -- cgit v1.2.3 From 061ee67915ba3e8c86bde89a2efb1b8a9aadfb37 Mon Sep 17 00:00:00 2001 From: Huajun Li Date: Sat, 26 Oct 2013 00:12:40 +0800 Subject: f2fs-tools: add inline data check Add inline data check Signed-off-by: Weihong Xu Signed-off-by: Huajun Li Signed-off-by: Haicheng Li Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 4 ++++ include/f2fs_fs.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/fsck/fsck.c b/fsck/fsck.c index 4c4e3c1..81223c7 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -341,6 +341,10 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV || ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK) goto check; + if((node_blk->i.i_inline & F2FS_INLINE_DATA)){ + DBG(3, "ino[0x%x] has inline data!\n", nid); + goto check; + } /* check data blocks in inode */ for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) { diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index fb7c94c..68f427d 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -360,6 +360,11 @@ struct f2fs_extent { #define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ #define F2FS_INLINE_DATA 0x02 /* file inline data flag */ +#define MAX_INLINE_DATA (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \ + F2FS_INLINE_XATTR_ADDRS - 1)) + +#define INLINE_DATA_OFFSET (PAGE_CACHE_SIZE - sizeof(struct node_footer) \ + - sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1)) struct f2fs_inode { __le16 i_mode; /* file mode */ -- cgit v1.2.3 From 1aae03594ba111174ed4902a29b969a1fb145adf Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 27 Dec 2013 12:57:51 +0900 Subject: fibmap: fix wrong block count This is an obvious bug fix patch. Signed-off-by: Jaegeuk Kim --- fsck/fibmap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fsck/fibmap.c b/fsck/fibmap.c index 0ced7ca..9eb6b90 100644 --- a/fsck/fibmap.c +++ b/fsck/fibmap.c @@ -103,12 +103,11 @@ int main(int argc, char *argv[]) ext.end_blk = blknum; ext.blk_count++; } else { - ext.blk_count++; print_ext(&ext); ext.f_pos = i * st.st_blksize; ext.start_blk = blknum; ext.end_blk = blknum; - ext.blk_count = 0; + ext.blk_count = 1; } } -- cgit v1.2.3 From 437dbf67730d2765c4dfc8539b07258e1ca3966f Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 10 Jan 2014 21:16:10 -0800 Subject: mkfs: completely abstract the dev IO during format This change allows for f2fs_format to work on a non-standard device (e.g. sparse-memory backed file). Removes direct access to config.fd from within f2fs_format.c. Now, f2fs_format_device() can be made to work against any device by providing f2fs_finalize_device() f2fs_trim_device() and the lib2fs.c functions ASCIIToUNICODE dev_write f2fs_cal_crc32 f2fs_set_bit log_base_2 This will allow Android's fastboot to use f2fs against a libsparse. Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- mkfs/Makefile.am | 2 +- mkfs/f2fs_format.c | 38 ++---------------------------- mkfs/f2fs_format_utils.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ mkfs/f2fs_format_utils.h | 18 +++++++++++++++ 4 files changed, 81 insertions(+), 37 deletions(-) create mode 100644 mkfs/f2fs_format_utils.c create mode 100644 mkfs/f2fs_format_utils.h diff --git a/mkfs/Makefile.am b/mkfs/Makefile.am index 08432da..79cbec2 100644 --- a/mkfs/Makefile.am +++ b/mkfs/Makefile.am @@ -3,5 +3,5 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include AM_CFLAGS = -Wall sbin_PROGRAMS = mkfs.f2fs -mkfs_f2fs_SOURCES = f2fs_format.c +mkfs_f2fs_SOURCES = f2fs_format.c f2fs_format_utils.c mkfs_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 18ded79..60c8231 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -22,6 +22,7 @@ #include #include "f2fs_fs.h" +#include "f2fs_format_utils.h" extern struct f2fs_configuration config; struct f2fs_super_block super_block; @@ -908,33 +909,6 @@ exit: return err; } -int f2fs_trim_device() -{ - unsigned long long range[2]; - struct stat stat_buf; - - if (!config.trim) - return 0; - - range[0] = 0; - range[1] = config.total_sectors * DEFAULT_SECTOR_SIZE; - - if (fstat(config.fd, &stat_buf) < 0 ) { - MSG(1, "\tError: Failed to get the device stat!!!\n"); - return -1; - } - - MSG(0, "Info: Discarding device\n"); - if (S_ISREG(stat_buf.st_mode)) - return 0; - else if (S_ISBLK(stat_buf.st_mode)) { - if (ioctl(config.fd, BLKDISCARD, &range) < 0) - MSG(0, "Info: This device doesn't support TRIM\n"); - } else - return -1; - return 0; -} - static int f2fs_format_device(void) { int err = 0; @@ -984,15 +958,7 @@ exit: if (err) MSG(0, "\tError: Could not format the device!!!\n"); - /* - * We should call fsync() to flush out all the dirty pages - * in the block device page cache. - */ - if (fsync(config.fd) < 0) - MSG(0, "\tError: Could not conduct fsync!!!\n"); - - if (close(config.fd) < 0) - MSG(0, "\tError: Failed to close device file!!!\n"); + f2fs_finalize_device(); return err; } diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c new file mode 100644 index 0000000..4a43405 --- /dev/null +++ b/mkfs/f2fs_format_utils.c @@ -0,0 +1,60 @@ +/** + * f2fs_format_utils.c + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define _LARGEFILE64_SOURCE + +#include +#include +#include +#include + +#include "f2fs_fs.h" + +void f2fs_finalize_device() +{ + /* + * We should call fsync() to flush out all the dirty pages + * in the block device page cache. + */ + if (fsync(config.fd) < 0) + MSG(0, "\tError: Could not conduct fsync!!!\n"); + + if (close(config.fd) < 0) + MSG(0, "\tError: Failed to close device file!!!\n"); + +} + +int f2fs_trim_device() +{ + unsigned long long range[2]; + struct stat stat_buf; + + if (!config.trim) + return 0; + + range[0] = 0; + range[1] = config.total_sectors * DEFAULT_SECTOR_SIZE; + + if (fstat(config.fd, &stat_buf) < 0 ) { + MSG(1, "\tError: Failed to get the device stat!!!\n"); + return -1; + } + + MSG(0, "Info: Discarding device\n"); + if (S_ISREG(stat_buf.st_mode)) + return 0; + else if (S_ISBLK(stat_buf.st_mode)) { + if (ioctl(config.fd, BLKDISCARD, &range) < 0) + MSG(0, "Info: This device doesn't support TRIM\n"); + } else + return -1; + return 0; +} + diff --git a/mkfs/f2fs_format_utils.h b/mkfs/f2fs_format_utils.h new file mode 100644 index 0000000..745be64 --- /dev/null +++ b/mkfs/f2fs_format_utils.h @@ -0,0 +1,18 @@ +/** + * f2fs_format_utils.c + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define _LARGEFILE64_SOURCE + +#include "f2fs_fs.h" + +extern struct f2fs_configuration config; + +void f2fs_finalize_device(); +int f2fs_trim_device(); -- cgit v1.2.3 From cb54e79739672366d849e02a3068f857c6bb544c Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Thu, 9 Jan 2014 13:56:07 -0800 Subject: fix typo around CONFIG_64BIT usage Would do 64 BITS_PER_LONG when CONFIG_64BIT was NOT defined, causing BITS_PER_LONG to be wrong on 32bit systems. Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- include/f2fs_fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 68f427d..bf3049d 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -185,7 +185,7 @@ struct f2fs_configuration { void *private; } __attribute__((packed)); -#ifndef CONFIG_64BIT +#ifdef CONFIG_64BIT #define BITS_PER_LONG 64 #else #define BITS_PER_LONG 32 -- cgit v1.2.3 From 6da30100ee0f64687c5e1bc84bf86f0e312261d9 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Thu, 9 Jan 2014 17:53:18 -0800 Subject: mkfs: write the cp page 2 of the checkpoint pack 2 during format Currently mkfs followed by fsck will fail with [f2fs_crc_valid: 351] CRC validation failed: cal_crc = 4076150800 blk_crc = 0 buff_size = 0x0 This is because the validatie_checkpoint() tries to read and checksum the cp page 2, and it is invoked on both cp packs. But format only writes the page 1 of the 2nd checkpoint pack. Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- mkfs/f2fs_format.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 60c8231..5580e60 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -703,6 +703,13 @@ static int f2fs_write_check_point_pack(void) return -1; } + /* 10. cp page 2 of check point pack 2 */ + cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count) - 1); + if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { + MSG(1, "\tError: While writing the ckp to disk!!!\n"); + return -1; + } + free(sum) ; free(ckp) ; return 0; -- cgit v1.2.3 From a0a5567e3e2bdf81b71c7e8c6f801f8d55dcbb6e Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Fri, 10 Jan 2014 17:44:59 +0900 Subject: f2fs-tools: add f2fstat to print f2fs's status in sec This tool prints /sys/kernel/debug/f2fs/status in sec so that we can monitor variation of f2fs status. Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- Makefile.am | 2 +- configure.ac | 1 + tools/Makefile.am | 7 ++ tools/f2fstat.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 tools/Makefile.am create mode 100644 tools/f2fstat.c diff --git a/Makefile.am b/Makefile.am index ca376b4..d2921d6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,4 +2,4 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = man lib mkfs fsck +SUBDIRS = man lib mkfs fsck tools diff --git a/configure.ac b/configure.ac index c5ca858..c2dafb0 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,7 @@ AC_CONFIG_FILES([ lib/Makefile mkfs/Makefile fsck/Makefile + tools/Makefile ]) AC_OUTPUT diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000..8442387 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,7 @@ +## Makefile.am + +AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include +AM_CFLAGS = -Wall +sbin_PROGRAMS = f2fstat +f2fstat_SOURCES = f2fstat.c +f2fstat_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la diff --git a/tools/f2fstat.c b/tools/f2fstat.c new file mode 100644 index 0000000..e26e174 --- /dev/null +++ b/tools/f2fstat.c @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include + +#ifdef DEBUG +#define dbg(fmt, args...) printf(fmt, __VA_ARGS__); +#else +#define dbg(fmt, args...) +#endif + +/* + * f2fs status + */ +#define F2FS_STATUS "/sys/kernel/debug/f2fs/status" + +unsigned long util; +unsigned long used_node_blks; +unsigned long used_data_blks; +//unsigned long inline_inode; + +unsigned long free_segs; +unsigned long valid_segs; +unsigned long dirty_segs; +unsigned long prefree_segs; + +unsigned long gc; +unsigned long bg_gc; +unsigned long gc_data_blks; +unsigned long gc_node_blks; + +//unsigned long extent_hit_ratio; + +unsigned long dirty_node; +unsigned long dirty_dents; +unsigned long dirty_meta; +unsigned long nat_caches; +unsigned long dirty_sit; + +unsigned long free_nids; + +unsigned long ssr_blks; +unsigned long lfs_blks; + + +struct options { + int delay; + int interval; +}; + +struct mm_table { + const char *name; + unsigned long *val; +}; + +static int compare_mm_table(const void *a, const void *b) +{ + dbg("[COMPARE] %s, %s\n", ((struct mm_table *)a)->name, ((struct mm_table *)b)->name); + return strcmp(((struct mm_table *)a)->name, ((struct mm_table *)b)->name); +} + +static inline void remove_newline(char **head) +{ +again: + if (**head == '\n') { + *head = *head + 1; + goto again; + } +} + +void f2fstat(void) +{ + int fd; + int ret; + char keyname[32]; + char buf[4096]; + struct mm_table key = { keyname, NULL }; + struct mm_table *found; + int f2fstat_table_cnt; + char *head, *tail; + + static struct mm_table f2fstat_table[] = { + { " - Data", &used_data_blks }, + { " - Dirty", &dirty_segs }, + { " - Free", &free_segs }, + { " - NATs", &nat_caches }, + { " - Node", &used_node_blks }, + { " - Prefree", &prefree_segs }, + { " - SITs", &dirty_sit }, + { " - Valid", &valid_segs }, + { " - dents", &dirty_dents }, + { " - meta", &dirty_meta }, + { " - nodes", &dirty_node }, + { "GC calls", &gc }, + { "LFS", &lfs_blks }, + { "SSR", &ssr_blks }, + { "Utilization", &util }, + }; + + f2fstat_table_cnt = sizeof(f2fstat_table)/sizeof(struct mm_table); + + fd = open(F2FS_STATUS, O_RDONLY); + if (fd < 0) { + perror("open " F2FS_STATUS); + exit(EXIT_FAILURE); + } + + ret = read(fd, buf, 4096); + if (ret < 0) { + perror("read " F2FS_STATUS); + exit(EXIT_FAILURE); + } + buf[ret] = '\0'; + + head = buf; + for (;;) { + remove_newline(&head); + tail = strchr(head, ':'); + if (!tail) + break; + *tail = '\0'; + if (strlen(head) >= sizeof(keyname)) { + dbg("[OVER] %s\n", head); + *tail = ':'; + tail = strchr(head, '\n'); + head = tail + 1; + continue; + } + + strcpy(keyname, head); + + found = bsearch(&key, f2fstat_table, f2fstat_table_cnt, sizeof(struct mm_table), compare_mm_table); + dbg("[RESULT] %s (%s)\n", head, (found) ? "O" : "X"); + head = tail + 1; + if (!found) + goto nextline; + + *(found->val) = strtoul(head, &tail, 10); +nextline: + tail = strchr(head, '\n'); + if (!tail) + break; + head = tail + 1; + } + + close(fd); +} + +void usage(void) +{ + printf("Usage: f2fstat [option]\n" + " -d delay (secs)\n" + " -i interval of head info\n"); + exit(EXIT_FAILURE); +} + +void parse_option(int argc, char *argv[], struct options *opt) +{ + char option; + const char *option_string = "d:i:h"; + + while ((option = getopt(argc, argv, option_string)) != EOF) { + switch (option) { + case 'd': + opt->delay = atoi(optarg); + break; + case 'i': + opt->interval = atoi(optarg); + break; + default: + usage(); + break; + } + } +} + +void print_head(void) +{ + printf("---utilization--- -----------main area-------- ---balancing async-- -gc- ---alloc---\n"); + printf("util node data free valid dirty prefree node dent meta sit gc ssr lfs\n"); +} + +int main(int argc, char *argv[]) +{ + char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %3ld %5ld %6ld %6ld\n"; + int head_interval; + struct options opt = { + .delay = 1, + .interval = 20, + }; + + parse_option(argc, argv, &opt); + head_interval = opt.interval; + + print_head(); + while (1) { + if (head_interval-- == 0) { + print_head(); + head_interval = opt.interval; + } + + f2fstat(); + + printf(format, util, used_node_blks, used_data_blks, + free_segs, valid_segs, dirty_segs, prefree_segs, + dirty_node, dirty_dents, dirty_meta, dirty_sit, + gc, ssr_blks, lfs_blks); + + sleep(opt.delay); + } + + return 0; +} -- cgit v1.2.3 From e296161af0a2429f36b155a1ab75095f6e0a81f9 Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Thu, 16 Jan 2014 12:01:26 +0900 Subject: f2fs-tools: move fsck/fibmap.f2fs to tools/ Let's move miscellaneous utilities into tools directory. Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- fsck/Makefile.am | 4 +- fsck/fibmap.c | 118 ------------------------------------------------------ tools/Makefile.am | 4 +- tools/fibmap.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 123 deletions(-) delete mode 100644 fsck/fibmap.c create mode 100644 tools/fibmap.c diff --git a/fsck/Makefile.am b/fsck/Makefile.am index fc54e91..3258e47 100644 --- a/fsck/Makefile.am +++ b/fsck/Makefile.am @@ -2,11 +2,9 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include AM_CFLAGS = -Wall -sbin_PROGRAMS = fsck.f2fs fibmap.f2fs +sbin_PROGRAMS = fsck.f2fs fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c fsck_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la -fibmap_f2fs_SOURCES = fibmap.c - install-data-hook: ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/dump.f2fs diff --git a/fsck/fibmap.c b/fsck/fibmap.c deleted file mode 100644 index 9eb6b90..0000000 --- a/fsck/fibmap.c +++ /dev/null @@ -1,118 +0,0 @@ -#define _LARGEFILE64_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct file_ext { - __u32 f_pos; - __u32 start_blk; - __u32 end_blk; - __u32 blk_count; -}; - -void print_ext(struct file_ext *ext) -{ - if (ext->end_blk == 0) - printf("%8d %8d %8d %8d\n", ext->f_pos, 0, 0, ext->blk_count); - else - printf("%8d %8d %8d %8d\n", ext->f_pos, ext->start_blk, - ext->end_blk, ext->blk_count); -} - -void print_stat(struct stat64 *st) -{ - printf("--------------------------------------------\n"); - printf("dev [%d:%d]\n", major(st->st_dev), minor(st->st_dev)); - printf("ino [0x%8lx : %ld]\n", st->st_ino, st->st_ino); - printf("mode [0x%8x : %d]\n", st->st_mode, st->st_mode); - printf("nlink [0x%8lx : %ld]\n", st->st_nlink, st->st_nlink); - printf("uid [0x%8x : %d]\n", st->st_uid, st->st_uid); - printf("gid [0x%8x : %d]\n", st->st_gid, st->st_gid); - printf("size [0x%8lx : %ld]\n", st->st_size, st->st_size); - printf("blksize [0x%8lx : %ld]\n", st->st_blksize, st->st_blksize); - printf("blocks [0x%8lx : %ld]\n", st->st_blocks, st->st_blocks); - printf("--------------------------------------------\n\n"); -} - -int main(int argc, char *argv[]) -{ - int fd; - int ret = 0; - char *filename; - struct stat64 st; - int total_blks; - unsigned int i; - struct file_ext ext; - __u32 blknum; - - if (argc != 2) { - fprintf(stderr, "No filename\n"); - exit(-1); - } - filename = argv[1]; - - fd = open(filename, O_RDONLY|O_LARGEFILE); - if (fd < 0) { - ret = errno; - perror(filename); - exit(-1); - } - - fsync(fd); - - if (fstat64(fd, &st) < 0) { - ret = errno; - perror(filename); - goto out; - } - - total_blks = (st.st_size + st.st_blksize - 1) / st.st_blksize; - - printf("\n%s :\n", filename); - print_stat(&st); - printf("file_pos start_blk end_blk blks\n"); - - blknum = 0; - if (ioctl(fd, FIBMAP, &blknum) < 0) { - ret = errno; - perror("ioctl(FIBMAP)"); - goto out; - } - ext.f_pos = 0; - ext.start_blk = blknum; - ext.end_blk = blknum; - ext.blk_count = 1; - - for (i = 1; i < total_blks; i++) { - blknum = i; - - if (ioctl(fd, FIBMAP, &blknum) < 0) { - ret = errno; - perror("ioctl(FIBMAP)"); - goto out; - } - - if ((blknum == 0 && blknum == ext.end_blk) || (ext.end_blk + 1) == blknum) { - ext.end_blk = blknum; - ext.blk_count++; - } else { - print_ext(&ext); - ext.f_pos = i * st.st_blksize; - ext.start_blk = blknum; - ext.end_blk = blknum; - ext.blk_count = 1; - } - } - - print_ext(&ext); -out: - close(fd); - return ret; -} diff --git a/tools/Makefile.am b/tools/Makefile.am index 8442387..1ead174 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -2,6 +2,6 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include AM_CFLAGS = -Wall -sbin_PROGRAMS = f2fstat +sbin_PROGRAMS = f2fstat fibmap.f2fs f2fstat_SOURCES = f2fstat.c -f2fstat_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la +fibmap_f2fs_SOURCES = fibmap.c diff --git a/tools/fibmap.c b/tools/fibmap.c new file mode 100644 index 0000000..9eb6b90 --- /dev/null +++ b/tools/fibmap.c @@ -0,0 +1,118 @@ +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct file_ext { + __u32 f_pos; + __u32 start_blk; + __u32 end_blk; + __u32 blk_count; +}; + +void print_ext(struct file_ext *ext) +{ + if (ext->end_blk == 0) + printf("%8d %8d %8d %8d\n", ext->f_pos, 0, 0, ext->blk_count); + else + printf("%8d %8d %8d %8d\n", ext->f_pos, ext->start_blk, + ext->end_blk, ext->blk_count); +} + +void print_stat(struct stat64 *st) +{ + printf("--------------------------------------------\n"); + printf("dev [%d:%d]\n", major(st->st_dev), minor(st->st_dev)); + printf("ino [0x%8lx : %ld]\n", st->st_ino, st->st_ino); + printf("mode [0x%8x : %d]\n", st->st_mode, st->st_mode); + printf("nlink [0x%8lx : %ld]\n", st->st_nlink, st->st_nlink); + printf("uid [0x%8x : %d]\n", st->st_uid, st->st_uid); + printf("gid [0x%8x : %d]\n", st->st_gid, st->st_gid); + printf("size [0x%8lx : %ld]\n", st->st_size, st->st_size); + printf("blksize [0x%8lx : %ld]\n", st->st_blksize, st->st_blksize); + printf("blocks [0x%8lx : %ld]\n", st->st_blocks, st->st_blocks); + printf("--------------------------------------------\n\n"); +} + +int main(int argc, char *argv[]) +{ + int fd; + int ret = 0; + char *filename; + struct stat64 st; + int total_blks; + unsigned int i; + struct file_ext ext; + __u32 blknum; + + if (argc != 2) { + fprintf(stderr, "No filename\n"); + exit(-1); + } + filename = argv[1]; + + fd = open(filename, O_RDONLY|O_LARGEFILE); + if (fd < 0) { + ret = errno; + perror(filename); + exit(-1); + } + + fsync(fd); + + if (fstat64(fd, &st) < 0) { + ret = errno; + perror(filename); + goto out; + } + + total_blks = (st.st_size + st.st_blksize - 1) / st.st_blksize; + + printf("\n%s :\n", filename); + print_stat(&st); + printf("file_pos start_blk end_blk blks\n"); + + blknum = 0; + if (ioctl(fd, FIBMAP, &blknum) < 0) { + ret = errno; + perror("ioctl(FIBMAP)"); + goto out; + } + ext.f_pos = 0; + ext.start_blk = blknum; + ext.end_blk = blknum; + ext.blk_count = 1; + + for (i = 1; i < total_blks; i++) { + blknum = i; + + if (ioctl(fd, FIBMAP, &blknum) < 0) { + ret = errno; + perror("ioctl(FIBMAP)"); + goto out; + } + + if ((blknum == 0 && blknum == ext.end_blk) || (ext.end_blk + 1) == blknum) { + ext.end_blk = blknum; + ext.blk_count++; + } else { + print_ext(&ext); + ext.f_pos = i * st.st_blksize; + ext.start_blk = blknum; + ext.end_blk = blknum; + ext.blk_count = 1; + } + } + + print_ext(&ext); +out: + close(fd); + return ret; +} -- cgit v1.2.3 From b611e1155a67be8220ceefc36d8ab5abae926d19 Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Thu, 16 Jan 2014 12:01:27 +0900 Subject: fibmap.f2fs: add bdev information This patch shows devname and start_lba based on zero sector. fibmap reports related lba, sometimes we want to know absolute lba of file to compare with blktrace. Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- tools/fibmap.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tools/fibmap.c b/tools/fibmap.c index 9eb6b90..ed0a08e 100644 --- a/tools/fibmap.c +++ b/tools/fibmap.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -41,6 +43,42 @@ void print_stat(struct stat64 *st) printf("--------------------------------------------\n\n"); } +void stat_bdev(struct stat64 *st, unsigned int *start_lba) +{ + struct stat bdev_stat; + struct hd_geometry geom; + char devname[32] = { 0, }; + char linkname[32] = { 0, }; + int fd; + + sprintf(devname, "/dev/block/%d:%d", major(st->st_dev), minor(st->st_dev)); + + fd = open(devname, O_RDONLY); + if (fd < 0) + return; + + if (fstat(fd, &bdev_stat) < 0) + goto out; + + if (S_ISBLK(bdev_stat.st_mode)) { + if (ioctl(fd, HDIO_GETGEO, &geom) < 0) + *start_lba = 0; + else + *start_lba = geom.start; + } + + if (readlink(devname, linkname, sizeof(linkname)) < 0) + goto out; + + printf("----------------bdev info-------------------\n"); + printf("devname = %s\n", basename(linkname)); + printf("start_lba = %u\n", *start_lba); + +out: + close(fd); + +} + int main(int argc, char *argv[]) { int fd; @@ -50,6 +88,7 @@ int main(int argc, char *argv[]) int total_blks; unsigned int i; struct file_ext ext; + __u32 start_lba; __u32 blknum; if (argc != 2) { @@ -73,9 +112,12 @@ int main(int argc, char *argv[]) goto out; } + stat_bdev(&st, &start_lba); + total_blks = (st.st_size + st.st_blksize - 1) / st.st_blksize; - printf("\n%s :\n", filename); + printf("\n----------------file info-------------------\n"); + printf("%s :\n", filename); print_stat(&st); printf("file_pos start_blk end_blk blks\n"); -- cgit v1.2.3 From 4f267323a28c3fb50fa08256517e2dae4e347b2d Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 20 Jan 2014 17:42:21 +0900 Subject: f2fs-tools: resolve build warnings Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 14 +------------- mkfs/f2fs_format.c | 4 ++-- mkfs/f2fs_format_utils.c | 1 + 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 81223c7..512a6f4 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -10,17 +10,6 @@ */ #include "fsck.h" -#define S_SHIFT 12 -static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = { - [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE, - [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR, - [S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV, - [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV, - [S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO, - [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK, - [S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK, -}; - char *tree_mark; int tree_mark_size = 256; @@ -392,7 +381,7 @@ check: le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, le32_to_cpu(node_blk->i.i_current_depth), child_files); if (ftype == F2FS_FT_ORPHAN) - DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %d\n\n", + DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %lu\n\n", le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, i_blocks); if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || @@ -659,7 +648,6 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) { - struct f2fs_fsck *fsck = F2FS_FSCK(sbi); int ret = 0; u32 blk_cnt = 0; diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 5580e60..8297ce8 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -627,7 +627,7 @@ static int f2fs_write_check_point_pack(void) sum->n_sits = cpu_to_le16(6); sum->sit_j.entries[0].segno = ckp->cur_node_segno[0]; sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1); - f2fs_set_bit(0, sum->sit_j.entries[0].se.valid_map); + f2fs_set_bit(0, (char *)sum->sit_j.entries[0].se.valid_map); sum->sit_j.entries[1].segno = ckp->cur_node_segno[1]; sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10)); sum->sit_j.entries[2].segno = ckp->cur_node_segno[2]; @@ -636,7 +636,7 @@ static int f2fs_write_check_point_pack(void) /* data sit for root */ sum->sit_j.entries[3].segno = ckp->cur_data_segno[0]; sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1); - f2fs_set_bit(0, sum->sit_j.entries[3].se.valid_map); + f2fs_set_bit(0, (char *)sum->sit_j.entries[3].se.valid_map); sum->sit_j.entries[4].segno = ckp->cur_data_segno[1]; sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10)); sum->sit_j.entries[5].segno = ckp->cur_data_segno[2]; diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c index 4a43405..3f9cdfa 100644 --- a/mkfs/f2fs_format_utils.c +++ b/mkfs/f2fs_format_utils.c @@ -12,6 +12,7 @@ #include #include +#include #include #include -- cgit v1.2.3 From 0255d52ebf3ce596804d6a631c61e6039b2bf271 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 28 Jan 2014 19:23:57 +0900 Subject: mkfs: fix the wrong nat bitmap size We should consider checksum bytes in the checkpoint block. Previously, this bug incured very critical panics for node entry handling. Signed-off-by: Jaegeuk Kim --- mkfs/f2fs_format.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 8297ce8..1be1552 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -299,7 +299,7 @@ static int f2fs_prepare_super_block(void) */ sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) << log_blks_per_seg) / 8; - max_nat_bitmap_size = 4096 - sizeof(struct f2fs_checkpoint) + 1 - + max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - sit_bitmap_size; max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg; -- cgit v1.2.3 From 28d45d09cd138420449d63c479755339a7b33050 Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Wed, 29 Jan 2014 13:36:54 +0900 Subject: f2fstat: add option to select partition to see status If there are some partitions, this may select a partition to see its status. If no selection, you will see first section of status. e.g.) f2fstat -p /dev/sda3 Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- tools/f2fstat.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tools/f2fstat.c b/tools/f2fstat.c index e26e174..b4f22ae 100644 --- a/tools/f2fstat.c +++ b/tools/f2fstat.c @@ -3,6 +3,7 @@ #include #include #include +#include #ifdef DEBUG #define dbg(fmt, args...) printf(fmt, __VA_ARGS__); @@ -47,6 +48,7 @@ unsigned long lfs_blks; struct options { int delay; int interval; + char partname[32]; }; struct mm_table { @@ -69,7 +71,7 @@ again: } } -void f2fstat(void) +void f2fstat(struct options *opt) { int fd; int ret; @@ -79,6 +81,7 @@ void f2fstat(void) struct mm_table *found; int f2fstat_table_cnt; char *head, *tail; + int found_cnt = 0; static struct mm_table f2fstat_table[] = { { " - Data", &used_data_blks }, @@ -114,6 +117,13 @@ void f2fstat(void) buf[ret] = '\0'; head = buf; + + if (opt->partname[0] != '\0') { + head = strstr(buf, opt->partname); + if (head == NULL) + exit(EXIT_FAILURE); + } + for (;;) { remove_newline(&head); tail = strchr(head, ':'); @@ -137,6 +147,8 @@ void f2fstat(void) goto nextline; *(found->val) = strtoul(head, &tail, 10); + if (++found_cnt == f2fstat_table_cnt) + break; nextline: tail = strchr(head, '\n'); if (!tail) @@ -151,14 +163,15 @@ void usage(void) { printf("Usage: f2fstat [option]\n" " -d delay (secs)\n" - " -i interval of head info\n"); + " -i interval of head info\n" + " -p partition name (e.g. /dev/sda3)\n"); exit(EXIT_FAILURE); } void parse_option(int argc, char *argv[], struct options *opt) { char option; - const char *option_string = "d:i:h"; + const char *option_string = "d:i:p:h"; while ((option = getopt(argc, argv, option_string)) != EOF) { switch (option) { @@ -168,6 +181,9 @@ void parse_option(int argc, char *argv[], struct options *opt) case 'i': opt->interval = atoi(optarg); break; + case 'p': + strcpy(opt->partname, basename(optarg)); + break; default: usage(); break; @@ -188,6 +204,7 @@ int main(int argc, char *argv[]) struct options opt = { .delay = 1, .interval = 20, + .partname = { 0, }, }; parse_option(argc, argv, &opt); @@ -200,7 +217,7 @@ int main(int argc, char *argv[]) head_interval = opt.interval; } - f2fstat(); + f2fstat(&opt); printf(format, util, used_node_blks, used_data_blks, free_segs, valid_segs, dirty_segs, prefree_segs, -- cgit v1.2.3 From 858c4039c85f7c00c57925902985701b1e083555 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 6 Feb 2014 01:09:36 +0900 Subject: mkfs, fsck: change the results for readability This patch cleans up several printing formats. Signed-off-by: Jaegeuk Kim --- fsck/dump.c | 42 +++++++++++++++++++++++++++--------------- fsck/fsck.c | 4 ++-- fsck/mount.c | 2 +- include/f2fs_fs.h | 2 +- mkfs/f2fs_format.c | 3 +-- 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index 1b19bbc..765e9db 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -70,22 +70,28 @@ void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa) fd = open("dump_ssa", O_CREAT|O_WRONLY|O_TRUNC, 0666); ASSERT(fd >= 0); + snprintf(buf, BUF_SZ, "Note: dump.f2fs -b blkaddr = 0x%x + segno * " + " 0x200 + offset\n", + sbi->sm_info->main_blkaddr); + ret = write(fd, buf, strlen(buf)); + ASSERT(ret >= 0); + for (segno = start_ssa; segno < end_ssa; segno++) { ret = get_sum_block(sbi, segno, &sum_blk); memset(buf, 0, BUF_SZ); switch (ret) { case SEG_TYPE_CUR_NODE: - snprintf(buf, BUF_SZ, "\n\nsegno: %d, Current Node\n", segno); + snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Node\n", segno); break; case SEG_TYPE_CUR_DATA: - snprintf(buf, BUF_SZ, "\n\nsegno: %d, Current Data\n", segno); + snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Data\n", segno); break; case SEG_TYPE_NODE: - snprintf(buf, BUF_SZ, "\n\nsegno: %d, Node\n", segno); + snprintf(buf, BUF_SZ, "\n\nsegno: %x, Node\n", segno); break; case SEG_TYPE_DATA: - snprintf(buf, BUF_SZ, "\n\nsegno: %d, Data\n", segno); + snprintf(buf, BUF_SZ, "\n\nsegno: %x, Data\n", segno); break; } ret = write(fd, buf, strlen(buf)); @@ -98,10 +104,8 @@ void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa) ret = write(fd, buf, strlen(buf)); ASSERT(ret >= 0); } - snprintf(buf, BUF_SZ, " [%8x, %3d, %3x]", - le32_to_cpu(sum_blk.entries[i].nid), - le16_to_cpu(sum_blk.entries[i].ofs_in_node), - sum_blk.entries[i].version); + snprintf(buf, BUF_SZ, "[%3d: %6x]", i, + le32_to_cpu(sum_blk.entries[i].nid)); ret = write(fd, buf, strlen(buf)); ASSERT(ret >= 0); } @@ -147,28 +151,36 @@ int dump_node(struct f2fs_sb_info *sbi, nid_t nid) int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) { nid_t ino, nid; - int ret; + int type, ret; struct f2fs_summary sum_entry; struct node_info ni; struct f2fs_node *node_blk; - ret = get_sum_entry(sbi, blk_addr, &sum_entry); + type = get_sum_entry(sbi, blk_addr, &sum_entry); nid = le32_to_cpu(sum_entry.nid); - DBG(1, "Node ID [0x%x]\n", nid); - DBG(1, "Segment Type [%s]\n", seg_type_name[ret]); - DBG(1, "version [%d]\n", sum_entry.version); - DBG(1, "ofs_in_node [%d]\n", sum_entry.ofs_in_node); ret = get_node_info(sbi, nid, &ni); ASSERT(ret >= 0); + DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n"); + DBG(1, "Block_addr [0x%x]\n", blk_addr); + DBG(1, " - Segno [0x%x]\n", GET_SEGNO(sbi, blk_addr)); + DBG(1, " - Offset [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr)); + DBG(1, "SUM.nid [0x%x]\n", nid); + DBG(1, "SUM.type [%s]\n", seg_type_name[type]); + DBG(1, "SUM.version [%d]\n", sum_entry.version); + DBG(1, "SUM.ofs_in_node [%d]\n", sum_entry.ofs_in_node); + DBG(1, "NAT.blkaddr [0x%x]\n", ni.blk_addr); + DBG(1, "NAT.ino [0x%x]\n", ni.ino); + node_blk = calloc(BLOCK_SZ, 1); read_node_blk: - dev_read_block(node_blk, ni.blk_addr); + dev_read_block(node_blk, blk_addr); ino = le32_to_cpu(node_blk->footer.ino); nid = le32_to_cpu(node_blk->footer.nid); + if (ino == nid) { print_node_info(node_blk); } else { diff --git a/fsck/fsck.c b/fsck/fsck.c index 512a6f4..ba29ab7 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -104,7 +104,7 @@ static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, u32 blk_addr if (le32_to_cpu(sum_entry.nid) != nid) { DBG(0, "nid [0x%x]\n", nid); DBG(0, "target blk_addr [0x%x]\n", blk_addr); - DBG(0, "summary blk_addr [0x%lx]\n", + DBG(0, "summary blk_addr [0x%x]\n", GET_SUM_BLKADDR(sbi, GET_SEGNO(sbi, blk_addr))); DBG(0, "seg no / offset [0x%x / 0x%x]\n", GET_SEGNO(sbi, blk_addr), OFFSET_IN_SEG(sbi, blk_addr)); @@ -667,7 +667,7 @@ int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { nid_t ino = le32_to_cpu(orphan_blk->ino[j]); - DBG(1, "[%3ld] ino [0x%x]\n", i, ino); + DBG(1, "[%3d] ino [0x%x]\n", i, ino); blk_cnt = 1; ret = fsck_chk_node_blk(sbi, NULL, diff --git a/fsck/mount.c b/fsck/mount.c index 7ab53b8..e2f3ace 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -738,7 +738,7 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summ ssa_blk = GET_SUM_BLKADDR(sbi, segno); for (type = 0; type < NR_CURSEG_NODE_TYPE; type++) { if (segno == ckpt->cur_node_segno[type]) { - curseg = CURSEG_I(sbi, type); + curseg = CURSEG_I(sbi, CURSEG_HOT_NODE + type); memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ); return SEG_TYPE_CUR_NODE; /* current node seg was not stored */ } diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index bf3049d..969e216 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -25,7 +25,7 @@ typedef u_int64_t u64; typedef u_int32_t u32; typedef u_int16_t u16; typedef u_int8_t u8; -typedef u64 block_t; +typedef u32 block_t; typedef u32 nid_t; typedef u8 bool; typedef unsigned long pgoff_t; diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 1be1552..d330c86 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -570,8 +570,7 @@ static int f2fs_write_check_point_pack(void) ckp->cp_pack_start_sum = cpu_to_le32(1); ckp->valid_node_count = cpu_to_le32(1); ckp->valid_inode_count = cpu_to_le32(1); - ckp->next_free_nid = cpu_to_le32( - le32_to_cpu(super_block.root_ino) + 1); + ckp->next_free_nid = cpu_to_le32(0xc00000); ckp->sit_ver_bitmap_bytesize = cpu_to_le32( ((le32_to_cpu(super_block.segment_count_sit) / 2) << -- cgit v1.2.3 From 4ff7400c519a8f644b8181756939fcb313345c12 Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Thu, 6 Feb 2014 16:37:53 +0900 Subject: f2fstat: add memory information used by f2fs This patch adds memory information used by f2fs. Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- tools/f2fstat.c | 69 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/tools/f2fstat.c b/tools/f2fstat.c index b4f22ae..8ece660 100644 --- a/tools/f2fstat.c +++ b/tools/f2fstat.c @@ -16,6 +16,9 @@ */ #define F2FS_STATUS "/sys/kernel/debug/f2fs/status" +#define KEY_NODE 0x00000001 +#define KEY_META 0x00000010 + unsigned long util; unsigned long used_node_blks; unsigned long used_data_blks; @@ -33,9 +36,9 @@ unsigned long gc_node_blks; //unsigned long extent_hit_ratio; -unsigned long dirty_node; +unsigned long dirty_node, node_kb; unsigned long dirty_dents; -unsigned long dirty_meta; +unsigned long dirty_meta, meta_kb; unsigned long nat_caches; unsigned long dirty_sit; @@ -43,7 +46,7 @@ unsigned long free_nids; unsigned long ssr_blks; unsigned long lfs_blks; - +unsigned long memory_kb; struct options { int delay; @@ -54,6 +57,7 @@ struct options { struct mm_table { const char *name; unsigned long *val; + int flag; }; static int compare_mm_table(const void *a, const void *b) @@ -84,21 +88,22 @@ void f2fstat(struct options *opt) int found_cnt = 0; static struct mm_table f2fstat_table[] = { - { " - Data", &used_data_blks }, - { " - Dirty", &dirty_segs }, - { " - Free", &free_segs }, - { " - NATs", &nat_caches }, - { " - Node", &used_node_blks }, - { " - Prefree", &prefree_segs }, - { " - SITs", &dirty_sit }, - { " - Valid", &valid_segs }, - { " - dents", &dirty_dents }, - { " - meta", &dirty_meta }, - { " - nodes", &dirty_node }, - { "GC calls", &gc }, - { "LFS", &lfs_blks }, - { "SSR", &ssr_blks }, - { "Utilization", &util }, + { " - Data", &used_data_blks, 0 }, + { " - Dirty", &dirty_segs, 0 }, + { " - Free", &free_segs, 0 }, + { " - NATs", &nat_caches, 0 }, + { " - Node", &used_node_blks, 0 }, + { " - Prefree", &prefree_segs, 0 }, + { " - SITs", &dirty_sit, 0 }, + { " - Valid", &valid_segs, 0 }, + { " - dents", &dirty_dents, 0 }, + { " - meta", &dirty_meta, KEY_META }, + { " - nodes", &dirty_node, KEY_NODE }, + { "GC calls", &gc, 0 }, + { "LFS", &lfs_blks, 0 }, + { "Memory", &memory_kb, 0 }, + { "SSR", &ssr_blks, 0 }, + { "Utilization", &util, 0 }, }; f2fstat_table_cnt = sizeof(f2fstat_table)/sizeof(struct mm_table); @@ -147,6 +152,20 @@ void f2fstat(struct options *opt) goto nextline; *(found->val) = strtoul(head, &tail, 10); + if (found->flag) { + int npages; + tail = strstr(head, "in"); + head = tail + 2; + npages = strtoul(head, &tail, 10); + switch (found->flag & (KEY_NODE | KEY_META)) { + case KEY_NODE: + node_kb = npages * 4; + break; + case KEY_META: + meta_kb = npages * 4; + break; + } + } if (++found_cnt == f2fstat_table_cnt) break; nextline: @@ -193,13 +212,13 @@ void parse_option(int argc, char *argv[], struct options *opt) void print_head(void) { - printf("---utilization--- -----------main area-------- ---balancing async-- -gc- ---alloc---\n"); - printf("util node data free valid dirty prefree node dent meta sit gc ssr lfs\n"); + fprintf(stderr, "---utilization--- -----------main area-------- ---balancing async-- -gc- ---alloc--- -----memory-----\n"); + fprintf(stderr, "util node data free valid dirty prefree node dent meta sit gc ssr lfs total node meta\n"); } int main(int argc, char *argv[]) { - char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %3ld %5ld %6ld %6ld\n"; + char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %3ld %5ld %6ld %6ld %6ld %6ld %6ld\n"; int head_interval; struct options opt = { .delay = 1, @@ -219,10 +238,10 @@ int main(int argc, char *argv[]) f2fstat(&opt); - printf(format, util, used_node_blks, used_data_blks, - free_segs, valid_segs, dirty_segs, prefree_segs, - dirty_node, dirty_dents, dirty_meta, dirty_sit, - gc, ssr_blks, lfs_blks); + fprintf(stderr, format, util, used_node_blks, used_data_blks, + free_segs, valid_segs, dirty_segs, prefree_segs, + dirty_node, dirty_dents, dirty_meta, dirty_sit, + gc, ssr_blks, lfs_blks, memory_kb, node_kb, meta_kb); sleep(opt.delay); } -- cgit v1.2.3 From b7906af37f1de9d4dfc47c55fa4578d204f5ea3f Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Thu, 13 Feb 2014 15:13:22 +0900 Subject: f2fstat: show cp count calling f2fs This patch is to inform how many checkpoint is called. Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- tools/f2fstat.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/f2fstat.c b/tools/f2fstat.c index 8ece660..73ad457 100644 --- a/tools/f2fstat.c +++ b/tools/f2fstat.c @@ -29,8 +29,8 @@ unsigned long valid_segs; unsigned long dirty_segs; unsigned long prefree_segs; -unsigned long gc; -unsigned long bg_gc; +unsigned long gc, bg_gc; +unsigned long cp; unsigned long gc_data_blks; unsigned long gc_node_blks; @@ -99,6 +99,7 @@ void f2fstat(struct options *opt) { " - dents", &dirty_dents, 0 }, { " - meta", &dirty_meta, KEY_META }, { " - nodes", &dirty_node, KEY_NODE }, + { "CP calls", &cp, 0 }, { "GC calls", &gc, 0 }, { "LFS", &lfs_blks, 0 }, { "Memory", &memory_kb, 0 }, @@ -213,12 +214,12 @@ void parse_option(int argc, char *argv[], struct options *opt) void print_head(void) { fprintf(stderr, "---utilization--- -----------main area-------- ---balancing async-- -gc- ---alloc--- -----memory-----\n"); - fprintf(stderr, "util node data free valid dirty prefree node dent meta sit gc ssr lfs total node meta\n"); + fprintf(stderr, "util node data free valid dirty prefree node dent meta sit cp gc ssr lfs total node meta\n"); } int main(int argc, char *argv[]) { - char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %3ld %5ld %6ld %6ld %6ld %6ld %6ld\n"; + char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %3ld %3ld %5ld %6ld %6ld %6ld %6ld %6ld\n"; int head_interval; struct options opt = { .delay = 1, @@ -241,7 +242,7 @@ int main(int argc, char *argv[]) fprintf(stderr, format, util, used_node_blks, used_data_blks, free_segs, valid_segs, dirty_segs, prefree_segs, dirty_node, dirty_dents, dirty_meta, dirty_sit, - gc, ssr_blks, lfs_blks, memory_kb, node_kb, meta_kb); + cp, gc, ssr_blks, lfs_blks, memory_kb, node_kb, meta_kb); sleep(opt.delay); } -- cgit v1.2.3 From c15df2285d1e6b7cee8bd9fd23007ab23db16d82 Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Thu, 13 Feb 2014 15:13:23 +0900 Subject: f2fstat: add nat caches and free nids This patch shows nat caches and free nids using f2fs. Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- tools/f2fstat.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/f2fstat.c b/tools/f2fstat.c index 73ad457..c9c1d30 100644 --- a/tools/f2fstat.c +++ b/tools/f2fstat.c @@ -97,6 +97,7 @@ void f2fstat(struct options *opt) { " - SITs", &dirty_sit, 0 }, { " - Valid", &valid_segs, 0 }, { " - dents", &dirty_dents, 0 }, + { " - free_nids", &free_nids, 0 }, { " - meta", &dirty_meta, KEY_META }, { " - nodes", &dirty_node, KEY_NODE }, { "CP calls", &cp, 0 }, @@ -213,13 +214,13 @@ void parse_option(int argc, char *argv[], struct options *opt) void print_head(void) { - fprintf(stderr, "---utilization--- -----------main area-------- ---balancing async-- -gc- ---alloc--- -----memory-----\n"); - fprintf(stderr, "util node data free valid dirty prefree node dent meta sit cp gc ssr lfs total node meta\n"); + fprintf(stderr, "---utilization--- -----------main area-------- ---------balancing async------- ---gc--- ---alloc--- -----memory-----\n"); + fprintf(stderr, "util node data free valid dirty prefree node dent meta sit nat fnid cp gc ssr lfs total node meta\n"); } int main(int argc, char *argv[]) { - char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %3ld %3ld %5ld %6ld %6ld %6ld %6ld %6ld\n"; + char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %5ld %5ld %3ld %3ld %3ld %6ld %6ld %6ld %6ld %6ld\n"; int head_interval; struct options opt = { .delay = 1, @@ -241,7 +242,7 @@ int main(int argc, char *argv[]) fprintf(stderr, format, util, used_node_blks, used_data_blks, free_segs, valid_segs, dirty_segs, prefree_segs, - dirty_node, dirty_dents, dirty_meta, dirty_sit, + dirty_node, dirty_dents, dirty_meta, dirty_sit, nat_caches, free_nids, cp, gc, ssr_blks, lfs_blks, memory_kb, node_kb, meta_kb); sleep(opt.delay); -- cgit v1.2.3 From 192d979c61719dd1a44eb845033e949dcabba3e7 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 25 Feb 2014 08:07:25 +0900 Subject: fsck: remove build warnings This patch casts some variable types to remove build warnings. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index ba29ab7..20582c9 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -381,9 +381,9 @@ check: le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, le32_to_cpu(node_blk->i.i_current_depth), child_files); if (ftype == F2FS_FT_ORPHAN) - DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %lu\n\n", + DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %u\n\n", le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, - i_blocks); + (u32)i_blocks); if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || (i_blocks != *blk_cnt)) { print_node_info(node_blk); @@ -793,9 +793,9 @@ int fsck_verify(struct f2fs_sb_info *sbi) printf("[FSCK] valid_block_count matching with CP "); if (sbi->total_valid_block_count == fsck->chk.valid_blk_cnt) { - printf(" [Ok..] [0x%lx]\n", fsck->chk.valid_blk_cnt); + printf(" [Ok..] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt); } else { - printf(" [Fail] [0x%lx]\n", fsck->chk.valid_blk_cnt); + printf(" [Fail] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt); ret = EXIT_ERR_CODE; } -- cgit v1.2.3 From 99250ec1aa15ea329fb090fd8f4c1e7e7b50bba3 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 27 Feb 2014 20:12:35 +0900 Subject: mkfs: support large directory This patch synchronizes mkfs with the latest f2fs configuration in which supports large directory by assigning dir_level. Signed-off-by: Jaegeuk Kim --- include/f2fs_fs.h | 4 +++- mkfs/f2fs_format.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 969e216..7210604 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -366,6 +366,8 @@ struct f2fs_extent { #define INLINE_DATA_OFFSET (PAGE_CACHE_SIZE - sizeof(struct node_footer) \ - sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1)) +#define DEF_DIR_LEVEL 0 + struct f2fs_inode { __le16 i_mode; /* file mode */ __u8 i_advise; /* file hints */ @@ -388,7 +390,7 @@ struct f2fs_inode { __le32 i_pino; /* parent inode number */ __le32 i_namelen; /* file name length */ __u8 i_name[F2FS_NAME_LEN]; /* file name for SPOR */ - __u8 i_reserved2; /* for backward compatibility */ + __u8 i_dir_level; /* dentry_level for large dir */ struct f2fs_extent i_ext; /* caching a largest extent */ diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index d330c86..9dbdc1d 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -774,6 +774,7 @@ static int f2fs_write_root_inode(void) raw_node->i.i_xattr_nid = 0; raw_node->i.i_flags = 0; raw_node->i.i_current_depth = cpu_to_le32(1); + raw_node->i.i_dir_level = DEF_DIR_LEVEL; data_blk_nor = le32_to_cpu(super_block.main_blkaddr) + config.cur_seg[CURSEG_HOT_DATA] * config.blks_per_seg; -- cgit v1.2.3 From 379ff8916e8b3fd19bca44265b70e50584be2c31 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Mon, 3 Mar 2014 09:20:58 +0000 Subject: fibmap.f2fs: compile fix for musl libc Include sys/types.h for major/minor macros. This fixes the following compile error with musl libc: fibmap.o: In function `print_stat': /home/ncopa/src/f2fs-tools/tools/fibmap.c:34: undefined reference to `minor' /home/ncopa/src/f2fs-tools/tools/fibmap.c:34: undefined reference to `major' fibmap.o: In function `stat_bdev': /home/ncopa/src/f2fs-tools/tools/fibmap.c:54: undefined reference to `minor' /home/ncopa/src/f2fs-tools/tools/fibmap.c:54: undefined reference to `major' collect2: error: ld returned 1 exit status Signed-off-by: Natanael Copa Signed-off-by: Jaegeuk Kim --- tools/fibmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/fibmap.c b/tools/fibmap.c index ed0a08e..a6a112b 100644 --- a/tools/fibmap.c +++ b/tools/fibmap.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 2f229b89a7756be7df9f36f232b7b0901c1c6e53 Mon Sep 17 00:00:00 2001 From: Dongho Sim Date: Wed, 26 Mar 2014 08:25:14 +0000 Subject: mkfs: fix wrong extension count fix an bug related to extension list. there was the potential bug in set_cold_files function, namei.c. Signed-off-by: Dongho Sim Signed-off-by: Jaegeuk Kim --- mkfs/f2fs_format.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 9dbdc1d..d485808 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -154,7 +154,7 @@ static void configure_extension_list(void) memcpy(super_block.extension_list[i++], *extlist, name_len); extlist++; } - super_block.extension_count = i - 1; + super_block.extension_count = i; if (!ext_str) return; @@ -165,11 +165,11 @@ static void configure_extension_list(void) name_len = strlen(ue); memcpy(super_block.extension_list[i++], ue, name_len); ue = strtok(NULL, ","); - if (i > F2FS_MAX_EXTENSION) + if (i >= F2FS_MAX_EXTENSION) break; } - super_block.extension_count = i - 1; + super_block.extension_count = i; free(config.extension_list); } -- cgit v1.2.3 From af3c6803bd3db784531ff5675c539eef4bae1a15 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Wed, 5 Feb 2014 19:53:19 -0800 Subject: split up mkfs format into main and just the format code. This will allow using the format code as a library. Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- mkfs/Makefile.am | 2 +- mkfs/f2fs_format.c | 105 +------------------------------------- mkfs/f2fs_format_main.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ mkfs/f2fs_format_utils.h | 5 +- 4 files changed, 135 insertions(+), 107 deletions(-) create mode 100644 mkfs/f2fs_format_main.c diff --git a/mkfs/Makefile.am b/mkfs/Makefile.am index 79cbec2..68cab66 100644 --- a/mkfs/Makefile.am +++ b/mkfs/Makefile.am @@ -3,5 +3,5 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include AM_CFLAGS = -Wall sbin_PROGRAMS = mkfs.f2fs -mkfs_f2fs_SOURCES = f2fs_format.c f2fs_format_utils.c +mkfs_f2fs_SOURCES = f2fs_format_main.c f2fs_format.c f2fs_format_utils.c mkfs_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index d485808..a46e60e 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -27,86 +27,6 @@ extern struct f2fs_configuration config; struct f2fs_super_block super_block; -static void mkfs_usage() -{ - MSG(0, "\nUsage: mkfs.f2fs [options] device\n"); - MSG(0, "[options]:\n"); - MSG(0, " -a heap-based allocation [default:1]\n"); - MSG(0, " -d debug level [default:0]\n"); - MSG(0, " -e [extension list] e.g. \"mp3,gif,mov\"\n"); - MSG(0, " -l label\n"); - MSG(0, " -o overprovision ratio [default:5]\n"); - MSG(0, " -s # of segments per section [default:1]\n"); - MSG(0, " -z # of sections per zone [default:1]\n"); - MSG(0, " -t 0: nodiscard, 1: discard [default:1]\n"); - exit(1); -} - -static void f2fs_parse_options(int argc, char *argv[]) -{ - static const char *option_string = "a:d:e:l:o:s:z:t:"; - int32_t option=0; - - while ((option = getopt(argc,argv,option_string)) != EOF) { - switch (option) { - case 'a': - config.heap = atoi(optarg); - if (config.heap == 0) - MSG(0, "Info: Disable heap-based policy\n"); - break; - case 'd': - config.dbg_lv = atoi(optarg); - MSG(0, "Info: Debug level = %d\n", config.dbg_lv); - break; - case 'e': - config.extension_list = strdup(optarg); - MSG(0, "Info: Add new extension list\n"); - break; - case 'l': /*v: volume label */ - if (strlen(optarg) > 512) { - MSG(0, "Error: Volume Label should be less than\ - 512 characters\n"); - mkfs_usage(); - } - config.vol_label = optarg; - MSG(0, "Info: Label = %s\n", config.vol_label); - break; - case 'o': - config.overprovision = atoi(optarg); - MSG(0, "Info: Overprovision ratio = %u%%\n", - atoi(optarg)); - break; - case 's': - config.segs_per_sec = atoi(optarg); - MSG(0, "Info: Segments per section = %d\n", - atoi(optarg)); - break; - case 'z': - config.secs_per_zone = atoi(optarg); - MSG(0, "Info: Sections per zone = %d\n", atoi(optarg)); - break; - case 't': - config.trim = atoi(optarg); - MSG(0, "Info: Trim is %s\n", config.trim ? "enabled": "disabled"); - break; - default: - MSG(0, "\tError: Unknown option %c\n",option); - mkfs_usage(); - break; - } - } - - if ((optind + 1) != argc) { - MSG(0, "\tError: Device not specified\n"); - mkfs_usage(); - } - - config.reserved_segments = - (2 * (100 / config.overprovision + 1) + 6) - * config.segs_per_sec; - config.device_name = argv[optind]; -} - const char *media_ext_lists[] = { "jpg", "gif", @@ -916,7 +836,7 @@ exit: return err; } -static int f2fs_format_device(void) +int f2fs_format_device(void) { int err = 0; @@ -969,26 +889,3 @@ exit: return err; } - -int main(int argc, char *argv[]) -{ - MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n", - F2FS_TOOLS_VERSION, - F2FS_TOOLS_DATE); - f2fs_init_configuration(&config); - - f2fs_parse_options(argc, argv); - - if (f2fs_dev_is_umounted(&config) < 0) - return -1; - - if (f2fs_get_device_info(&config) < 0) - return -1; - - if (f2fs_format_device() < 0) - return -1; - - MSG(0, "Info: format successful\n"); - - return 0; -} diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c new file mode 100644 index 0000000..f266ba6 --- /dev/null +++ b/mkfs/f2fs_format_main.c @@ -0,0 +1,130 @@ +/** + * f2fs_format.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define _LARGEFILE64_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs_fs.h" +#include "f2fs_format_utils.h" + +extern struct f2fs_configuration config; + +static void mkfs_usage() +{ + MSG(0, "\nUsage: mkfs.f2fs [options] device\n"); + MSG(0, "[options]:\n"); + MSG(0, " -a heap-based allocation [default:1]\n"); + MSG(0, " -d debug level [default:0]\n"); + MSG(0, " -e [extension list] e.g. \"mp3,gif,mov\"\n"); + MSG(0, " -l label\n"); + MSG(0, " -o overprovision ratio [default:5]\n"); + MSG(0, " -s # of segments per section [default:1]\n"); + MSG(0, " -z # of sections per zone [default:1]\n"); + MSG(0, " -t 0: nodiscard, 1: discard [default:1]\n"); + exit(1); +} + +static void f2fs_parse_options(int argc, char *argv[]) +{ + static const char *option_string = "a:d:e:l:o:s:z:t:"; + int32_t option=0; + + while ((option = getopt(argc,argv,option_string)) != EOF) { + switch (option) { + case 'a': + config.heap = atoi(optarg); + if (config.heap == 0) + MSG(0, "Info: Disable heap-based policy\n"); + break; + case 'd': + config.dbg_lv = atoi(optarg); + MSG(0, "Info: Debug level = %d\n", config.dbg_lv); + break; + case 'e': + config.extension_list = strdup(optarg); + MSG(0, "Info: Add new extension list\n"); + break; + case 'l': /*v: volume label */ + if (strlen(optarg) > 512) { + MSG(0, "Error: Volume Label should be less than\ + 512 characters\n"); + mkfs_usage(); + } + config.vol_label = optarg; + MSG(0, "Info: Label = %s\n", config.vol_label); + break; + case 'o': + config.overprovision = atoi(optarg); + MSG(0, "Info: Overprovision ratio = %u%%\n", + atoi(optarg)); + break; + case 's': + config.segs_per_sec = atoi(optarg); + MSG(0, "Info: Segments per section = %d\n", + atoi(optarg)); + break; + case 'z': + config.secs_per_zone = atoi(optarg); + MSG(0, "Info: Sections per zone = %d\n", atoi(optarg)); + break; + case 't': + config.trim = atoi(optarg); + MSG(0, "Info: Trim is %s\n", config.trim ? "enabled": "disabled"); + break; + default: + MSG(0, "\tError: Unknown option %c\n",option); + mkfs_usage(); + break; + } + } + + if ((optind + 1) != argc) { + MSG(0, "\tError: Device not specified\n"); + mkfs_usage(); + } + + config.reserved_segments = + (2 * (100 / config.overprovision + 1) + 6) + * config.segs_per_sec; + config.device_name = argv[optind]; +} + +int main(int argc, char *argv[]) +{ + MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n", + F2FS_TOOLS_VERSION, + F2FS_TOOLS_DATE); + f2fs_init_configuration(&config); + + f2fs_parse_options(argc, argv); + + if (f2fs_dev_is_umounted(&config) < 0) + return -1; + + if (f2fs_get_device_info(&config) < 0) + return -1; + + if (f2fs_format_device() < 0) + return -1; + + MSG(0, "Info: format successful\n"); + + return 0; +} diff --git a/mkfs/f2fs_format_utils.h b/mkfs/f2fs_format_utils.h index 745be64..31100d5 100644 --- a/mkfs/f2fs_format_utils.h +++ b/mkfs/f2fs_format_utils.h @@ -14,5 +14,6 @@ extern struct f2fs_configuration config; -void f2fs_finalize_device(); -int f2fs_trim_device(); +void f2fs_finalize_device(void); +int f2fs_trim_device(void); +int f2fs_format_device(void); -- cgit v1.2.3 From 15ea79b3ae7f0474ade43ba8b6eb328806e01e15 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Wed, 5 Feb 2014 19:54:12 -0800 Subject: further split up lib2fs so that it does not do any IO directly. This will allow turning mkfs into a libarary more easily. Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- lib/Makefile.am | 2 +- lib/libf2fs.c | 32 ------------------------------ lib/libf2fs_io.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 33 deletions(-) create mode 100644 lib/libf2fs_io.c diff --git a/lib/Makefile.am b/lib/Makefile.am index 6498df9..a6b304c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2,6 +2,6 @@ lib_LTLIBRARIES = libf2fs.la -libf2fs_la_SOURCES = libf2fs.c +libf2fs_la_SOURCES = libf2fs.c libf2fs_io.c libf2fs_la_CFLAGS = -Wall libf2fs_la_CPPFLAGS = -I$(top_srcdir)/include diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 3984697..5fd17fb 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -26,8 +26,6 @@ #include -struct f2fs_configuration config; - void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf) { u_int8_t *pchTempPtr = in_buf; @@ -491,33 +489,3 @@ int f2fs_get_device_info(struct f2fs_configuration *c) return 0; } -/* - * IO interfaces - */ -int dev_read(void *buf, __u64 offset, size_t len) -{ - if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0) - return -1; - if (read(config.fd, buf, len) < 0) - return -1; - return 0; -} - -int dev_write(void *buf, __u64 offset, size_t len) -{ - if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0) - return -1; - if (write(config.fd, buf, len) < 0) - return -1; - return 0; -} - -int dev_read_block(void *buf, __u64 blk_addr) -{ - return dev_read(buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE); -} - -int dev_read_blocks(void *buf, __u64 addr, __u32 nr_blks) -{ - return dev_read(buf, addr * F2FS_BLKSIZE, nr_blks * F2FS_BLKSIZE); -} diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c new file mode 100644 index 0000000..e48dd1a --- /dev/null +++ b/lib/libf2fs_io.c @@ -0,0 +1,60 @@ +/** + * libf2fs.c + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define _LARGEFILE64_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct f2fs_configuration config; + +/* + * IO interfaces + */ +int dev_read(void *buf, __u64 offset, size_t len) +{ + if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0) + return -1; + if (read(config.fd, buf, len) < 0) + return -1; + return 0; +} + +int dev_write(void *buf, __u64 offset, size_t len) +{ + if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0) + return -1; + if (write(config.fd, buf, len) < 0) + return -1; + return 0; +} + +int dev_read_block(void *buf, __u64 blk_addr) +{ + return dev_read(buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE); +} + +int dev_read_blocks(void *buf, __u64 addr, __u32 nr_blks) +{ + return dev_read(buf, addr * F2FS_BLKSIZE, nr_blks * F2FS_BLKSIZE); +} -- cgit v1.2.3 From a35529fce0c5171562ec0ebebcc6120d1604924b Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Mon, 31 Mar 2014 15:33:01 -0700 Subject: format: add support for dev_fill() and extra dev_*() debugging. Support an fs_io dev_fill(). This helps with devices that actually already return 0 on uninitialized data. It also helps with in memory devices using sparse libs: don't allocate a block of 0s. Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- include/f2fs_fs.h | 2 ++ lib/libf2fs_io.c | 12 ++++++++++++ mkfs/f2fs_format.c | 21 +++++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 7210604..095d755 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -665,6 +665,8 @@ extern int f2fs_get_device_info(struct f2fs_configuration *); extern int dev_read(void *, __u64, size_t); extern int dev_write(void *, __u64, size_t); +/* All bytes in the buffer must be 0 use dev_fill(). */ +extern int dev_fill(void *, __u64, size_t); extern int dev_read_block(void *, __u64); extern int dev_read_blocks(void *, __u64, __u32 ); diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index e48dd1a..5f0a547 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -49,6 +49,18 @@ int dev_write(void *buf, __u64 offset, size_t len) return 0; } +int dev_fill(void *buf, __u64 offset, size_t len) +{ + /* Only allow fill to zero */ + if (*((__u8*)buf)) + return -1; + if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0) + return -1; + if (write(config.fd, buf, len) < 0) + return -1; + return 0; +} + int dev_read_block(void *buf, __u64 blk_addr) { return dev_read(buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE); diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index a46e60e..31b4422 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -376,10 +376,11 @@ static int f2fs_init_sit_area(void) sit_seg_addr = le32_to_cpu(super_block.sit_blkaddr); sit_seg_addr *= blk_size; + DBG(1, "\tFilling sit area at offset 0x%08"PRIx64"\n", sit_seg_addr); for (index = 0; index < (le32_to_cpu(super_block.segment_count_sit) / 2); index++) { - if (dev_write(zero_buf, sit_seg_addr, seg_size)) { + if (dev_fill(zero_buf, sit_seg_addr, seg_size)) { MSG(1, "\tError: While zeroing out the sit area \ on disk!!!\n"); return -1; @@ -411,10 +412,11 @@ static int f2fs_init_nat_area(void) nat_seg_addr = le32_to_cpu(super_block.nat_blkaddr); nat_seg_addr *= blk_size; + DBG(1, "\tFilling nat area at offset 0x%08"PRIx64"\n", nat_seg_addr); for (index = 0; index < (le32_to_cpu(super_block.segment_count_nat) / 2); index++) { - if (dev_write(nat_buf, nat_seg_addr, seg_size)) { + if (dev_fill(nat_buf, nat_seg_addr, seg_size)) { MSG(1, "\tError: While zeroing out the nat area \ on disk!!!\n"); return -1; @@ -510,6 +512,7 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset = le32_to_cpu(super_block.segment0_blkaddr); cp_seg_blk_offset *= blk_size_bytes; + DBG(1, "\tWriting main segments, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; @@ -523,6 +526,7 @@ static int f2fs_write_check_point_pack(void) sum->entries[0].ofs_in_node = 0; cp_seg_blk_offset += blk_size_bytes; + DBG(1, "\tWriting segment summary for data, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; @@ -533,6 +537,7 @@ static int f2fs_write_check_point_pack(void) SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); cp_seg_blk_offset += blk_size_bytes; + DBG(1, "\tWriting segment summary, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; @@ -562,6 +567,7 @@ static int f2fs_write_check_point_pack(void) sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10)); cp_seg_blk_offset += blk_size_bytes; + DBG(1, "\tWriting data sit for root, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; @@ -575,6 +581,7 @@ static int f2fs_write_check_point_pack(void) sum->entries[0].ofs_in_node = 0; cp_seg_blk_offset += blk_size_bytes; + DBG(1, "\tWriting Segment summary for node blocks, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; @@ -585,6 +592,7 @@ static int f2fs_write_check_point_pack(void) SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); cp_seg_blk_offset += blk_size_bytes; + DBG(1, "\tWriting Segment summary for data block (1/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; @@ -594,6 +602,7 @@ static int f2fs_write_check_point_pack(void) memset(sum, 0, sizeof(struct f2fs_summary_block)); SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); cp_seg_blk_offset += blk_size_bytes; + DBG(1, "\tWriting Segment summary for data block (2/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; @@ -601,6 +610,7 @@ static int f2fs_write_check_point_pack(void) /* 8. cp page2 */ cp_seg_blk_offset += blk_size_bytes; + DBG(1, "\tWriting cp page2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; @@ -617,6 +627,7 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset = (le32_to_cpu(super_block.segment0_blkaddr) + config.blks_per_seg) * blk_size_bytes; + DBG(1, "\tWriting cp page 1 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; @@ -624,6 +635,7 @@ static int f2fs_write_check_point_pack(void) /* 10. cp page 2 of check point pack 2 */ cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count) - 1); + DBG(1, "\tWriting cp page 2 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; @@ -643,6 +655,7 @@ static int f2fs_write_super_block(void) memcpy(zero_buff + F2FS_SUPER_OFFSET, &super_block, sizeof(super_block)); + DBG(1, "\tWriting super block, at offset 0x%08x\n", 0); for (index = 0; index < 2; index++) { if (dev_write(zero_buff, index * F2FS_BLKSIZE, F2FS_BLKSIZE)) { MSG(1, "\tError: While while writing supe_blk \ @@ -709,6 +722,7 @@ static int f2fs_write_root_inode(void) config.blks_per_seg; main_area_node_seg_blk_offset *= blk_size_bytes; + DBG(1, "\tWriting root inode (hot node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset); if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the raw_node to disk!!!\n"); return -1; @@ -722,6 +736,7 @@ static int f2fs_write_root_inode(void) config.blks_per_seg; main_area_node_seg_blk_offset *= blk_size_bytes; + DBG(1, "\tWriting root inode (warm node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset); if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the raw_node to disk!!!\n"); return -1; @@ -759,6 +774,7 @@ static int f2fs_update_nat_root(void) nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr); nat_seg_blk_offset *= blk_size_bytes; + DBG(1, "\tWriting nat root, at offset 0x%08"PRIx64"\n", nat_seg_blk_offset); if (dev_write(nat_blk, nat_seg_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the nat_blk set0 to disk!\n"); return -1; @@ -799,6 +815,7 @@ static int f2fs_add_default_dentry_root(void) config.blks_per_seg; data_blk_offset *= blk_size_bytes; + DBG(1, "\tWriting default dentry root, at offset 0x%08"PRIx64"\n", data_blk_offset); if (dev_write(dent_blk, data_blk_offset, F2FS_BLKSIZE)) { MSG(1, "\tError: While writing the dentry_blk to disk!!!\n"); return -1; -- cgit v1.2.3 From e35b8afb34822ccc0835b453c7a3417bc0825569 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 7 Apr 2014 12:10:59 +0900 Subject: f2fs-tools: announce dual licenses with GPL and LGPL v2 This patch announces LGPL v2 for the following files. - include/f2fs_fs.h - lib/libf2fs.c - lib/libf2fs_io.c - mkfs/f2fs_format.c - mkfs/f2fs_format_main.c - mkfs/f2fs_format_utils.c - mkfs/f2fs_format_utils.h Signed-off-by: Jaegeuk Kim --- COPYING | 492 +++++++++++++++++++++++++++++++++++++++++++++++ include/f2fs_fs.h | 4 +- lib/libf2fs.c | 4 +- lib/libf2fs_io.c | 4 +- mkfs/f2fs_format.c | 4 +- mkfs/f2fs_format_main.c | 4 +- mkfs/f2fs_format_utils.c | 4 +- mkfs/f2fs_format_utils.h | 4 +- 8 files changed, 499 insertions(+), 21 deletions(-) diff --git a/COPYING b/COPYING index 21cd6db..88dc016 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,15 @@ The tools for F2FS are covered by GNU Public License version 2. +Exceptionally, the following files are also covered by the GNU Library General +Public License Version 2 as the dual licenses. +- include/f2fs_fs.h +- lib/libf2fs.c +- lib/libf2fs_io.c +- mkfs/f2fs_format.c +- mkfs/f2fs_format_main.c +- mkfs/f2fs_format_utils.c +- mkfs/f2fs_format_utils.h +================================================================================ Copyright (c) 2012 Samsung Electronics Co., Ltd. http://www.samsung.com/ @@ -348,4 +358,486 @@ proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. + ================================================================================ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 095d755..94d8dc3 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -4,9 +4,7 @@ * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Dual licensed under the GPL or LGPL version 2 licenses. */ #ifndef __F2FS_FS_H__ #define __F2FS_FS_H__ diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 5fd17fb..fb3f8c1 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -4,9 +4,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Dual licensed under the GPL or LGPL version 2 licenses. */ #define _LARGEFILE64_SOURCE diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index 5f0a547..b726bae 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -4,9 +4,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Dual licensed under the GPL or LGPL version 2 licenses. */ #define _LARGEFILE64_SOURCE diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 31b4422..cdbf74a 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -4,9 +4,7 @@ * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Dual licensed under the GPL or LGPL version 2 licenses. */ #define _LARGEFILE64_SOURCE diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c index f266ba6..8350182 100644 --- a/mkfs/f2fs_format_main.c +++ b/mkfs/f2fs_format_main.c @@ -4,9 +4,7 @@ * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Dual licensed under the GPL or LGPL version 2 licenses. */ #define _LARGEFILE64_SOURCE diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c index 3f9cdfa..bd10968 100644 --- a/mkfs/f2fs_format_utils.c +++ b/mkfs/f2fs_format_utils.c @@ -4,9 +4,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Dual licensed under the GPL or LGPL version 2 licenses. */ #define _LARGEFILE64_SOURCE diff --git a/mkfs/f2fs_format_utils.h b/mkfs/f2fs_format_utils.h index 31100d5..fb731fc 100644 --- a/mkfs/f2fs_format_utils.h +++ b/mkfs/f2fs_format_utils.h @@ -4,9 +4,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Dual licensed under the GPL or LGPL version 2 licenses. */ #define _LARGEFILE64_SOURCE -- cgit v1.2.3 From a4499dbe939d3dfc373b824bd8741e8d323c79f6 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 9 May 2014 10:32:14 +0900 Subject: f2fs: fix to remove the test code that should not be merged Signed-off-by: Jaegeuk Kim --- mkfs/f2fs_format.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index cdbf74a..cef484a 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -490,8 +490,8 @@ static int f2fs_write_check_point_pack(void) ckp->cp_pack_start_sum = cpu_to_le32(1); ckp->valid_node_count = cpu_to_le32(1); ckp->valid_inode_count = cpu_to_le32(1); - ckp->next_free_nid = cpu_to_le32(0xc00000); - + ckp->next_free_nid = cpu_to_le32( + le32_to_cpu(super_block.root_ino) + 1); ckp->sit_ver_bitmap_bytesize = cpu_to_le32( ((le32_to_cpu(super_block.segment_count_sit) / 2) << le32_to_cpu(super_block.log_blocks_per_seg)) / 8); -- cgit v1.2.3 From a68ee58a5d1485be637bcc4e4fbddc5da727fc62 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Tue, 13 May 2014 17:02:55 -0700 Subject: Cleanup various build warnings (signed vs unsigned, unused vars,...) * removed unused includes. * removed unused parameters. * Fixed a bunch of warnings around: int i; if (i < some_uint) ... and u32 x; ... if (x < 0) return error; * Protect BLKDISCARD usage if it is not available. Change-Id: Iede035b1beb2df01c961589a69aff47a5258ecd2 Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 17 ++++------------- fsck/fsck.h | 6 +----- fsck/main.c | 2 +- fsck/mount.c | 24 +++++++++++++----------- include/f2fs_fs.h | 2 -- include/list.h | 6 ++++-- lib/libf2fs.c | 3 +-- lib/libf2fs_io.c | 1 - mkfs/f2fs_format.c | 20 -------------------- mkfs/f2fs_format_main.c | 2 +- mkfs/f2fs_format_utils.c | 3 ++- tools/fibmap.c | 2 +- 12 files changed, 28 insertions(+), 60 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 20582c9..6e04ffa 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -11,7 +11,7 @@ #include "fsck.h" char *tree_mark; -int tree_mark_size = 256; +uint32_t tree_mark_size = 256; static int add_into_hard_link_list(struct f2fs_sb_info *sbi, u32 nid, u32 link_cnt) { @@ -238,7 +238,6 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, case TYPE_INDIRECT_NODE: ret = fsck_chk_idnode_blk(sbi, inode, - nid, ftype, node_blk, blk_cnt); @@ -246,7 +245,6 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, case TYPE_DOUBLE_INDIRECT_NODE: ret = fsck_chk_didnode_blk(sbi, inode, - nid, ftype, node_blk, blk_cnt); @@ -273,7 +271,7 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, enum NODE_TYPE ntype; u32 i_links = le32_to_cpu(node_blk->i.i_links); u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks); - int idx = 0; + unsigned int idx = 0; int ret = 0; ASSERT(node_blk->footer.nid == node_blk->footer.ino); @@ -340,7 +338,6 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) { *blk_cnt = *blk_cnt + 1; ret = fsck_chk_data_blk(sbi, - &node_blk->i, le32_to_cpu(node_blk->i.i_addr[idx]), &child_cnt, &child_files, @@ -414,7 +411,6 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, continue; *blk_cnt = *blk_cnt + 1; fsck_chk_data_blk(sbi, - inode, le32_to_cpu(node_blk->dn.addr[idx]), &child_cnt, &child_files, @@ -430,7 +426,6 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, - u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt) @@ -454,7 +449,6 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, - u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt) @@ -482,7 +476,7 @@ static void print_dentry(__u32 depth, __u8 *name, int last_de = 0; int next_idx = 0; int name_len; - int i; + unsigned int i; int bit_offset; if (config.dbg_lv != -1) @@ -516,7 +510,6 @@ static void print_dentry(__u32 depth, __u8 *name, } int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, u32 blk_addr, u32 *child_cnt, u32 *child_files, @@ -600,7 +593,6 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, } int fsck_chk_data_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, u32 blk_addr, u32 *child_cnt, u32 *child_files, @@ -636,7 +628,6 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, if (ftype == F2FS_FT_DIR) { fsck_chk_dentry_blk(sbi, - inode, blk_addr, child_cnt, child_files, @@ -743,7 +734,7 @@ int fsck_init(struct f2fs_sb_info *sbi) int fsck_verify(struct f2fs_sb_info *sbi) { - int i = 0; + unsigned int i = 0; int ret = 0; u32 nr_unref_nid = 0; struct f2fs_fsck *fsck = F2FS_FSCK(sbi); diff --git a/fsck/fsck.h b/fsck/fsck.h index 8c98c93..e5a3841 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -103,20 +103,17 @@ extern int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, extern int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, - u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt); extern int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, - u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt); extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, u32 blk_addr, u32 *child_cnt, u32 *child_files, @@ -127,7 +124,6 @@ extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u8 ver); extern int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, u32 blk_addr, u32 *child_cnt, u32 *child_files, @@ -154,7 +150,7 @@ struct dump_option { int end_sit; int start_ssa; int end_ssa; - u32 blk_addr; + int32_t blk_addr; }; extern void sit_dump(struct f2fs_sb_info *sbi, int start_sit, int end_sit); diff --git a/fsck/main.c b/fsck/main.c index a0144fc..5aa3956 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -12,7 +12,7 @@ #include struct f2fs_fsck gfsck = { - .sbi.fsck = &gfsck, + .sbi = { .fsck = &gfsck, }, }; void fsck_usage() diff --git a/fsck/mount.c b/fsck/mount.c index e2f3ace..383a8ac 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -12,7 +12,7 @@ void print_inode_info(struct f2fs_inode *inode) { - int i = 0; + unsigned int i = 0; int namelen = le32_to_cpu(inode->i_namelen); DISP_u32(inode, i_mode); @@ -470,7 +470,7 @@ int build_sit_info(struct f2fs_sb_info *sbi) return 0; } -void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) +void reset_curseg(struct f2fs_sb_info *sbi, int type) { struct curseg_info *curseg = CURSEG_I(sbi, type); @@ -509,7 +509,7 @@ int read_compacted_summaries(struct f2fs_sb_info *sbi) segno = le32_to_cpu(ckpt->cur_data_segno[i]); blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]); curseg->next_segno = segno; - reset_curseg(sbi, i, 0); + reset_curseg(sbi, i); curseg->alloc_type = ckpt->alloc_type[i]; curseg->next_blkoff = blk_off; @@ -540,7 +540,7 @@ int restore_node_summary(struct f2fs_sb_info *sbi, struct f2fs_summary *sum_entry; void *page; block_t addr; - int i; + unsigned int i; page = malloc(PAGE_SIZE); if (!page) @@ -602,7 +602,7 @@ int read_normal_summaries(struct f2fs_sb_info *sbi, int type) if (IS_NODESEG(type)) { if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) { struct f2fs_summary *sum_entry = &sum_blk->entries[0]; - int i; + unsigned int i; for (i = 0; i < sbi->blocks_per_seg; i++, sum_entry++) { /* do not change original value */ #if 0 @@ -621,7 +621,7 @@ int read_normal_summaries(struct f2fs_sb_info *sbi, int type) curseg = CURSEG_I(sbi, type); memcpy(curseg->sum_blk, sum_blk, PAGE_CACHE_SIZE); curseg->next_segno = segno; - reset_curseg(sbi, type, 0); + reset_curseg(sbi, type); curseg->alloc_type = ckpt->alloc_type[type]; curseg->next_blkoff = blk_off; free(sum_blk); @@ -690,12 +690,12 @@ struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, unsigned i } void check_block_count(struct f2fs_sb_info *sbi, - int segno, struct f2fs_sit_entry *raw_sit) + unsigned int segno, struct f2fs_sit_entry *raw_sit) { struct f2fs_sm_info *sm_info = SM_I(sbi); unsigned int end_segno = sm_info->segment_count - 1; int valid_blocks = 0; - int i; + unsigned int i; /* check segment usage */ ASSERT(GET_SIT_VBLOCKS(raw_sit) <= sbi->blocks_per_seg); @@ -896,7 +896,8 @@ int build_sit_area_bitmap(struct f2fs_sb_info *sbi) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct f2fs_sm_info *sm_i = SM_I(sbi); - int segno = 0, j = 0; + unsigned int segno = 0; + int j = 0; char *ptr = NULL; u32 sum_vblocks = 0; @@ -977,7 +978,8 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) pgoff_t block_off; pgoff_t block_addr; int seg_off; - int ret, i; + int ret; + unsigned int i; nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); @@ -1097,7 +1099,7 @@ void f2fs_do_umount(struct f2fs_sb_info *sbi) struct sit_info *sit_i = SIT_I(sbi); struct f2fs_sm_info *sm_i = SM_I(sbi); struct f2fs_nm_info *nm_i = NM_I(sbi); - int i; + unsigned int i; /* free nm_info */ free(nm_i->nat_bitmap); diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 94d8dc3..bfca1a4 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -12,8 +12,6 @@ #include #include #include -#include -#include #ifdef HAVE_CONFIG_H #include diff --git a/include/list.h b/include/list.h index b1b1ca3..571cd5c 100644 --- a/include/list.h +++ b/include/list.h @@ -1,9 +1,11 @@ #define POISON_POINTER_DELTA 0 -#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) -#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA) +#define LIST_POISON1 ((void *) (0x00100100 + POISON_POINTER_DELTA)) +#define LIST_POISON2 ((void *) (0x00200200 + POISON_POINTER_DELTA)) +#if !defined(offsetof) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) diff --git a/lib/libf2fs.c b/lib/libf2fs.c index fb3f8c1..c1e0b0e 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -20,7 +20,6 @@ #include #include #include -#include #include @@ -428,7 +427,7 @@ int f2fs_dev_is_umounted(struct f2fs_configuration *c) int f2fs_get_device_info(struct f2fs_configuration *c) { int32_t fd = 0; - int32_t sector_size; + uint32_t sector_size; struct stat stat_buf; struct hd_geometry geom; diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index b726bae..508ccce 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -20,7 +20,6 @@ #include #include #include -#include #include diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index cef484a..c7c6971 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include "f2fs_fs.h" @@ -115,30 +114,11 @@ static int f2fs_prepare_super_block(void) log_blks_per_seg = log_base_2(config.blks_per_seg); super_block.log_sectorsize = cpu_to_le32(log_sectorsize); - - if (log_sectorsize < 0) { - MSG(1, "\tError: Failed to get the sector size: %u!\n", - config.sector_size); - return -1; - } - super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block); - if (log_sectors_per_block < 0) { - MSG(1, "\tError: Failed to get sectors per block: %u!\n", - config.sectors_per_blk); - return -1; - } - super_block.log_blocksize = cpu_to_le32(log_blocksize); super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg); - if (log_blks_per_seg < 0) { - MSG(1, "\tError: Failed to get block per segment: %u!\n", - config.blks_per_seg); - return -1; - } - super_block.segs_per_sec = cpu_to_le32(config.segs_per_sec); super_block.secs_per_zone = cpu_to_le32(config.secs_per_zone); blk_size_bytes = 1 << log_blocksize; diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c index 8350182..cee640a 100644 --- a/mkfs/f2fs_format_main.c +++ b/mkfs/f2fs_format_main.c @@ -16,7 +16,7 @@ #include #include #include -#include +//#include #include #include "f2fs_fs.h" diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c index bd10968..f4c3767 100644 --- a/mkfs/f2fs_format_utils.c +++ b/mkfs/f2fs_format_utils.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "f2fs_fs.h" @@ -46,6 +45,7 @@ int f2fs_trim_device() return -1; } +#if defined(BLKDISCARD) MSG(0, "Info: Discarding device\n"); if (S_ISREG(stat_buf.st_mode)) return 0; @@ -54,6 +54,7 @@ int f2fs_trim_device() MSG(0, "Info: This device doesn't support TRIM\n"); } else return -1; +#endif return 0; } diff --git a/tools/fibmap.c b/tools/fibmap.c index a6a112b..c672808 100644 --- a/tools/fibmap.c +++ b/tools/fibmap.c @@ -11,7 +11,7 @@ #include #include #include -#include +// #include struct file_ext { __u32 f_pos; -- cgit v1.2.3 From 03ca33c40720a122e956989bd95f1229881dacae Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 21 May 2014 12:05:31 +0900 Subject: fibmap: need linux/fs.h for FIBMAP Signed-off-by: Jaegeuk Kim --- tools/fibmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/fibmap.c b/tools/fibmap.c index c672808..a6a112b 100644 --- a/tools/fibmap.c +++ b/tools/fibmap.c @@ -11,7 +11,7 @@ #include #include #include -// #include +#include struct file_ext { __u32 f_pos; -- cgit v1.2.3 From 4ea4f1db27c0d0d3e40f561191b4ceeecb80ab1a Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Mon, 12 May 2014 22:03:46 +0900 Subject: fsck.f2fs: large volume support This patch support large volume over about 3TB. Signed-off-by: Changman Lee [Jaegeuk Kim: add missing cp_payload in f2fs_super_block] Signed-off-by: Jaegeuk Kim --- fsck/f2fs.h | 14 +++++++++++--- fsck/fsck.c | 7 +++++-- fsck/mount.c | 22 ++++++++++++++++++++-- include/f2fs_fs.h | 1 + lib/libf2fs.c | 4 ++-- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index e1740fe..427a733 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -203,9 +203,17 @@ 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) ? - le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0; - return &ckpt->sit_nat_version_bitmap + offset; + int offset; + if (le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload) > 0) { + if (flag == NAT_BITMAP) + return &ckpt->sit_nat_version_bitmap; + else + return ((char *)ckpt + F2FS_BLKSIZE); + } else { + offset = (flag == NAT_BITMAP) ? + le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0; + return &ckpt->sit_nat_version_bitmap + offset; + } } static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) diff --git a/fsck/fsck.c b/fsck/fsck.c index 6e04ffa..0f48918 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -644,11 +644,14 @@ int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) block_t start_blk, orphan_blkaddr, i, j; struct f2fs_orphan_block *orphan_blk; + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); - if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG)) + if (!is_set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG)) return 0; - start_blk = __start_cp_addr(sbi) + 1; + start_blk = __start_cp_addr(sbi) + 1 + + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); + orphan_blkaddr = __start_sum_addr(sbi) - 1; orphan_blk = calloc(BLOCK_SZ, 1); diff --git a/fsck/mount.c b/fsck/mount.c index 383a8ac..5d3231f 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -129,6 +129,7 @@ void print_raw_sb_info(struct f2fs_sb_info *sbi) DISP_u32(sb, root_ino); DISP_u32(sb, node_ino); DISP_u32(sb, meta_ino); + DISP_u32(sb, cp_payload); printf("\n"); } @@ -285,6 +286,7 @@ void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, unsigned lo /* Read the 2nd cp block in this CP pack */ cp_page_2 = malloc(PAGE_SIZE); cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1; + if (dev_read_block(cp_page_2, cp_addr) < 0) goto invalid_cp2; @@ -295,7 +297,7 @@ void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, unsigned lo crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset); if (f2fs_crc_valid(crc, cp_block, crc_offset)) - goto invalid_cp1; + goto invalid_cp2; cur_version = le64_to_cpu(cp_block->checkpoint_ver); @@ -319,8 +321,9 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) unsigned long blk_size = sbi->blocksize; unsigned long long cp1_version = 0, cp2_version = 0; unsigned long long cp_start_blk_no; + unsigned int cp_blks = 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); - sbi->ckpt = malloc(blk_size); + sbi->ckpt = malloc(cp_blks * blk_size); if (!sbi->ckpt) return -ENOMEM; /* @@ -351,6 +354,20 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) memcpy(sbi->ckpt, cur_page, blk_size); + if (cp_blks > 1) { + int i; + unsigned long long cp_blk_no; + + cp_blk_no = le32_to_cpu(raw_sb->cp_blkaddr); + if (cur_page == cp2) + cp_blk_no += 1 << le32_to_cpu(raw_sb->log_blocks_per_seg); + /* copy sit bitmap */ + for (i = 1; i < cp_blks; i++) { + unsigned char *ckpt = (unsigned char *)sbi->ckpt; + dev_read_block(cur_page, cp_blk_no + i); + memcpy(ckpt + i * blk_size, cur_page, blk_size); + } + } free(cp1); free(cp2); return 0; @@ -697,6 +714,7 @@ void check_block_count(struct f2fs_sb_info *sbi, int valid_blocks = 0; unsigned int i; + /* check segment usage */ ASSERT(GET_SIT_VBLOCKS(raw_sit) <= sbi->blocks_per_seg); diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index bfca1a4..4f44866 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -277,6 +277,7 @@ struct f2fs_super_block { __le16 volume_name[512]; /* volume name */ __le32 extension_count; /* # of extensions below */ __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */ + __le32 cp_payload; } __attribute__((packed)); /* diff --git a/lib/libf2fs.c b/lib/libf2fs.c index c1e0b0e..358bfb8 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -341,8 +341,8 @@ int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len) cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len); if (cal_crc != blk_crc) { - DBG(0,"CRC validation failed: cal_crc = %u \ - blk_crc = %u buff_size = 0x%x", + DBG(0,"CRC validation failed: cal_crc = %u, " + "blk_crc = %u buff_size = 0x%x\n", cal_crc, blk_crc, len); return -1; } -- cgit v1.2.3 From 97fd9037ec0d56945e4fa89366ea19d1c9694c50 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Wed, 11 Jun 2014 21:56:56 -0700 Subject: License tweak: LGPL v2.1 vs LGPL v2 The important part is b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. Change-Id: Ic1a02ec5cfcb2bedda3d53f3061037e1e7437221 Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- COPYING | 215 +++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 118 insertions(+), 97 deletions(-) diff --git a/COPYING b/COPYING index 88dc016..52f956d 100644 --- a/COPYING +++ b/COPYING @@ -1,6 +1,6 @@ The tools for F2FS are covered by GNU Public License version 2. -Exceptionally, the following files are also covered by the GNU Library General -Public License Version 2 as the dual licenses. +Exceptionally, the following files are also covered by the GNU Lesser General +Public License Version 2.1 as the dual licenses. - include/f2fs_fs.h - lib/libf2fs.c - lib/libf2fs_io.c @@ -360,115 +360,128 @@ library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================================================ - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 - Copyright (C) 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -[This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. - This license, the Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the library, or if you modify it. +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source -code. If you link a program with the library, you must provide -complete object files to the recipients so that they can relink them -with the library, after making changes to the library and recompiling +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The -former contains code derived from the library, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. - GNU LIBRARY GENERAL PUBLIC LICENSE + GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -General Public License (also called "this License"). Each licensee is -addressed as "you". + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs @@ -617,7 +630,7 @@ distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. - 6. As an exception to the Sections above, you may also compile or + 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit @@ -644,23 +657,31 @@ of these things: Library will not necessarily be able to recompile the application to use the modified definitions.) - b) Accompany the work with a written offer, valid for at + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. - c) If distribution of the work is made by offering access to copy + d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. - d) Verify that the user has already received a copy of these + e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, -the source code distributed need not include anything that is normally -distributed (in either source or binary form) with the major +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. @@ -709,7 +730,7 @@ Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to +You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent @@ -752,7 +773,7 @@ excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new -versions of the Library General Public License from time to time. +versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. @@ -773,7 +794,7 @@ decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. @@ -796,7 +817,7 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries @@ -815,18 +836,18 @@ convey the exclusion of warranty; and each file should have at least the Copyright (C) This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public + modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. -- cgit v1.2.3 From 3ba4ce8950e1a53f760e8ed200ad2b7d13cfa585 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Wed, 11 Jun 2014 21:55:38 -0700 Subject: mkfs: support passing in the number of sectors to use Adds the optional sectors count: mkfs.f2fs [options] device [sectors] Change-Id: I3ac83121576574bda074140ffa60195a2bc9947b Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- lib/libf2fs.c | 7 +++++++ mkfs/f2fs_format_main.c | 13 ++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 358bfb8..6168c5c 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -354,6 +354,7 @@ int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len) */ void f2fs_init_configuration(struct f2fs_configuration *c) { + c->total_sectors = 0; c->sector_size = DEFAULT_SECTOR_SIZE; c->sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK; c->blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT; @@ -430,6 +431,7 @@ int f2fs_get_device_info(struct f2fs_configuration *c) uint32_t sector_size; struct stat stat_buf; struct hd_geometry geom; + u_int64_t wanted_total_sectors = c->total_sectors; fd = open(c->device_name, O_RDWR); if (fd < 0) { @@ -472,7 +474,12 @@ int f2fs_get_device_info(struct f2fs_configuration *c) MSG(0, "\tError: Volume type is not supported!!!\n"); return -1; } + if (wanted_total_sectors && wanted_total_sectors < c->total_sectors) { + MSG(0, "Info: total device sectors = %"PRIu64" (in 512bytes)\n", + c->total_sectors); + c->total_sectors = wanted_total_sectors; + } MSG(0, "Info: sector size = %u\n", c->sector_size); MSG(0, "Info: total sectors = %"PRIu64" (in 512bytes)\n", c->total_sectors); diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c index cee640a..2b6c195 100644 --- a/mkfs/f2fs_format_main.c +++ b/mkfs/f2fs_format_main.c @@ -26,7 +26,7 @@ extern struct f2fs_configuration config; static void mkfs_usage() { - MSG(0, "\nUsage: mkfs.f2fs [options] device\n"); + MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n"); MSG(0, "[options]:\n"); MSG(0, " -a heap-based allocation [default:1]\n"); MSG(0, " -d debug level [default:0]\n"); @@ -36,6 +36,7 @@ static void mkfs_usage() MSG(0, " -s # of segments per section [default:1]\n"); MSG(0, " -z # of sections per zone [default:1]\n"); MSG(0, " -t 0: nodiscard, 1: discard [default:1]\n"); + MSG(0, "sectors: number of sectors. [default: determined by device size]\n"); exit(1); } @@ -93,15 +94,21 @@ static void f2fs_parse_options(int argc, char *argv[]) } } - if ((optind + 1) != argc) { + if (optind >= argc) { MSG(0, "\tError: Device not specified\n"); mkfs_usage(); } + config.device_name = argv[optind]; + + if ((optind + 1) < argc) { + /* We have a sector count. */ + config.total_sectors = atoll(argv[optind+1]); + MSG(0, "\ttotal_sectors=%lu (%s bytes)\n", config.total_sectors, argv[optind+1]); + } config.reserved_segments = (2 * (100 / config.overprovision + 1) + 6) * config.segs_per_sec; - config.device_name = argv[optind]; } int main(int argc, char *argv[]) -- cgit v1.2.3 From 0575dd1c56ef731662687fa5b7817335b14c69ee Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 13 Jun 2014 16:51:32 +0900 Subject: libf2fs, fsck, mkfs: call f2fs_finalize_device before exit The fsck tool should call f2fs_finalize_device before exit to close the device file. Signed-off-by: Jaegeuk Kim --- fsck/main.c | 3 +++ include/f2fs_fs.h | 1 + lib/libf2fs.c | 12 ++++++++++++ mkfs/f2fs_format.c | 2 -- mkfs/f2fs_format_main.c | 2 ++ mkfs/f2fs_format_utils.c | 14 -------------- mkfs/f2fs_format_utils.h | 1 - 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/fsck/main.c b/fsck/main.c index 5aa3956..46f5d04 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -203,6 +203,9 @@ int main (int argc, char **argv) } f2fs_do_umount(sbi); + + f2fs_finalize_device(&config); + printf("\nDone.\n"); return ret; } diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 4f44866..53b8cb9 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -659,6 +659,7 @@ extern int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len); extern void f2fs_init_configuration(struct f2fs_configuration *); extern int f2fs_dev_is_umounted(struct f2fs_configuration *); extern int f2fs_get_device_info(struct f2fs_configuration *); +extern void f2fs_finalize_device(struct f2fs_configuration *); extern int dev_read(void *, __u64, size_t); extern int dev_write(void *, __u64, size_t); diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 6168c5c..8d6c670 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -493,3 +493,15 @@ int f2fs_get_device_info(struct f2fs_configuration *c) return 0; } +void f2fs_finalize_device(struct f2fs_configuration *c) +{ + /* + * We should call fsync() to flush out all the dirty pages + * in the block device page cache. + */ + if (fsync(c->fd) < 0) + MSG(0, "\tError: Could not conduct fsync!!!\n"); + + if (close(c->fd) < 0) + MSG(0, "\tError: Failed to close device file!!!\n"); +} diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index c7c6971..1568545 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -880,7 +880,5 @@ exit: if (err) MSG(0, "\tError: Could not format the device!!!\n"); - f2fs_finalize_device(); - return err; } diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c index 2b6c195..19c52e4 100644 --- a/mkfs/f2fs_format_main.c +++ b/mkfs/f2fs_format_main.c @@ -129,6 +129,8 @@ int main(int argc, char *argv[]) if (f2fs_format_device() < 0) return -1; + f2fs_finalize_device(&config); + MSG(0, "Info: format successful\n"); return 0; diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c index f4c3767..5cc2a32 100644 --- a/mkfs/f2fs_format_utils.c +++ b/mkfs/f2fs_format_utils.c @@ -15,20 +15,6 @@ #include "f2fs_fs.h" -void f2fs_finalize_device() -{ - /* - * We should call fsync() to flush out all the dirty pages - * in the block device page cache. - */ - if (fsync(config.fd) < 0) - MSG(0, "\tError: Could not conduct fsync!!!\n"); - - if (close(config.fd) < 0) - MSG(0, "\tError: Failed to close device file!!!\n"); - -} - int f2fs_trim_device() { unsigned long long range[2]; diff --git a/mkfs/f2fs_format_utils.h b/mkfs/f2fs_format_utils.h index fb731fc..9eb2cea 100644 --- a/mkfs/f2fs_format_utils.h +++ b/mkfs/f2fs_format_utils.h @@ -12,6 +12,5 @@ extern struct f2fs_configuration config; -void f2fs_finalize_device(void); int f2fs_trim_device(void); int f2fs_format_device(void); -- cgit v1.2.3 From 09f8f56066efd3a9fadb4c731f7184980383f9f9 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 13 Jun 2014 17:41:58 +0900 Subject: mkfs: set BLKDISCARD by default And let's show some debug info as well. Signed-off-by: Jaegeuk Kim --- mkfs/Makefile.am | 2 +- mkfs/f2fs_format_utils.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mkfs/Makefile.am b/mkfs/Makefile.am index 68cab66..ff136a7 100644 --- a/mkfs/Makefile.am +++ b/mkfs/Makefile.am @@ -1,7 +1,7 @@ ## Makefile.am AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include -AM_CFLAGS = -Wall +AM_CFLAGS = -Wall -DBLKDISCARD sbin_PROGRAMS = mkfs.f2fs mkfs_f2fs_SOURCES = f2fs_format_main.c f2fs_format.c f2fs_format_utils.c mkfs_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c index 5cc2a32..8f7e094 100644 --- a/mkfs/f2fs_format_utils.c +++ b/mkfs/f2fs_format_utils.c @@ -36,8 +36,12 @@ int f2fs_trim_device() if (S_ISREG(stat_buf.st_mode)) return 0; else if (S_ISBLK(stat_buf.st_mode)) { - if (ioctl(config.fd, BLKDISCARD, &range) < 0) + if (ioctl(config.fd, BLKDISCARD, &range) < 0) { MSG(0, "Info: This device doesn't support TRIM\n"); + } else { + MSG(0, "Info: Discarded %lu sectors\n", + config.total_sectors); + } } else return -1; #endif -- cgit v1.2.3 From e91da2f664a765a5bd2bde7d47efe7c8b957ebb9 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 13 Jun 2014 13:25:20 -0700 Subject: libf2fs: move the finalize_device() into the io lib. This is required so that libf2fs.c can be used against any kind of device (E.g. an in-memory sparse file) just by linking against something that provides the libf2fs_io.c functions. libf2fs is currently libf2fs.c + libf2fs_io.c Signed-off-by: JP Abgrall Signed-off-by: Jaegeuk Kim --- lib/libf2fs.c | 12 ------------ lib/libf2fs_io.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 8d6c670..6168c5c 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -493,15 +493,3 @@ int f2fs_get_device_info(struct f2fs_configuration *c) return 0; } -void f2fs_finalize_device(struct f2fs_configuration *c) -{ - /* - * We should call fsync() to flush out all the dirty pages - * in the block device page cache. - */ - if (fsync(c->fd) < 0) - MSG(0, "\tError: Could not conduct fsync!!!\n"); - - if (close(c->fd) < 0) - MSG(0, "\tError: Failed to close device file!!!\n"); -} diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index 508ccce..5d9b68d 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -67,3 +67,16 @@ int dev_read_blocks(void *buf, __u64 addr, __u32 nr_blks) { return dev_read(buf, addr * F2FS_BLKSIZE, nr_blks * F2FS_BLKSIZE); } + +void f2fs_finalize_device(struct f2fs_configuration *c) +{ + /* + * We should call fsync() to flush out all the dirty pages + * in the block device page cache. + */ + if (fsync(c->fd) < 0) + MSG(0, "\tError: Could not conduct fsync!!!\n"); + + if (close(c->fd) < 0) + MSG(0, "\tError: Failed to close device file!!!\n"); +} -- cgit v1.2.3 From 58edb106a8b47d2ed693ab41f63b314dc2882ecd Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Mon, 30 Jun 2014 13:57:17 -0700 Subject: f2fs-tools: 64-bit compile issue Signed-off-by: Mark Salyzyn Change-Id: I9398b877571d3dabbcb29c87a67d59672ea7fbaa Signed-off-by: Jaegeuk Kim --- fsck/dump.c | 4 +++- fsck/mount.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index 765e9db..880e78a 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -8,6 +8,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include + #include "fsck.h" #define BUF_SZ 80 @@ -57,7 +59,7 @@ void sit_dump(struct f2fs_sb_info *sbi, int start_sit, int end_sit) ASSERT(ret >= 0); close(fd); - DBG(1, "Blocks [0x%lx] Free Segs [0x%x]\n", valid_blocks, free_segs); + DBG(1, "Blocks [0x%" PRIx64 "] Free Segs [0x%x]\n", valid_blocks, free_segs); } void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa) diff --git a/fsck/mount.c b/fsck/mount.c index 5d3231f..7ea3296 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -355,7 +355,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) memcpy(sbi->ckpt, cur_page, blk_size); if (cp_blks > 1) { - int i; + unsigned int i; unsigned long long cp_blk_no; cp_blk_no = le32_to_cpu(raw_sb->cp_blkaddr); -- cgit v1.2.3 From 092e3d9da37796daf439e94141c57886d6fc6e50 Mon Sep 17 00:00:00 2001 From: Changman Lee Date: Thu, 10 Jul 2014 15:26:04 +0900 Subject: mkfs.f2fs: large volume support This patch supports large volume over about 3TB. Signed-off-by: Changman Lee Signed-off-by: Jaegeuk Kim --- include/f2fs_fs.h | 8 ++++++ mkfs/f2fs_format.c | 79 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 16 deletions(-) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 53b8cb9..80ce918 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -221,6 +221,7 @@ enum { #define F2FS_LOG_SECTORS_PER_BLOCK 3 /* 4KB: F2FS_BLKSIZE */ #define F2FS_BLKSIZE 4096 /* support only 4KB block */ #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ +#define F2FS_BLK_ALIGN(x) (((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE) #define NULL_ADDR 0x0U #define NEW_ADDR -1U @@ -455,6 +456,13 @@ struct f2fs_nat_block { #define SIT_VBLOCK_MAP_SIZE 64 #define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry)) +/* + * F2FS uses 4 bytes to represent block address. As a result, supported size of + * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments. + */ +#define F2FS_MAX_SEGMENT ((16 * 1024 * 1024) / 2) +#define MAX_SIT_BITMAP_SIZE ((F2FS_MAX_SEGMENT / SIT_ENTRY_PER_BLOCK) / 8) + /* * Note that f2fs_sit_entry->vblocks has the following bit-field information. * [15:10] : allocation type such as CURSEG_XXXX_TYPE diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 1568545..a62a8fe 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -101,7 +101,8 @@ static int f2fs_prepare_super_block(void) u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa; u_int32_t total_valid_blks_available; u_int64_t zone_align_start_offset, diff, total_meta_segments; - u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments; + u_int32_t sit_bitmap_size, max_sit_bitmap_size; + u_int32_t max_nat_bitmap_size, max_nat_segments; u_int32_t total_zones; super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC); @@ -197,8 +198,26 @@ static int f2fs_prepare_super_block(void) */ sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) << log_blks_per_seg) / 8; - max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - - sit_bitmap_size; + + if (sit_bitmap_size > MAX_SIT_BITMAP_SIZE) + max_sit_bitmap_size = MAX_SIT_BITMAP_SIZE; + else + max_sit_bitmap_size = sit_bitmap_size; + + /* + * It should be reserved minimum 1 segment for nat. + * When sit is too large, we should expand cp area. It requires more pages for cp. + */ + if (max_sit_bitmap_size > + (CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 65)) { + max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1; + super_block.cp_payload = F2FS_BLK_ALIGN(max_sit_bitmap_size); + } else { + max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 + - max_sit_bitmap_size; + super_block.cp_payload = 0; + } + max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg; if (le32_to_cpu(super_block.segment_count_nat) > max_nat_segments) @@ -414,6 +433,7 @@ static int f2fs_write_check_point_pack(void) u_int64_t cp_seg_blk_offset = 0; u_int32_t crc = 0; int i; + char *cp_payload = NULL; ckp = calloc(F2FS_BLKSIZE, 1); if (ckp == NULL) { @@ -427,6 +447,12 @@ static int f2fs_write_check_point_pack(void) return -1; } + cp_payload = calloc(F2FS_BLKSIZE, 1); + if (cp_payload == NULL) { + MSG(1, "\tError: Calloc Failed for cp_payload!!!\n"); + return -1; + } + /* 1. cp page 1 of checkpoint pack 1 */ ckp->checkpoint_ver = cpu_to_le64(1); ckp->cur_node_segno[0] = @@ -465,9 +491,10 @@ static int f2fs_write_check_point_pack(void) ((le32_to_cpu(ckp->free_segment_count) + 6 - le32_to_cpu(ckp->overprov_segment_count)) * config.blks_per_seg)); - ckp->cp_pack_total_block_count = cpu_to_le32(8); + ckp->cp_pack_total_block_count = + cpu_to_le32(8 + le32_to_cpu(super_block.cp_payload)); ckp->ckpt_flags = cpu_to_le32(CP_UMOUNT_FLAG); - ckp->cp_pack_start_sum = cpu_to_le32(1); + ckp->cp_pack_start_sum = cpu_to_le32(1 + le32_to_cpu(super_block.cp_payload)); ckp->valid_node_count = cpu_to_le32(1); ckp->valid_inode_count = cpu_to_le32(1); ckp->next_free_nid = cpu_to_le32( @@ -491,11 +518,20 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset *= blk_size_bytes; DBG(1, "\tWriting main segments, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; } + for (i = 0; i < le32_to_cpu(super_block.cp_payload); i++) { + cp_seg_blk_offset += blk_size_bytes; + if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) { + MSG(1, "\tError: While zeroing out the sit bitmap area \ + on disk!!!\n"); + return -1; + } + } + /* 2. Prepare and write Segment summary for data blocks */ memset(sum, 0, sizeof(struct f2fs_summary_block)); SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); @@ -505,7 +541,7 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset += blk_size_bytes; DBG(1, "\tWriting segment summary for data, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; } @@ -516,7 +552,7 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset += blk_size_bytes; DBG(1, "\tWriting segment summary, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; } @@ -546,7 +582,7 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset += blk_size_bytes; DBG(1, "\tWriting data sit for root, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; } @@ -560,7 +596,7 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset += blk_size_bytes; DBG(1, "\tWriting Segment summary for node blocks, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; } @@ -571,7 +607,7 @@ static int f2fs_write_check_point_pack(void) cp_seg_blk_offset += blk_size_bytes; DBG(1, "\tWriting Segment summary for data block (1/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; } @@ -581,7 +617,7 @@ static int f2fs_write_check_point_pack(void) SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); cp_seg_blk_offset += blk_size_bytes; DBG(1, "\tWriting Segment summary for data block (2/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); return -1; } @@ -589,7 +625,7 @@ static int f2fs_write_check_point_pack(void) /* 8. cp page2 */ cp_seg_blk_offset += blk_size_bytes; DBG(1, "\tWriting cp page2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; } @@ -606,21 +642,32 @@ static int f2fs_write_check_point_pack(void) config.blks_per_seg) * blk_size_bytes; DBG(1, "\tWriting cp page 1 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; } + for (i = 0; i < le32_to_cpu(super_block.cp_payload); i++) { + cp_seg_blk_offset += blk_size_bytes; + if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) { + MSG(1, "\tError: While zeroing out the sit bitmap area \ + on disk!!!\n"); + return -1; + } + } + /* 10. cp page 2 of check point pack 2 */ - cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count) - 1); + cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count) + - le32_to_cpu(super_block.cp_payload) - 1); DBG(1, "\tWriting cp page 2 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); - if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) { + if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { MSG(1, "\tError: While writing the ckp to disk!!!\n"); return -1; } free(sum) ; free(ckp) ; + free(cp_payload); return 0; } -- cgit v1.2.3 From 92a65a44e5637b1f86f5d6e10cb058b6aa21db41 Mon Sep 17 00:00:00 2001 From: Sankalp Bose Date: Wed, 23 Jul 2014 03:28:14 +0300 Subject: mkfs.f2fs: fix name conflict for BLKDISCARD The compile time option BLKDISCARD conflicts with ioctl code for discard. This causes discard to fail with "Info: This device doesn't support TRIM". Rename compile time option to WITH_BLKDISCARD. Signed-off-by: Sankalp Bose Signed-off-by: Jaegeuk Kim --- configure.ac | 2 +- mkfs/Makefile.am | 2 +- mkfs/f2fs_format_utils.c | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index c2dafb0..0111e72 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ AC_PATH_PROG([LDCONFIG], [ldconfig], PKG_CHECK_MODULES([libuuid], [uuid]) # Checks for header files. -AC_CHECK_HEADERS([fcntl.h mntent.h stdlib.h string.h \ +AC_CHECK_HEADERS([linux/fs.h fcntl.h mntent.h stdlib.h string.h \ sys/ioctl.h sys/mount.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. diff --git a/mkfs/Makefile.am b/mkfs/Makefile.am index ff136a7..fa48699 100644 --- a/mkfs/Makefile.am +++ b/mkfs/Makefile.am @@ -1,7 +1,7 @@ ## Makefile.am AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include -AM_CFLAGS = -Wall -DBLKDISCARD +AM_CFLAGS = -Wall -DWITH_BLKDISCARD sbin_PROGRAMS = mkfs.f2fs mkfs_f2fs_SOURCES = f2fs_format_main.c f2fs_format.c f2fs_format_utils.c mkfs_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c index 8f7e094..9892a8f 100644 --- a/mkfs/f2fs_format_utils.c +++ b/mkfs/f2fs_format_utils.c @@ -15,6 +15,10 @@ #include "f2fs_fs.h" +#ifdef HAVE_LINUX_FS_H +#include +#endif + int f2fs_trim_device() { unsigned long long range[2]; @@ -31,7 +35,7 @@ int f2fs_trim_device() return -1; } -#if defined(BLKDISCARD) +#if defined(WITH_BLKDISCARD) && defined(BLKDISCARD) MSG(0, "Info: Discarding device\n"); if (S_ISREG(stat_buf.st_mode)) return 0; -- cgit v1.2.3 From 4b80852d7662a2ab63b5c7e9870afe3db1b5facc Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 29 Jul 2014 16:24:11 -0700 Subject: tracepoint.sh: add missing tracepoints Signed-off-by: Jaegeuk Kim --- scripts/tracepoint.sh | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/scripts/tracepoint.sh b/scripts/tracepoint.sh index b0d2fcb..7f5a9b8 100755 --- a/scripts/tracepoint.sh +++ b/scripts/tracepoint.sh @@ -1,13 +1,13 @@ -#!/bin/bash +#!/system/bin/sh TRACE=/sys/kernel/debug/tracing/ dev=$(((8<<20) + 17)) # sdb1 (8,17) -echo 1 > tracing_on +echo 1 > $TRACE/tracing_on # block tracepoints -echo "dev == $dev" > $TRACE/events/block/block_rq_complete/filter -echo 1 > $TRACE/events/block/block_rq_complete/enable +#echo "dev == $dev" > $TRACE/events/block/block_rq_complete/filter +echo 0 > $TRACE/events/block/block_rq_complete/enable echo 0 > $TRACE/events/block/block_bio_complete/enable # GC @@ -41,9 +41,15 @@ echo $S > $TRACE/events/f2fs/f2fs_get_data_block/enable # IOs R=0 W=0 -echo $W > $TRACE/events/f2fs/f2fs_submit_write_page/enable -echo $W > $TRACE/events/f2fs/f2fs_do_submit_bio/enable echo $R > $TRACE/events/f2fs/f2fs_readpage/enable +echo $W > $TRACE/events/f2fs/f2fs_writepage/enable +echo $W > $TRACE/events/f2fs/f2fs_submit_write_bio/enable +echo $R > $TRACE/events/f2fs/f2fs_submit_read_bio/enable + +echo 0 > $TRACE/events/f2fs/f2fs_submit_page_bio/enable +echo 0 > $TRACE/events/f2fs/f2fs_submit_page_mbio/enable +echo 0 > $TRACE/events/f2fs/f2fs_issue_discard/enable +echo 0 > $TRACE/events/f2fs/f2fs_issue_flush/enable # VFS interfaces V=0 -- cgit v1.2.3 From f381590f8005c0d3abaaa6637eacbfe1098f0d4d Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 29 Jul 2014 16:24:52 -0700 Subject: mkfs.f2fs: remove build warning Should be unsigned int for le32_to_cpu. Signed-off-by: Jaegeuk Kim --- mkfs/f2fs_format.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index a62a8fe..e300731 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -432,7 +432,7 @@ static int f2fs_write_check_point_pack(void) u_int32_t blk_size_bytes; u_int64_t cp_seg_blk_offset = 0; u_int32_t crc = 0; - int i; + unsigned int i; char *cp_payload = NULL; ckp = calloc(F2FS_BLKSIZE, 1); -- cgit v1.2.3 From 6cd2c51c205b039e71fe0ffe695d6c7a8864bae4 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 19 Aug 2014 14:05:21 -0700 Subject: dump.f2fs: support dump_file from image This patch adds supporting dump_file, which can extract a file from image. You can simply select [yes|no] when doing dump.f2fs -i [inode number] [img]. Signed-off-by: Jaegeuk Kim --- fsck/dump.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/f2fs_fs.h | 2 + lib/libf2fs_io.c | 9 ++++ 3 files changed, 164 insertions(+) diff --git a/fsck/dump.c b/fsck/dump.c index 880e78a..44d4105 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -115,6 +115,158 @@ void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa) close(fd); } +static void dump_data_blk(__u64 offset, u32 blkaddr) +{ + char buf[F2FS_BLKSIZE]; + + if (blkaddr == NULL_ADDR) + return; + + /* get data */ + if (blkaddr == NEW_ADDR) { + memset(buf, 0, F2FS_BLKSIZE); + } else { + int ret; + ret = dev_read_block(buf, blkaddr); + ASSERT(ret >= 0); + } + + /* write blkaddr */ + dev_write_dump(buf, offset, F2FS_BLKSIZE); +} + +static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype, + u32 nid, u64 *ofs) +{ + struct node_info ni; + struct f2fs_node *node_blk; + int i, ret; + u32 idx, skip; + + switch (ntype) { + case TYPE_DIRECT_NODE: + skip = idx = ADDRS_PER_BLOCK; + break; + case TYPE_INDIRECT_NODE: + idx = NIDS_PER_BLOCK; + skip = idx * ADDRS_PER_BLOCK; + break; + case TYPE_DOUBLE_INDIRECT_NODE: + skip = 0; + idx = NIDS_PER_BLOCK; + break; + } + + if (nid == 0) { + *ofs += skip; + return; + } + + ret = get_node_info(sbi, nid, &ni); + ASSERT(ret >= 0); + + node_blk = calloc(BLOCK_SZ, 1); + dev_read_block(node_blk, ni.blk_addr); + + for (i = 0; i < idx; i++, (*ofs)++) { + switch (ntype) { + case TYPE_DIRECT_NODE: + dump_data_blk(*ofs * F2FS_BLKSIZE, + le32_to_cpu(node_blk->dn.addr[i])); + break; + case TYPE_INDIRECT_NODE: + dump_node_blk(sbi, TYPE_DIRECT_NODE, + le32_to_cpu(node_blk->in.nid[i]), ofs); + break; + case TYPE_DOUBLE_INDIRECT_NODE: + dump_node_blk(sbi, TYPE_INDIRECT_NODE, + le32_to_cpu(node_blk->in.nid[i]), ofs); + break; + } + } + free(node_blk); +} + +static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid, + struct f2fs_node *node_blk) +{ + u32 i = 0; + u64 ofs = 0; + + /* TODO: need to dump xattr */ + + if((node_blk->i.i_inline & F2FS_INLINE_DATA)){ + DBG(3, "ino[0x%x] has inline data!\n", nid); + /* recover from inline data */ + dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET, + 0, MAX_INLINE_DATA); + return; + } + + /* check data blocks in inode */ + for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++) + dump_data_blk(ofs * F2FS_BLKSIZE, + le32_to_cpu(node_blk->i.i_addr[i])); + + /* check node blocks in inode */ + 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); + else if (i == 2 || i == 3) + dump_node_blk(sbi, TYPE_INDIRECT_NODE, + 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); + else + ASSERT(0); + } +} + +void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni, + struct f2fs_node *node_blk) +{ + struct f2fs_inode *inode = &node_blk->i; + u32 imode = le32_to_cpu(inode->i_mode); + char name[255] = {0}; + char path[1024] = {0}; + char ans[255] = {0}; + int ret; + + if (!S_ISREG(imode)) { + MSG(0, "Not a regular file\n\n"); + return; + } + + printf("Do you want to dump this file into ./lost_found/? [Y/N] "); + ret = scanf("%s", ans); + ASSERT(ret >= 0); + + if (!strcasecmp(ans, "y")) { + ret = system("mkdir -p ./lost_found"); + ASSERT(ret >= 0); + + /* make a file */ + strncpy(name, (const char *)inode->i_name, + le32_to_cpu(inode->i_namelen)); + name[le32_to_cpu(inode->i_namelen)] = 0; + sprintf(path, "./lost_found/%s", name); + + config.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666); + ASSERT(config.dump_fd >= 0); + + /* dump file's data */ + dump_inode_blk(sbi, ni->ino, node_blk); + + /* adjust file size */ + ret = ftruncate(config.dump_fd, le32_to_cpu(inode->i_size)); + ASSERT(ret >= 0); + + close(config.dump_fd); + } +} + int dump_node(struct f2fs_sb_info *sbi, nid_t nid) { struct node_info ni; @@ -142,6 +294,7 @@ int dump_node(struct f2fs_sb_info *sbi, nid_t nid) if (le32_to_cpu(node_blk->footer.ino) == ni.ino && le32_to_cpu(node_blk->footer.nid) == ni.nid) { print_node_info(node_blk); + dump_file(sbi, &ni, node_blk); } else { MSG(0, "Invalid node block\n\n"); } diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 80ce918..9ade334 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -173,6 +173,7 @@ struct f2fs_configuration { char *vol_label; int heap; int32_t fd; + int32_t dump_fd; char *device_name; char *extension_list; int dbg_lv; @@ -671,6 +672,7 @@ extern void f2fs_finalize_device(struct f2fs_configuration *); extern int dev_read(void *, __u64, size_t); extern int dev_write(void *, __u64, size_t); +extern int dev_write_dump(void *, __u64, size_t); /* All bytes in the buffer must be 0 use dev_fill(). */ extern int dev_fill(void *, __u64, size_t); diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index 5d9b68d..d5ced53 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -46,6 +46,15 @@ int dev_write(void *buf, __u64 offset, size_t len) return 0; } +int dev_write_dump(void *buf, __u64 offset, size_t len) +{ + if (lseek64(config.dump_fd, (off64_t)offset, SEEK_SET) < 0) + return -1; + if (write(config.dump_fd, buf, len) < 0) + return -1; + return 0; +} + int dev_fill(void *buf, __u64 offset, size_t len) { /* Only allow fill to zero */ -- cgit v1.2.3 From 347e94f4b293b0093f3c23632c0fa797329c1604 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 19 Aug 2014 15:10:47 -0700 Subject: fsck.f2fs: show inode numbers fsck.f2fs -d 1 [dev] : shows inode informations fsck.f2fs -d -1 [dev] : shows directory tree with inode number Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 0f48918..2d8dffb 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -506,7 +506,8 @@ static void print_dentry(__u32 depth, __u8 *name, for (i = 1; i < depth; i++) printf("%c ", tree_mark[i]); - printf("%c-- %s\n", last_de ? '`' : '|', name); + printf("%c-- %s 0x%x\n", last_de ? '`' : '|', + name, le32_to_cpu(de_blk->dentry[idx].ino)); } int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, @@ -561,7 +562,7 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, } } - DBG(2, "[%3u] - no[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n", + DBG(1, "[%3u] - no[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n", fsck->dentry_depth, i, name, name_len, le32_to_cpu(de_blk->dentry[i].ino), de_blk->dentry[i].file_type); -- cgit v1.2.3 From f46078949bdc58736170a2c85ea5b8bd3bcefa25 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 26 Aug 2014 16:28:12 -0700 Subject: f2fs_dentry_hash: avoid casting unsigned char to singed char This can hurt when calculating hash value, resulting in false alarm. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 5 +++-- include/f2fs_fs.h | 2 +- lib/libf2fs.c | 31 ++++++++++++------------------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 2d8dffb..303ba8d 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -542,11 +542,12 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, continue; } - name_len = le32_to_cpu(de_blk->dentry[i].name_len); + name_len = le16_to_cpu(de_blk->dentry[i].name_len); name = calloc(name_len + 1, 1); memcpy(name, de_blk->filename[i], name_len); + hash_code = f2fs_dentry_hash((const unsigned char *)name, + name_len); - hash_code = f2fs_dentry_hash((const char *)name, name_len); ASSERT(le32_to_cpu(de_blk->dentry[i].hash_code) == hash_code); ftype = de_blk->dentry[i].file_type; diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 9ade334..aebb1d2 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -679,7 +679,7 @@ extern int dev_fill(void *, __u64, size_t); extern int dev_read_block(void *, __u64); extern int dev_read_blocks(void *, __u64, __u32 ); -f2fs_hash_t f2fs_dentry_hash(const char *, int); +f2fs_hash_t f2fs_dentry_hash(const unsigned char *, int); extern struct f2fs_configuration config; diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 6168c5c..01ef4e9 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -235,7 +235,8 @@ static void TEA_transform(unsigned int buf[4], unsigned int const in[]) } -static void str2hashbuf(const char *msg, int len, unsigned int *buf, int num) +static void str2hashbuf(const unsigned char *msg, int len, + unsigned int *buf, int num) { unsigned pad, val; int i; @@ -269,24 +270,17 @@ static void str2hashbuf(const char *msg, int len, unsigned int *buf, int num) * @param len name lenth * @return return on success hash value, errno on failure */ -f2fs_hash_t f2fs_dentry_hash(const char *name, int len) +f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len) { __u32 hash; f2fs_hash_t f2fs_hash; - const char *p; + const unsigned char *p; __u32 in[8], buf[4]; /* special hash codes for special dentries */ - if (name[0] == '.') { - if (name[1] == '\0') { - f2fs_hash = F2FS_DOT_HASH; - goto exit; - } - if (name[1] == '.' && name[2] == '\0') { - f2fs_hash = F2FS_DDOT_HASH; - goto exit; - } - } + if ((len <= 2) && (name[0] == '.') && + (name[1] == '.' || name[1] == '\0')) + return 0; /* Initialize the default seed for the hash checksum functions */ buf[0] = 0x67452301; @@ -295,18 +289,17 @@ f2fs_hash_t f2fs_dentry_hash(const char *name, int len) buf[3] = 0x10325476; p = name; - while (len > 0) { + while (1) { str2hashbuf(p, len, in, 4); TEA_transform(buf, in); - len -= 16; p += 16; + if (len <= 16) + break; + len -= 16; } hash = buf[0]; - f2fs_hash = hash; -exit: - f2fs_hash &= ~F2FS_HASH_COL_BIT; - + f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT); return f2fs_hash; } -- cgit v1.2.3 From 6f4106c12bb2faa6cd9922ae3a03b400bdf49fde Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 26 Aug 2014 17:26:01 -0700 Subject: fsck.f2fs: retry to fix corrupted image This patch adds a facility to retry conducting fsck. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 9 +++- fsck/main.c | 141 +++++++++++++++++++++++++++++++++++------------------- include/f2fs_fs.h | 5 ++ 3 files changed, 104 insertions(+), 51 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 303ba8d..9a4c26c 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -761,6 +761,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) node->nid, node->links); node = node->next; } + config.bug_on = 1; } printf("[FSCK] Unreachable nat entries "); @@ -769,6 +770,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) } else { printf(" [Fail] [0x%x]\n", nr_unref_nid); ret = EXIT_ERR_CODE; + config.bug_on = 1; } printf("[FSCK] SIT valid block bitmap checking "); @@ -777,6 +779,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) } else { printf("[Fail]\n"); ret = EXIT_ERR_CODE; + config.bug_on = 1; } printf("[FSCK] Hard link checking for regular file "); @@ -785,6 +788,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) } else { printf(" [Fail] [0x%x]\n", fsck->chk.multi_hard_link_files); ret = EXIT_ERR_CODE; + config.bug_on = 1; } printf("[FSCK] valid_block_count matching with CP "); @@ -793,6 +797,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) } else { printf(" [Fail] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt); ret = EXIT_ERR_CODE; + config.bug_on = 1; } printf("[FSCK] valid_node_count matcing with CP (de lookup) "); @@ -801,6 +806,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) } else { printf(" [Fail] [0x%x]\n", fsck->chk.valid_node_cnt); ret = EXIT_ERR_CODE; + config.bug_on = 1; } printf("[FSCK] valid_node_count matcing with CP (nat lookup) "); @@ -809,6 +815,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) } else { printf(" [Fail] [0x%x]\n", fsck->chk.valid_nat_entry_cnt); ret = EXIT_ERR_CODE; + config.bug_on = 1; } printf("[FSCK] valid_inode_count matched with CP "); @@ -817,8 +824,8 @@ int fsck_verify(struct f2fs_sb_info *sbi) } else { printf(" [Fail] [0x%x]\n", fsck->chk.valid_inode_cnt); ret = EXIT_ERR_CODE; + config.bug_on = 1; } - return ret; } diff --git a/fsck/main.c b/fsck/main.c index 46f5d04..266e9b5 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -11,9 +11,7 @@ #include "fsck.h" #include -struct f2fs_fsck gfsck = { - .sbi = { .fsck = &gfsck, }, -}; +struct f2fs_fsck gfsck; void fsck_usage() { @@ -42,22 +40,27 @@ void f2fs_parse_options(int argc, char *argv[]) char *prog = basename(argv[0]); if (!strcmp("fsck.f2fs", prog)) { - const char *option_string = "d:t"; + const char *option_string = "d:tf"; config.func = FSCK; while ((option = getopt(argc, argv, option_string)) != EOF) { switch (option) { - case 'd': - config.dbg_lv = atoi(optarg); - MSG(0, "Info: Debug level = %d\n", config.dbg_lv); - break; - case 't': - config.dbg_lv = -1; - break; - default: - MSG(0, "\tError: Unknown option %c\n",option); - fsck_usage(); - break; + case 'd': + config.dbg_lv = atoi(optarg); + MSG(0, "Info: Debug level = %d\n", + config.dbg_lv); + break; + case 't': + config.dbg_lv = -1; + break; + case 'f': + config.fix_on = 1; + MSG(0, "Info: Force to fix corruption\n"); + break; + default: + MSG(0, "\tError: Unknown option %c\n", option); + fsck_usage(); + break; } } } else if (!strcmp("dump.f2fs", prog)) { @@ -73,34 +76,46 @@ void f2fs_parse_options(int argc, char *argv[]) config.func = DUMP; while ((option = getopt(argc, argv, option_string)) != EOF) { + int ret = 0; + switch (option) { - case 'd': - config.dbg_lv = atoi(optarg); - MSG(0, "Info: Debug level = %d\n", config.dbg_lv); - break; - case 'i': - if (strncmp(optarg, "0x", 2)) - sscanf(optarg, "%d", &dump_opt.nid); - else - sscanf(optarg, "%x", &dump_opt.nid); - break; - case 's': - sscanf(optarg, "%d~%d", &dump_opt.start_sit, &dump_opt.end_sit); - break; - case 'a': - sscanf(optarg, "%d~%d", &dump_opt.start_ssa, &dump_opt.end_ssa); - break; - case 'b': - if (strncmp(optarg, "0x", 2)) - sscanf(optarg, "%d", &dump_opt.blk_addr); - else - sscanf(optarg, "%x", &dump_opt.blk_addr); - break; - default: - MSG(0, "\tError: Unknown option %c\n", option); - dump_usage(); - break; + case 'd': + config.dbg_lv = atoi(optarg); + MSG(0, "Info: Debug level = %d\n", + config.dbg_lv); + break; + case 'i': + if (strncmp(optarg, "0x", 2)) + ret = sscanf(optarg, "%d", + &dump_opt.nid); + else + ret = sscanf(optarg, "%x", + &dump_opt.nid); + break; + case 's': + ret = sscanf(optarg, "%d~%d", + &dump_opt.start_sit, + &dump_opt.end_sit); + break; + case 'a': + ret = sscanf(optarg, "%d~%d", + &dump_opt.start_ssa, + &dump_opt.end_ssa); + break; + case 'b': + if (strncmp(optarg, "0x", 2)) + ret = sscanf(optarg, "%d", + &dump_opt.blk_addr); + else + ret = sscanf(optarg, "%x", + &dump_opt.blk_addr); + break; + default: + MSG(0, "\tError: Unknown option %c\n", option); + dump_usage(); + break; } + ASSERT(ret >= 0); } config.private = &dump_opt; @@ -121,13 +136,15 @@ int do_fsck(struct f2fs_sb_info *sbi) u32 blk_cnt; int ret; + config.bug_on = 0; + ret = fsck_init(sbi); if (ret < 0) return ret; fsck_chk_orphan_node(sbi); - /* Travses all block recursively from root inode */ + /* Traverse all block recursively from root inode */ blk_cnt = 1; ret = fsck_chk_node_blk(sbi, NULL, @@ -139,7 +156,6 @@ int do_fsck(struct f2fs_sb_info *sbi) goto out1; ret = fsck_verify(sbi); - out1: fsck_free(sbi); return ret; @@ -176,7 +192,7 @@ cleanup: int main (int argc, char **argv) { - struct f2fs_sb_info *sbi = &gfsck.sbi; + struct f2fs_sb_info *sbi; int ret = 0; f2fs_init_configuration(&config); @@ -189,21 +205,46 @@ int main (int argc, char **argv) /* Get device */ if (f2fs_get_device_info(&config) < 0) return -1; +fsck_again: + memset(&gfsck, 0, sizeof(gfsck)); + gfsck.sbi.fsck = &gfsck; + sbi = &gfsck.sbi; if (f2fs_do_mount(sbi) < 0) return -1; switch (config.func) { - case FSCK: - ret = do_fsck(sbi); - break; - case DUMP: - ret = do_dump(sbi); - break; + case FSCK: + ret = do_fsck(sbi); + break; + case DUMP: + ret = do_dump(sbi); + break; } f2fs_do_umount(sbi); + if (config.func == FSCK && config.bug_on) { + if (config.fix_on == 0) { + char ans[255] = {0}; +retry: + printf("Do you want to fix this partition? [Y/N] "); + ret = scanf("%s", ans); + ASSERT(ret >= 0); + if (!strcasecmp(ans, "y")) + config.fix_cnt++; + else if (!strcasecmp(ans, "n")) + config.fix_cnt = 0; + else + goto retry; + } else { + config.fix_cnt++; + } + /* avoid infinite trials */ + if (config.fix_cnt > 0 && config.fix_cnt < 4) + goto fsck_again; + } + f2fs_finalize_device(&config); printf("\nDone.\n"); diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index aebb1d2..49911a0 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -60,6 +60,7 @@ typedef unsigned long pgoff_t; printf("\nAssertion failed!\n"); \ printf("[%s:%4d] " #exp, __func__, __LINE__); \ printf("\n --> "fmt, ##__VA_ARGS__); \ + config.bug_on = 1; \ exit(-1); \ } \ } while (0); @@ -69,6 +70,7 @@ typedef unsigned long pgoff_t; if (!(exp)) { \ printf("\nAssertion failed!\n"); \ printf("[%s:%4d] " #exp"\n", __func__, __LINE__);\ + config.bug_on = 1; \ exit(-1); \ } \ } while (0); @@ -180,6 +182,9 @@ struct f2fs_configuration { int trim; int func; void *private; + int fix_on; + int fix_cnt; + int bug_on; } __attribute__((packed)); #ifdef CONFIG_64BIT -- cgit v1.2.3 From f6d1d582e9d561082834726475e1e7f51ea6d06d Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 27 Aug 2014 16:16:16 -0700 Subject: fsck.f2fs: clean up codes Fix wrong coding style. Signed-off-by: Jaegeuk Kim --- fsck/dump.c | 2 +- fsck/f2fs.h | 12 +-- fsck/fsck.c | 294 +++++++++++++++++++++++++----------------------------- fsck/fsck.h | 105 +++++++------------ include/f2fs_fs.h | 83 ++++++++------- 5 files changed, 217 insertions(+), 279 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index 44d4105..e14a190 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -141,7 +141,7 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype, struct node_info ni; struct f2fs_node *node_blk; int i, ret; - u32 idx, skip; + u32 idx, skip = 0; switch (ntype) { case TYPE_DIRECT_NODE: diff --git a/fsck/f2fs.h b/fsck/f2fs.h index 427a733..aa43cdc 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -301,12 +301,12 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type) (segno / SIT_ENTRY_PER_BLOCK) #define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segments) -#define IS_VALID_NID(sbi, nid) \ - do { \ - ASSERT(nid <= (NAT_ENTRY_PER_BLOCK * \ - F2FS_RAW_SUPER(sbi)->segment_count_nat \ - << (sbi->log_blocks_per_seg - 1))); \ - } while (0); +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 + << (sbi->log_blocks_per_seg - 1))); +} #define IS_VALID_BLK_ADDR(sbi, addr) \ do { \ diff --git a/fsck/fsck.c b/fsck/fsck.c index 9a4c26c..5c99385 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -13,7 +13,30 @@ char *tree_mark; uint32_t tree_mark_size = 256; -static int add_into_hard_link_list(struct f2fs_sb_info *sbi, u32 nid, u32 link_cnt) +static inline int f2fs_set_main_bitmap(struct f2fs_sb_info *sbi, u32 blk) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + + return f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, blk), fsck->main_area_bitmap); +} + +static inline int f2fs_test_main_bitmap(struct f2fs_sb_info *sbi, u32 blk) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + + return f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk), + fsck->main_area_bitmap); +} + +static inline int f2fs_test_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + + return f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk), fsck->sit_area_bitmap); +} + +static int add_into_hard_link_list(struct f2fs_sb_info *sbi, + u32 nid, u32 link_cnt) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct hard_link_node *node = NULL, *tmp = NULL, *prev = NULL; @@ -90,7 +113,8 @@ static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid) } -static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, u32 blk_addr) +static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, + u32 blk_addr) { int ret = 0; struct f2fs_summary sum_entry; @@ -99,23 +123,26 @@ static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, u32 blk_addr ASSERT(ret >= 0); if (ret == SEG_TYPE_DATA || ret == SEG_TYPE_CUR_DATA) { - ASSERT_MSG(0, "Summary footer is not a node segment summary\n");; + ASSERT_MSG("Summary footer is not for node segment\n"); } else if (ret == SEG_TYPE_NODE) { if (le32_to_cpu(sum_entry.nid) != nid) { DBG(0, "nid [0x%x]\n", nid); DBG(0, "target blk_addr [0x%x]\n", blk_addr); DBG(0, "summary blk_addr [0x%x]\n", - GET_SUM_BLKADDR(sbi, GET_SEGNO(sbi, blk_addr))); + GET_SUM_BLKADDR(sbi, + GET_SEGNO(sbi, blk_addr))); DBG(0, "seg no / offset [0x%x / 0x%x]\n", - GET_SEGNO(sbi, blk_addr), OFFSET_IN_SEG(sbi, blk_addr)); - DBG(0, "summary_entry.nid [0x%x]\n", le32_to_cpu(sum_entry.nid)); + GET_SEGNO(sbi, blk_addr), + OFFSET_IN_SEG(sbi, blk_addr)); + DBG(0, "summary_entry.nid [0x%x]\n", + le32_to_cpu(sum_entry.nid)); DBG(0, "--> node block's nid [0x%x]\n", nid); - ASSERT_MSG(0, "Invalid node seg summary\n"); + ASSERT_MSG("Invalid node seg summary\n"); } } else if (ret == SEG_TYPE_CUR_NODE) { /* current node segment has no ssa */ } else { - ASSERT_MSG(0, "Invalid return value of 'get_sum_entry'"); + ASSERT_MSG("Invalid return value of 'get_sum_entry'"); } return 1; @@ -134,18 +161,19 @@ static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, sum_entry.version != version || le16_to_cpu(sum_entry.ofs_in_node) != idx_in_node) { - DBG(0, "summary_entry.nid [0x%x]\n", le32_to_cpu(sum_entry.nid)); - DBG(0, "summary_entry.version [0x%x]\n", sum_entry.version); - DBG(0, "summary_entry.ofs_in_node [0x%x]\n", le16_to_cpu(sum_entry.ofs_in_node)); - + DBG(0, "summary_entry.nid [0x%x]\n", + le32_to_cpu(sum_entry.nid)); + DBG(0, "summary_entry.version [0x%x]\n", + sum_entry.version); + DBG(0, "summary_entry.ofs_in_node [0x%x]\n", + le16_to_cpu(sum_entry.ofs_in_node)); DBG(0, "parent nid [0x%x]\n", parent_nid); DBG(0, "version from nat [0x%x]\n", version); DBG(0, "idx in parent node [0x%x]\n", idx_in_node); DBG(0, "Target data block addr [0x%x]\n", blk_addr); - ASSERT_MSG(0, "Invalid data seg summary\n"); + ASSERT_MSG("Invalid data seg summary\n"); } - return 1; } @@ -161,13 +189,14 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk = NULL; int ret = 0; - IS_VALID_NID(sbi, nid); + if (!IS_VALID_NID(sbi, nid)) + ASSERT_MSG("nid is not valid. [0x%x]", nid); if (ftype != F2FS_FT_ORPHAN || f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0x0) f2fs_clear_bit(nid, fsck->nat_area_bitmap); else - ASSERT_MSG(0, "nid duplicated [0x%x]\n", nid); + ASSERT_MSG("nid duplicated [0x%x]\n", nid); ret = get_node_info(sbi, nid, &ni); ASSERT(ret >= 0); @@ -188,12 +217,10 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, is_valid_ssa_node_blk(sbi, nid, ni.blk_addr); - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->sit_area_bitmap) == 0x0) { - DBG(0, "SIT bitmap is 0x0. blk_addr[0x%x]\n", ni.blk_addr); - ASSERT(0); - } + if (f2fs_test_sit_bitmap(sbi, ni.blk_addr) == 0) + ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", ni.blk_addr); - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) == 0x0) { + if (f2fs_test_main_bitmap(sbi, ni.blk_addr) == 0) { fsck->chk.valid_blk_cnt++; fsck->chk.valid_node_cnt++; } @@ -204,8 +231,8 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, ret = dev_read_block(node_blk, ni.blk_addr); ASSERT(ret >= 0); - ASSERT_MSG(nid == le32_to_cpu(node_blk->footer.nid), - "nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]\n", + if (nid != le32_to_cpu(node_blk->footer.nid)) + ASSERT_MSG("nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]", nid, ni.blk_addr, le32_to_cpu(node_blk->footer.nid)); if (ntype == TYPE_INODE) { @@ -219,34 +246,23 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, /* it's not inode */ ASSERT(node_blk->footer.nid != node_blk->footer.ino); - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) != 0) { - DBG(0, "Duplicated node block. ino[0x%x][0x%x]\n", nid, ni.blk_addr); - ASSERT(0); - } - f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap); + if (f2fs_test_main_bitmap(sbi, ni.blk_addr) != 0) + ASSERT_MSG("Duplicated node blk. nid[0x%x][0x%x]\n", + nid, ni.blk_addr); + + f2fs_set_main_bitmap(sbi, ni.blk_addr); switch (ntype) { case TYPE_DIRECT_NODE: - ret = fsck_chk_dnode_blk(sbi, - inode, - nid, - ftype, - node_blk, - blk_cnt, - &ni); + ret = fsck_chk_dnode_blk(sbi, inode, nid, ftype, + node_blk, blk_cnt, &ni); break; case TYPE_INDIRECT_NODE: - ret = fsck_chk_idnode_blk(sbi, - inode, - ftype, - node_blk, + ret = fsck_chk_idnode_blk(sbi, inode, ftype, node_blk, blk_cnt); break; case TYPE_DOUBLE_INDIRECT_NODE: - ret = fsck_chk_didnode_blk(sbi, - inode, - ftype, - node_blk, + ret = fsck_chk_didnode_blk(sbi, inode, ftype, node_blk, blk_cnt); break; default: @@ -277,7 +293,7 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, ASSERT(node_blk->footer.nid == node_blk->footer.ino); ASSERT(le32_to_cpu(node_blk->footer.nid) == nid); - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) == 0x0) + if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) fsck->chk.valid_inode_cnt++; /* Orphan node. i_links should be 0 */ @@ -290,16 +306,16 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, if (ftype == F2FS_FT_DIR) { /* not included '.' & '..' */ - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) != 0) { - DBG(0, "Duplicated inode blk. ino[0x%x][0x%x]\n", nid, ni->blk_addr); + if (f2fs_test_main_bitmap(sbi, ni->blk_addr) != 0) { + DBG(0, "Duplicated inode blk. ino[0x%x][0x%x]\n", + nid, ni->blk_addr); ASSERT(0); } - f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap); + f2fs_set_main_bitmap(sbi, ni->blk_addr); } else { - - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) == 0x0) { - f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap); + if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) { + f2fs_set_main_bitmap(sbi, ni->blk_addr); if (i_links > 1) { /* First time. Create new hard link node */ add_into_hard_link_list(sbi, nid, i_links); @@ -308,13 +324,14 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, } else { if (i_links <= 1) { DBG(0, "Error. Node ID [0x%x]." - " There are one more hard links." - " But i_links is [0x%x]\n", + " There are one more hard links." + " But i_links is [0x%x]\n", nid, i_links); ASSERT(0); } - DBG(3, "ino[0x%x] has hard links [0x%x]\n", nid, i_links); + DBG(3, "ino[0x%x] has hard links [0x%x]\n", + nid, i_links); ret = find_and_dec_hard_link_list(sbi, nid); ASSERT(ret >= 0); @@ -323,7 +340,8 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, } } - fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt); + fsck_chk_xattr_blk(sbi, nid, + le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt); if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV || ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK) @@ -339,13 +357,9 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, *blk_cnt = *blk_cnt + 1; ret = fsck_chk_data_blk(sbi, le32_to_cpu(node_blk->i.i_addr[idx]), - &child_cnt, - &child_files, + &child_cnt, &child_files, (i_blocks == *blk_cnt), - ftype, - nid, - idx, - ni->version); + ftype, nid, idx, ni->version); ASSERT(ret >= 0); } } @@ -363,23 +377,23 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, if (le32_to_cpu(node_blk->i.i_nid[idx]) != 0) { *blk_cnt = *blk_cnt + 1; - ret = fsck_chk_node_blk(sbi, - &node_blk->i, + ret = fsck_chk_node_blk(sbi, &node_blk->i, le32_to_cpu(node_blk->i.i_nid[idx]), - ftype, - ntype, - blk_cnt); + ftype, ntype, blk_cnt); ASSERT(ret >= 0); } } check: if (ftype == F2FS_FT_DIR) - DBG(1, "Directory Inode: ino: %x name: %s depth: %d child files: %d\n\n", - le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, - le32_to_cpu(node_blk->i.i_current_depth), child_files); + DBG(1, "Directory Inode: 0x%x [%s] depth: %d has %d files\n\n", + le32_to_cpu(node_blk->footer.ino), + node_blk->i.i_name, + le32_to_cpu(node_blk->i.i_current_depth), + child_files); if (ftype == F2FS_FT_ORPHAN) - DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %u\n\n", - le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, + DBG(1, "Orphan Inode: 0x%x [%s] i_blocks: %u\n\n", + le32_to_cpu(node_blk->footer.ino), + node_blk->i.i_name, (u32)i_blocks); if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || (i_blocks != *blk_cnt)) { @@ -395,13 +409,9 @@ out: return 0; } -int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - u32 nid, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt, - struct node_info *ni) +int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, + u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk, + u32 *blk_cnt, struct node_info *ni) { int idx; u32 child_cnt = 0, child_files = 0; @@ -411,24 +421,16 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, continue; *blk_cnt = *blk_cnt + 1; fsck_chk_data_blk(sbi, - le32_to_cpu(node_blk->dn.addr[idx]), - &child_cnt, - &child_files, - le64_to_cpu(inode->i_blocks) == *blk_cnt, - ftype, - nid, - idx, - ni->version); + le32_to_cpu(node_blk->dn.addr[idx]), + &child_cnt, &child_files, + le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype, + nid, idx, ni->version); } - return 0; } -int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt) +int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, + enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt) { int i = 0; @@ -436,22 +438,14 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, if (le32_to_cpu(node_blk->in.nid[i]) == 0x0) continue; *blk_cnt = *blk_cnt + 1; - fsck_chk_node_blk(sbi, - inode, - le32_to_cpu(node_blk->in.nid[i]), - ftype, - TYPE_DIRECT_NODE, - blk_cnt); + fsck_chk_node_blk(sbi, inode, le32_to_cpu(node_blk->in.nid[i]), + ftype, TYPE_DIRECT_NODE, blk_cnt); } - return 0; } -int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt) +int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, + enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt) { int i = 0; @@ -459,14 +453,10 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, if (le32_to_cpu(node_blk->in.nid[i]) == 0x0) continue; *blk_cnt = *blk_cnt + 1; - fsck_chk_node_blk(sbi, - inode, + fsck_chk_node_blk(sbi, inode, le32_to_cpu(node_blk->in.nid[i]), - ftype, - TYPE_INDIRECT_NODE, - blk_cnt); + ftype, TYPE_INDIRECT_NODE, blk_cnt); } - return 0; } @@ -510,11 +500,8 @@ static void print_dentry(__u32 depth, __u8 *name, name, le32_to_cpu(de_blk->dentry[idx].ino)); } -int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, - u32 blk_addr, - u32 *child_cnt, - u32 *child_files, - int last_blk) +int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr, + u32 *child_cnt, u32 *child_files, int last_blk) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); int i; @@ -537,7 +524,7 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, fsck->dentry_depth++; for (i = 0; i < NR_DENTRY_IN_BLOCK;) { - if (test_bit(i, (unsigned long *)de_blk->dentry_bitmap) == 0x0) { + if (test_bit(i, (unsigned long *)de_blk->dentry_bitmap) == 0) { i++; continue; } @@ -555,15 +542,16 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, /* Becareful. 'dentry.file_type' is not imode. */ if (ftype == F2FS_FT_DIR) { *child_cnt = *child_cnt + 1; - if ((name[0] == '.' && name[1] == '.' && name_len == 2) || - (name[0] == '.' && name_len == 1)) { + if ((name[0] == '.' && name_len == 1) || + (name[0] == '.' && name[1] == '.' && + name_len == 2)) { i++; free(name); continue; } } - DBG(1, "[%3u] - no[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n", + DBG(1, "[%3u]-[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n", fsck->dentry_depth, i, name, name_len, le32_to_cpu(de_blk->dentry[i].ino), de_blk->dentry[i].file_type); @@ -586,23 +574,19 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, free(name); } - DBG(1, "[%3d] Dentry Block [0x%x] Done : dentries:%d in %d slots (len:%d)\n\n", - fsck->dentry_depth, blk_addr, dentries, NR_DENTRY_IN_BLOCK, F2FS_NAME_LEN); + DBG(1, "[%3d] Dentry Block [0x%x] Done : " + "dentries:%d in %d slots (len:%d)\n\n", + fsck->dentry_depth, blk_addr, dentries, + NR_DENTRY_IN_BLOCK, F2FS_NAME_LEN); fsck->dentry_depth--; free(de_blk); return 0; } -int fsck_chk_data_blk(struct f2fs_sb_info *sbi, - u32 blk_addr, - u32 *child_cnt, - u32 *child_files, - int last_blk, - enum FILE_TYPE ftype, - u32 parent_nid, - u16 idx_in_node, - u8 ver) +int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, + u32 *child_cnt, u32 *child_files, int last_blk, + enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); @@ -616,24 +600,20 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, is_valid_ssa_data_blk(sbi, blk_addr, parent_nid, idx_in_node, ver); - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk_addr), fsck->sit_area_bitmap) == 0x0) { - ASSERT_MSG(0, "SIT bitmap is 0x0. blk_addr[0x%x]\n", blk_addr); - } + if (f2fs_test_sit_bitmap(sbi, blk_addr) == 0) + ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]\n", blk_addr); - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk_addr), fsck->main_area_bitmap) != 0) { - ASSERT_MSG(0, "Duplicated data block. pnid[0x%x] idx[0x%x] blk_addr[0x%x]\n", - parent_nid, idx_in_node, blk_addr); - } - f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, blk_addr), fsck->main_area_bitmap); + if (f2fs_test_main_bitmap(sbi, blk_addr) != 0) + ASSERT_MSG("Duplicated data [0x%x]. pnid[0x%x] idx[0x%x]", + blk_addr, parent_nid, idx_in_node); + + f2fs_set_main_bitmap(sbi, blk_addr); fsck->chk.valid_blk_cnt++; if (ftype == F2FS_FT_DIR) { - fsck_chk_dentry_blk(sbi, - blk_addr, - child_cnt, - child_files, - last_blk); + fsck_chk_dentry_blk(sbi, blk_addr, child_cnt, + child_files, last_blk); } return 0; @@ -665,23 +645,18 @@ int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) nid_t ino = le32_to_cpu(orphan_blk->ino[j]); DBG(1, "[%3d] ino [0x%x]\n", i, ino); blk_cnt = 1; - ret = fsck_chk_node_blk(sbi, - NULL, - ino, - F2FS_FT_ORPHAN, - TYPE_INODE, - &blk_cnt); + ret = fsck_chk_node_blk(sbi, NULL, ino, + F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt); ASSERT(ret >= 0); } memset(orphan_blk, 0, BLOCK_SZ); } free(orphan_blk); - - return 0; } -int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, u32 x_nid, u32 *blk_cnt) +int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, + u32 x_nid, u32 *blk_cnt) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct node_info ni; @@ -692,7 +667,7 @@ int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, u32 x_nid, u32 *blk_cn if (f2fs_test_bit(x_nid, fsck->nat_area_bitmap) != 0x0) { f2fs_clear_bit(x_nid, fsck->nat_area_bitmap); } else { - ASSERT_MSG(0, "xattr_nid duplicated [0x%x]\n", x_nid); + ASSERT_MSG("xattr_nid duplicated [0x%x]\n", x_nid); } *blk_cnt = *blk_cnt + 1; @@ -701,12 +676,12 @@ int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, u32 x_nid, u32 *blk_cn ASSERT(get_node_info(sbi, x_nid, &ni) >= 0); - if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) != 0) { - ASSERT_MSG(0, "Duplicated node block for x_attr. " + if (f2fs_test_main_bitmap(sbi, ni.blk_addr) != 0) { + ASSERT_MSG("Duplicated node block for x_attr. " "x_nid[0x%x] block addr[0x%x]\n", x_nid, ni.blk_addr); } - f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap); + f2fs_set_main_bitmap(sbi, ni.blk_addr); DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid); return 0; @@ -718,8 +693,10 @@ int fsck_init(struct f2fs_sb_info *sbi) struct f2fs_sm_info *sm_i = SM_I(sbi); /* - * We build three bitmap for main/sit/nat so that may check consistency of filesystem. - * 1. main_area_bitmap will be used to check whether all blocks of main area is used or not. + * We build three bitmap for main/sit/nat so that may check consistency + * of filesystem. + * 1. main_area_bitmap will be used to check whether all blocks of main + * area is used or not. * 2. nat_area_bitmap has bitmap information of used nid in NAT. * 3. sit_area_bitmap has bitmap information of used main block. * At Last sequence, we compare main_area_bitmap with sit_area_bitmap. @@ -774,7 +751,8 @@ int fsck_verify(struct f2fs_sb_info *sbi) } printf("[FSCK] SIT valid block bitmap checking "); - if (memcmp(fsck->sit_area_bitmap, fsck->main_area_bitmap, fsck->sit_area_bitmap_sz) == 0x0) { + if (memcmp(fsck->sit_area_bitmap, fsck->main_area_bitmap, + fsck->sit_area_bitmap_sz) == 0x0) { printf("[Ok..]\n"); } else { printf("[Fail]\n"); diff --git a/fsck/fsck.h b/fsck/fsck.h index e5a3841..dcb6656 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -76,72 +76,37 @@ enum seg_type { SEG_TYPE_MAX, }; -extern int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, u32 x_nid, u32 *blk_cnt); -extern int fsck_chk_orphan_node(struct f2fs_sb_info *sbi); - -extern int fsck_chk_node_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - u32 nid, - enum FILE_TYPE ftype, - enum NODE_TYPE ntype, - u32 *blk_cnt); - -extern int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, - u32 nid, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt, - struct node_info *ni); - -extern int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - u32 nid, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt, - struct node_info *ni); - -extern int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt); - -extern int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt); - -extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, - u32 blk_addr, - u32 *child_cnt, - u32 *child_files, - int last_blk, - enum FILE_TYPE ftype, - u32 parent_nid, - u16 idx_in_node, - u8 ver); - -extern int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, - u32 blk_addr, - u32 *child_cnt, - u32 *child_files, - int last_blk); - -extern void print_node_info(struct f2fs_node *node_block); -extern void print_inode_info(struct f2fs_inode *inode); -extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi, unsigned int segno); -extern int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum_blk); -extern int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, struct f2fs_summary *sum_entry); -extern int get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni); -extern void build_nat_area_bitmap(struct f2fs_sb_info *sbi); -extern int build_sit_area_bitmap(struct f2fs_sb_info *sbi); -extern int fsck_init(struct f2fs_sb_info *sbi); -extern int fsck_verify(struct f2fs_sb_info *sbi); -extern void fsck_free(struct f2fs_sb_info *sbi); -extern int f2fs_do_mount(struct f2fs_sb_info *sbi); -extern void f2fs_do_umount(struct f2fs_sb_info *sbi); +extern int fsck_chk_xattr_blk(struct f2fs_sb_info *, u32, u32, u32 *); +extern int fsck_chk_orphan_node(struct f2fs_sb_info *); +extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32, + enum FILE_TYPE, enum NODE_TYPE, u32 *); +extern int fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE, + struct f2fs_node *, u32 *, struct node_info *); +extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *, + u32, enum FILE_TYPE, struct f2fs_node *, u32 *, + struct node_info *); +extern int fsck_chk_idnode_blk(struct f2fs_sb_info *, struct f2fs_inode *, + enum FILE_TYPE, struct f2fs_node *, u32 *); +extern int fsck_chk_didnode_blk(struct f2fs_sb_info *, struct f2fs_inode *, + enum FILE_TYPE, struct f2fs_node *, u32 *); +extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32, u32 *, u32 *, + int, enum FILE_TYPE, u32, u16, u8); +extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, u32, u32 *, u32 *, int); + +extern void print_node_info(struct f2fs_node *); +extern void print_inode_info(struct f2fs_inode *); +extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int); +extern int get_sum_block(struct f2fs_sb_info *, unsigned int, + struct f2fs_summary_block *); +extern int get_sum_entry(struct f2fs_sb_info *, u32, struct f2fs_summary *); +extern int get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); +extern void build_nat_area_bitmap(struct f2fs_sb_info *); +extern int build_sit_area_bitmap(struct f2fs_sb_info *); +extern int fsck_init(struct f2fs_sb_info *); +extern int fsck_verify(struct f2fs_sb_info *); +extern void fsck_free(struct f2fs_sb_info *); +extern int f2fs_do_mount(struct f2fs_sb_info *); +extern void f2fs_do_umount(struct f2fs_sb_info *); /* dump.c */ struct dump_option { @@ -153,9 +118,9 @@ struct dump_option { int32_t blk_addr; }; -extern void sit_dump(struct f2fs_sb_info *sbi, int start_sit, int end_sit); -extern void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa); -extern int dump_node(struct f2fs_sb_info *sbi, nid_t nid); -extern int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr); +extern void sit_dump(struct f2fs_sb_info *, int, int); +extern void ssa_dump(struct f2fs_sb_info *, int, int); +extern int dump_node(struct f2fs_sb_info *, nid_t); +extern int dump_inode_from_blkaddr(struct f2fs_sb_info *, u32); #endif /* _FSCK_H_ */ diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 49911a0..dace9aa 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -54,39 +54,33 @@ typedef unsigned long pgoff_t; /* * Debugging interfaces */ -#define ASSERT_MSG(exp, fmt, ...) \ +#define ASSERT_MSG(fmt, ...) \ do { \ - if (!(exp)) { \ - printf("\nAssertion failed!\n"); \ - printf("[%s:%4d] " #exp, __func__, __LINE__); \ - printf("\n --> "fmt, ##__VA_ARGS__); \ - config.bug_on = 1; \ - exit(-1); \ - } \ - } while (0); + printf("[ASSERT] (%s:%4d) ", __func__, __LINE__); \ + printf(" --> "fmt"\n", ##__VA_ARGS__); \ + config.bug_on = 1; \ + } while (0) #define ASSERT(exp) \ do { \ if (!(exp)) { \ - printf("\nAssertion failed!\n"); \ - printf("[%s:%4d] " #exp"\n", __func__, __LINE__);\ - config.bug_on = 1; \ + printf("[ASSERT] (%s:%4d) " #exp"\n", \ + __func__, __LINE__); \ exit(-1); \ } \ - } while (0); + } while (0) #define ERR_MSG(fmt, ...) \ do { \ - printf("[%s:%d] " fmt, __func__, __LINE__, ##__VA_ARGS__); \ - } while (0); - + printf("[%s:%d] " fmt, __func__, __LINE__, ##__VA_ARGS__); \ + } while (0) #define MSG(n, fmt, ...) \ do { \ if (config.dbg_lv >= n) { \ printf(fmt, ##__VA_ARGS__); \ } \ - } while (0); + } while (0) #define DBG(n, fmt, ...) \ do { \ @@ -94,52 +88,52 @@ typedef unsigned long pgoff_t; printf("[%s:%4d] " fmt, \ __func__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0); + } while (0) /* Display on console */ #define DISP(fmt, ptr, member) \ do { \ printf("%-30s" fmt, #member, ((ptr)->member)); \ - } while (0); + } while (0) #define DISP_u32(ptr, member) \ do { \ assert(sizeof((ptr)->member) <= 4); \ printf("%-30s" "\t\t[0x%8x : %u]\n", \ - #member, ((ptr)->member), ((ptr)->member) ); \ - } while (0); + #member, ((ptr)->member), ((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) ); \ - } while (0); + #member, ((ptr)->member), ((ptr)->member)); \ + } while (0) #define DISP_utf(ptr, member) \ do { \ - printf("%-30s" "\t\t[%s]\n", #member, ((ptr)->member) ); \ - } while (0); + printf("%-30s" "\t\t[%s]\n", #member, ((ptr)->member)); \ + } while (0) /* Display to buffer */ -#define BUF_DISP_u32(buf, data, len, ptr, member) \ - do { \ - assert(sizeof((ptr)->member) <= 4); \ - snprintf(buf, len, #member); \ - snprintf(data, len, "0x%x : %u", ((ptr)->member), ((ptr)->member)); \ - } while (0); - -#define BUF_DISP_u64(buf, data, len, ptr, member) \ - do { \ - assert(sizeof((ptr)->member) == 8); \ - snprintf(buf, len, #member); \ - snprintf(data, len, "0x%llx : %llu", ((ptr)->member), ((ptr)->member)); \ - } while (0); - -#define BUF_DISP_utf(buf, data, len, ptr, member) \ - do { \ - snprintf(buf, len, #member); \ - } while (0); +#define BUF_DISP_u32(buf, data, len, ptr, member) \ + do { \ + assert(sizeof((ptr)->member) <= 4); \ + snprintf(buf, len, #member); \ + snprintf(data, len, "0x%x : %u", ((ptr)->member), \ + ((ptr)->member)); \ + } while (0) + +#define BUF_DISP_u64(buf, data, len, ptr, member) \ + do { \ + assert(sizeof((ptr)->member) == 8); \ + snprintf(buf, len, #member); \ + snprintf(data, len, "0x%llx : %llu", ((ptr)->member), \ + ((ptr)->member)); \ + } while (0) + +#define BUF_DISP_utf(buf, data, len, ptr, member) \ + snprintf(buf, len, #member) /* these are defined in kernel */ #define PAGE_SIZE 4096 @@ -665,7 +659,8 @@ extern int test_bit(unsigned int nr, const void * addr); extern int f2fs_test_bit(unsigned int, const char *); extern int f2fs_set_bit(unsigned int, char *); extern int f2fs_clear_bit(unsigned int, char *); -extern unsigned long find_next_bit(const unsigned long *, unsigned long, unsigned long); +extern unsigned long find_next_bit(const unsigned long *, + unsigned long, unsigned long); extern u_int32_t f2fs_cal_crc32(u_int32_t, void *, int); extern int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len); -- cgit v1.2.3 From 7aafb1b5f46b873aa610312e818025fe3141e03e Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 27 Aug 2014 16:32:06 -0700 Subject: fsck.f2fs: handle IS_VALID_BLK_ADDR Signed-off-by: Jaegeuk Kim --- fsck/f2fs.h | 21 +++++++++++---------- fsck/fsck.c | 14 +++++++++++--- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index aa43cdc..2adffd8 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -308,16 +308,17 @@ static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid) << (sbi->log_blocks_per_seg - 1))); } -#define IS_VALID_BLK_ADDR(sbi, addr) \ - do { \ - if (addr >= F2FS_RAW_SUPER(sbi)->block_count || \ - addr < SM_I(sbi)->main_blkaddr) \ - { \ - DBG(0, "block addr [0x%x]\n", addr); \ - ASSERT(addr < F2FS_RAW_SUPER(sbi)->block_count); \ - ASSERT(addr >= SM_I(sbi)->main_blkaddr); \ - } \ - } while (0); +static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr) +{ + if (addr >= F2FS_RAW_SUPER(sbi)->block_count || + addr < SM_I(sbi)->main_blkaddr) { + DBG(0, "block addr [0x%x]\n", addr); + ASSERT(addr < F2FS_RAW_SUPER(sbi)->block_count); + ASSERT(addr >= SM_I(sbi)->main_blkaddr); + return 0; + } + return 1; +} static inline u64 BLKOFF_FROM_MAIN(struct f2fs_sb_info *sbi, u64 blk_addr) { diff --git a/fsck/fsck.c b/fsck/fsck.c index 5c99385..5eab522 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -189,8 +189,10 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk = NULL; int ret = 0; - if (!IS_VALID_NID(sbi, nid)) + if (!IS_VALID_NID(sbi, nid)) { ASSERT_MSG("nid is not valid. [0x%x]", nid); + return 0; + } if (ftype != F2FS_FT_ORPHAN || f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0x0) @@ -213,7 +215,10 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, return 0; } - IS_VALID_BLK_ADDR(sbi, ni.blk_addr); + if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) { + ASSERT_MSG("blkaddres is not valid. [0x%x]", ni.blk_addr); + return 0; + } is_valid_ssa_node_blk(sbi, nid, ni.blk_addr); @@ -596,7 +601,10 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, return 0; } - IS_VALID_BLK_ADDR(sbi, blk_addr); + if (!IS_VALID_BLK_ADDR(sbi, blk_addr)) { + ASSERT_MSG("blkaddres is not valid. [0x%x]", blk_addr); + return 0; + } is_valid_ssa_data_blk(sbi, blk_addr, parent_nid, idx_in_node, ver); -- cgit v1.2.3 From 2701c94ab00c350a41ab874a52846b0a93bad9e1 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 27 Aug 2014 16:39:23 -0700 Subject: fsck.f2fs: remove return value of get_node_info We don't need to get the return value. Signed-off-by: Jaegeuk Kim --- fsck/dump.c | 23 +++++++++-------------- fsck/fsck.c | 5 ++--- fsck/fsck.h | 4 ++-- fsck/mount.c | 23 +++++++---------------- 4 files changed, 20 insertions(+), 35 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index e14a190..54f9a52 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -140,8 +140,8 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype, { struct node_info ni; struct f2fs_node *node_blk; - int i, ret; u32 idx, skip = 0; + int i; switch (ntype) { case TYPE_DIRECT_NODE: @@ -162,8 +162,7 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype, return; } - ret = get_node_info(sbi, nid, &ni); - ASSERT(ret >= 0); + get_node_info(sbi, nid, &ni); node_blk = calloc(BLOCK_SZ, 1); dev_read_block(node_blk, ni.blk_addr); @@ -267,14 +266,12 @@ void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni, } } -int dump_node(struct f2fs_sb_info *sbi, nid_t nid) +void dump_node(struct f2fs_sb_info *sbi, nid_t nid) { struct node_info ni; struct f2fs_node *node_blk; - int ret; - ret = get_node_info(sbi, nid, &ni); - ASSERT(ret >= 0); + get_node_info(sbi, nid, &ni); node_blk = calloc(BLOCK_SZ, 1); dev_read_block(node_blk, ni.blk_addr); @@ -284,9 +281,8 @@ int dump_node(struct f2fs_sb_info *sbi, nid_t nid) DBG(1, "nat_entry.version [0x%x]\n", ni.version); DBG(1, "nat_entry.ino [0x%x]\n", ni.ino); - if (ni.blk_addr == 0x0) { + if (ni.blk_addr == 0x0) MSG(0, "Invalid nat entry\n\n"); - } DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino)); DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid)); @@ -300,7 +296,6 @@ int dump_node(struct f2fs_sb_info *sbi, nid_t nid) } free(node_blk); - return 0; } int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) @@ -314,8 +309,7 @@ int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) type = get_sum_entry(sbi, blk_addr, &sum_entry); nid = le32_to_cpu(sum_entry.nid); - ret = get_node_info(sbi, nid, &ni); - ASSERT(ret >= 0); + get_node_info(sbi, nid, &ni); DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n"); DBG(1, "Block_addr [0x%x]\n", blk_addr); @@ -331,7 +325,8 @@ int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) node_blk = calloc(BLOCK_SZ, 1); read_node_blk: - dev_read_block(node_blk, blk_addr); + ret = dev_read_block(node_blk, blk_addr); + ASSERT(ret >= 0); ino = le32_to_cpu(node_blk->footer.ino); nid = le32_to_cpu(node_blk->footer.nid); @@ -339,7 +334,7 @@ read_node_blk: if (ino == nid) { print_node_info(node_blk); } else { - ret = get_node_info(sbi, ino, &ni); + get_node_info(sbi, ino, &ni); goto read_node_blk; } diff --git a/fsck/fsck.c b/fsck/fsck.c index 5eab522..d2781d9 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -200,8 +200,7 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, else ASSERT_MSG("nid duplicated [0x%x]\n", nid); - ret = get_node_info(sbi, nid, &ni); - ASSERT(ret >= 0); + get_node_info(sbi, nid, &ni); /* Is it reserved block? * if block addresss was 0xffff,ffff,ffff,ffff @@ -682,7 +681,7 @@ int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, fsck->chk.valid_blk_cnt++; fsck->chk.valid_node_cnt++; - ASSERT(get_node_info(sbi, x_nid, &ni) >= 0); + get_node_info(sbi, x_nid, &ni); if (f2fs_test_main_bitmap(sbi, ni.blk_addr) != 0) { ASSERT_MSG("Duplicated node block for x_attr. " diff --git a/fsck/fsck.h b/fsck/fsck.h index dcb6656..b673646 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -99,7 +99,7 @@ extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int); extern int get_sum_block(struct f2fs_sb_info *, unsigned int, struct f2fs_summary_block *); extern int get_sum_entry(struct f2fs_sb_info *, u32, struct f2fs_summary *); -extern int get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); +extern void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); extern void build_nat_area_bitmap(struct f2fs_sb_info *); extern int build_sit_area_bitmap(struct f2fs_sb_info *); extern int fsck_init(struct f2fs_sb_info *); @@ -120,7 +120,7 @@ struct dump_option { extern void sit_dump(struct f2fs_sb_info *, int, int); extern void ssa_dump(struct f2fs_sb_info *, int, int); -extern int dump_node(struct f2fs_sb_info *, nid_t); +extern void dump_node(struct f2fs_sb_info *, nid_t); extern int dump_inode_from_blkaddr(struct f2fs_sb_info *, u32); #endif /* _FSCK_H_ */ diff --git a/fsck/mount.c b/fsck/mount.c index 7ea3296..ab5f7f3 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -801,9 +801,9 @@ int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, struct f2fs_summary *s return ret; } -int get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, struct f2fs_nat_entry *raw_nat) +static void get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, + struct f2fs_nat_entry *raw_nat) { - struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct f2fs_nm_info *nm_i = NM_I(sbi); struct f2fs_nat_block *nat_block; pgoff_t block_off; @@ -811,13 +811,8 @@ int get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, struct f2fs_nat_entry *ra int seg_off, entry_off; int ret; - if ((nid / NAT_ENTRY_PER_BLOCK) > fsck->nr_nat_entries) { - DBG(0, "nid is over max nid\n"); - return -EINVAL; - } - if (lookup_nat_in_journal(sbi, nid, raw_nat) >= 0) - return 0; + return; nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); @@ -835,21 +830,17 @@ int get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, struct f2fs_nat_entry *ra ret = dev_read_block(nat_block, block_addr); ASSERT(ret >= 0); - memcpy(raw_nat, &nat_block->entries[entry_off], sizeof(struct f2fs_nat_entry)); + memcpy(raw_nat, &nat_block->entries[entry_off], + sizeof(struct f2fs_nat_entry)); free(nat_block); - - return 0; } -int get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) +void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) { struct f2fs_nat_entry raw_nat; - int ret; - - ret = get_nat_entry(sbi, nid, &raw_nat); + get_nat_entry(sbi, nid, &raw_nat); ni->nid = nid; node_info_from_raw_nat(ni, &raw_nat); - return ret; } void build_sit_entries(struct f2fs_sb_info *sbi) -- cgit v1.2.3 From 5cd7001f5dfaf1c7f275826c44dcf203d49f4cce Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 27 Aug 2014 17:06:17 -0700 Subject: fsck.f2fs: handle error cases Do sanity check first and then update metadata. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 344 +++++++++++++++++++++++++++++------------------------- fsck/fsck.h | 11 +- fsck/main.c | 40 ++----- fsck/mount.c | 3 +- include/f2fs_fs.h | 4 + 5 files changed, 205 insertions(+), 197 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index d2781d9..9ebe2be 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -80,10 +80,8 @@ static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid) struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct hard_link_node *node = NULL, *prev = NULL; - if (fsck->hard_link_list_head == NULL) { - ASSERT(0); - return -1; - } + if (fsck->hard_link_list_head == NULL) + return -EINVAL; node = fsck->hard_link_list_head; @@ -92,10 +90,8 @@ static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid) node = node->next; } - if (node == NULL || (nid != node->nid)) { - ASSERT(0); - return -1; - } + if (node == NULL || (nid != node->nid)) + return -EINVAL; /* Decrease link count */ node->links = node->links - 1; @@ -108,9 +104,7 @@ static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid) prev->next = node->next; free(node); } - return 0; - } static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, @@ -138,14 +132,16 @@ static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, le32_to_cpu(sum_entry.nid)); DBG(0, "--> node block's nid [0x%x]\n", nid); ASSERT_MSG("Invalid node seg summary\n"); + return -EINVAL; } + return 0; } else if (ret == SEG_TYPE_CUR_NODE) { /* current node segment has no ssa */ + return 0; } else { ASSERT_MSG("Invalid return value of 'get_sum_entry'"); } - - return 1; + return -EINVAL; } static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, @@ -177,114 +173,145 @@ static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, return 1; } -int fsck_chk_node_blk(struct f2fs_sb_info *sbi, - struct f2fs_inode *inode, - u32 nid, - enum FILE_TYPE ftype, - enum NODE_TYPE ntype, - u32 *blk_cnt) +static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid, + struct f2fs_node *node_blk, + enum FILE_TYPE ftype, enum NODE_TYPE ntype, + struct node_info *ni) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); - struct node_info ni; - struct f2fs_node *node_blk = NULL; - int ret = 0; + int ret; if (!IS_VALID_NID(sbi, nid)) { ASSERT_MSG("nid is not valid. [0x%x]", nid); - return 0; + return -EINVAL; } - if (ftype != F2FS_FT_ORPHAN || - f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0x0) - f2fs_clear_bit(nid, fsck->nat_area_bitmap); - else - ASSERT_MSG("nid duplicated [0x%x]\n", nid); + get_node_info(sbi, nid, ni); + if (ni->blk_addr == NEW_ADDR) { + ASSERT_MSG("nid is NEW_ADDR. [0x%x]", nid); + return -EINVAL; + } - get_node_info(sbi, nid, &ni); + if (!IS_VALID_BLK_ADDR(sbi, ni->blk_addr)) { + ASSERT_MSG("blkaddres is not valid. [0x%x]", ni->blk_addr); + return -EINVAL; + } - /* Is it reserved block? - * if block addresss was 0xffff,ffff,ffff,ffff - * it means that block was already allocated, but not stored in disk - */ - if (ni.blk_addr == NEW_ADDR) { - fsck->chk.valid_blk_cnt++; - fsck->chk.valid_node_cnt++; - if (ntype == TYPE_INODE) - fsck->chk.valid_inode_cnt++; - return 0; + if (is_valid_ssa_node_blk(sbi, nid, ni->blk_addr)) { + ASSERT_MSG("summary node block is not valid. [0x%x]", nid); + return -EINVAL; } - if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) { - ASSERT_MSG("blkaddres is not valid. [0x%x]", ni.blk_addr); - return 0; + ret = dev_read_block(node_blk, ni->blk_addr); + ASSERT(ret >= 0); + + if (ntype == TYPE_INODE && + node_blk->footer.nid != node_blk->footer.ino) { + ASSERT_MSG("nid[0x%x] footer.nid[0x%x] footer.ino[0x%x]", + nid, le32_to_cpu(node_blk->footer.nid), + le32_to_cpu(node_blk->footer.ino)); + return -EINVAL; + } + if (ntype != TYPE_INODE && + node_blk->footer.nid == node_blk->footer.ino) { + ASSERT_MSG("nid[0x%x] footer.nid[0x%x] footer.ino[0x%x]", + nid, le32_to_cpu(node_blk->footer.nid), + le32_to_cpu(node_blk->footer.ino)); + return -EINVAL; + } + + if (le32_to_cpu(node_blk->footer.nid) != nid) { + ASSERT_MSG("nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]", + nid, ni->blk_addr, + le32_to_cpu(node_blk->footer.nid)); + return -EINVAL; + } + + if (ntype == TYPE_XATTR) { + u32 flag = le32_to_cpu(node_blk->footer.flag); + + if ((flag >> OFFSET_BIT_SHIFT) != XATTR_NODE_OFFSET) { + ASSERT_MSG("xnid[0x%x] has wrong ofs:[0x%x]", + nid, flag); + return -EINVAL; + } + } + + if ((ntype == TYPE_INODE && ftype == F2FS_FT_DIR) || + (ntype == TYPE_XATTR && ftype == F2FS_FT_XATTR)) { + /* not included '.' & '..' */ + if (f2fs_test_main_bitmap(sbi, ni->blk_addr) != 0) { + ASSERT_MSG("Duplicated node blk. nid[0x%x][0x%x]\n", + nid, ni->blk_addr); + return -EINVAL; + } } - is_valid_ssa_node_blk(sbi, nid, ni.blk_addr); + /* workaround to fix later */ + if (ftype != F2FS_FT_ORPHAN || + f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) + f2fs_clear_bit(nid, fsck->nat_area_bitmap); + else + ASSERT_MSG("orphan or xattr nid is duplicated [0x%x]\n", + nid); - if (f2fs_test_sit_bitmap(sbi, ni.blk_addr) == 0) - ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", ni.blk_addr); + if (f2fs_test_sit_bitmap(sbi, ni->blk_addr) == 0) + ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", + ni->blk_addr); - if (f2fs_test_main_bitmap(sbi, ni.blk_addr) == 0) { + if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) { fsck->chk.valid_blk_cnt++; fsck->chk.valid_node_cnt++; } + return 0; +} + +int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, + u32 nid, enum FILE_TYPE ftype, enum NODE_TYPE ntype, + u32 *blk_cnt) +{ + struct node_info ni; + struct f2fs_node *node_blk = NULL; node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); ASSERT(node_blk != NULL); - ret = dev_read_block(node_blk, ni.blk_addr); - ASSERT(ret >= 0); - - if (nid != le32_to_cpu(node_blk->footer.nid)) - ASSERT_MSG("nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]", - nid, ni.blk_addr, le32_to_cpu(node_blk->footer.nid)); + if (sanity_check_nid(sbi, nid, node_blk, ftype, ntype, &ni)) + goto err; if (ntype == TYPE_INODE) { - ret = fsck_chk_inode_blk(sbi, - nid, - ftype, - node_blk, - blk_cnt, - &ni); + fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni); } else { - /* it's not inode */ - ASSERT(node_blk->footer.nid != node_blk->footer.ino); - - if (f2fs_test_main_bitmap(sbi, ni.blk_addr) != 0) - ASSERT_MSG("Duplicated node blk. nid[0x%x][0x%x]\n", - nid, ni.blk_addr); - f2fs_set_main_bitmap(sbi, ni.blk_addr); switch (ntype) { case TYPE_DIRECT_NODE: - ret = fsck_chk_dnode_blk(sbi, inode, nid, ftype, - node_blk, blk_cnt, &ni); + fsck_chk_dnode_blk(sbi, inode, nid, ftype, node_blk, + blk_cnt, &ni); break; case TYPE_INDIRECT_NODE: - ret = fsck_chk_idnode_blk(sbi, inode, ftype, node_blk, + fsck_chk_idnode_blk(sbi, inode, ftype, node_blk, blk_cnt); break; case TYPE_DOUBLE_INDIRECT_NODE: - ret = fsck_chk_didnode_blk(sbi, inode, ftype, node_blk, + fsck_chk_didnode_blk(sbi, inode, ftype, node_blk, blk_cnt); break; default: ASSERT(0); } } - ASSERT(ret >= 0); - free(node_blk); return 0; +err: + free(node_blk); + return -EINVAL; } -int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, - u32 nid, - enum FILE_TYPE ftype, - struct f2fs_node *node_blk, - u32 *blk_cnt, - struct node_info *ni) +/* start with valid nid and blkaddr */ +void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, + enum FILE_TYPE ftype, struct f2fs_node *node_blk, + u32 *blk_cnt, struct node_info *ni) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); u32 child_cnt = 0, child_files = 0; @@ -292,31 +319,13 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 i_links = le32_to_cpu(node_blk->i.i_links); u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks); unsigned int idx = 0; - int ret = 0; - - ASSERT(node_blk->footer.nid == node_blk->footer.ino); - ASSERT(le32_to_cpu(node_blk->footer.nid) == nid); + int ret; if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) fsck->chk.valid_inode_cnt++; - /* Orphan node. i_links should be 0 */ - if (ftype == F2FS_FT_ORPHAN) { - ASSERT(i_links == 0); - } else { - ASSERT(i_links > 0); - } - if (ftype == F2FS_FT_DIR) { - - /* not included '.' & '..' */ - if (f2fs_test_main_bitmap(sbi, ni->blk_addr) != 0) { - DBG(0, "Duplicated inode blk. ino[0x%x][0x%x]\n", - nid, ni->blk_addr); - ASSERT(0); - } f2fs_set_main_bitmap(sbi, ni->blk_addr); - } else { if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) { f2fs_set_main_bitmap(sbi, ni->blk_addr); @@ -326,21 +335,15 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, fsck->chk.multi_hard_link_files++; } } else { - if (i_links <= 1) { - DBG(0, "Error. Node ID [0x%x]." - " There are one more hard links." - " But i_links is [0x%x]\n", + DBG(3, "[0x%x] has hard links [0x%x]\n", nid, i_links); + if (find_and_dec_hard_link_list(sbi, nid)) { + ASSERT_MSG("[0x%x] needs more i_links=0x%x", nid, i_links); - ASSERT(0); + if (config.fix_cnt) + printf("TODO: i_links++\n"); } - - DBG(3, "ino[0x%x] has hard links [0x%x]\n", - nid, i_links); - ret = find_and_dec_hard_link_list(sbi, nid); - ASSERT(ret >= 0); - /* No need to go deep into the node */ - goto out; + return; } } @@ -358,13 +361,13 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, /* check data blocks in inode */ for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) { if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) { - *blk_cnt = *blk_cnt + 1; ret = fsck_chk_data_blk(sbi, le32_to_cpu(node_blk->i.i_addr[idx]), &child_cnt, &child_files, (i_blocks == *blk_cnt), ftype, nid, idx, ni->version); - ASSERT(ret >= 0); + if (!ret) + *blk_cnt = *blk_cnt + 1; } } @@ -380,11 +383,13 @@ int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, ASSERT(0); if (le32_to_cpu(node_blk->i.i_nid[idx]) != 0) { - *blk_cnt = *blk_cnt + 1; ret = fsck_chk_node_blk(sbi, &node_blk->i, le32_to_cpu(node_blk->i.i_nid[idx]), ftype, ntype, blk_cnt); - ASSERT(ret >= 0); + if (!ret) + *blk_cnt = *blk_cnt + 1; + else if (config.fix_cnt) + printf("TODO delete i_nid[idx] = 0;\n"); } } check: @@ -400,35 +405,46 @@ check: node_blk->i.i_name, (u32)i_blocks); if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || - (i_blocks != *blk_cnt)) { - print_node_info(node_blk); + (i_blocks != *blk_cnt)) { + if (!config.fix_cnt) + print_node_info(node_blk); + + /* node_blk, ni.blkaddr, child_cnt, *blk_cnt */ + if (config.fix_cnt) + printf("TODO fix_inode_block\n"); + else + print_node_info(node_blk); DBG(1, "blk cnt [0x%x]\n", *blk_cnt); DBG(1, "child cnt [0x%x]\n", child_cnt); } - - ASSERT(i_blocks == *blk_cnt); - if (ftype == F2FS_FT_DIR) - ASSERT(i_links == child_cnt); -out: - return 0; + if (i_blocks != *blk_cnt) + ASSERT_MSG("ino: 0x%x has i_blocks: %lu, but has %u blocks", + nid, i_blocks, *blk_cnt); + if (ftype == F2FS_FT_DIR && i_links != child_cnt) + ASSERT_MSG("ino: 0x%x has i_links: %u but real links: %u", + nid, i_links, child_cnt); + if (ftype == F2FS_FT_ORPHAN && i_links) + ASSERT_MSG("ino: 0x%x is orphan inode, but has i_links: %u", + nid, i_links); } int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt, struct node_info *ni) { - int idx; + int idx, ret; u32 child_cnt = 0, child_files = 0; for (idx = 0; idx < ADDRS_PER_BLOCK; idx++) { if (le32_to_cpu(node_blk->dn.addr[idx]) == 0x0) continue; - *blk_cnt = *blk_cnt + 1; - fsck_chk_data_blk(sbi, + ret = fsck_chk_data_blk(sbi, le32_to_cpu(node_blk->dn.addr[idx]), &child_cnt, &child_files, le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype, nid, idx, ni->version); + if (!ret) + *blk_cnt = *blk_cnt + 1; } return 0; } @@ -436,14 +452,19 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt) { + int ret; int i = 0; for (i = 0 ; i < NIDS_PER_BLOCK; i++) { if (le32_to_cpu(node_blk->in.nid[i]) == 0x0) continue; - *blk_cnt = *blk_cnt + 1; - fsck_chk_node_blk(sbi, inode, le32_to_cpu(node_blk->in.nid[i]), + ret = fsck_chk_node_blk(sbi, inode, + le32_to_cpu(node_blk->in.nid[i]), ftype, TYPE_DIRECT_NODE, blk_cnt); + if (!ret) + *blk_cnt = *blk_cnt + 1; + else if (ret == -EINVAL) + printf("delete in.nid[i] = 0;\n"); } return 0; } @@ -452,14 +473,18 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt) { int i = 0; + int ret = 0; for (i = 0; i < NIDS_PER_BLOCK; i++) { if (le32_to_cpu(node_blk->in.nid[i]) == 0x0) continue; - *blk_cnt = *blk_cnt + 1; - fsck_chk_node_blk(sbi, inode, + ret = fsck_chk_node_blk(sbi, inode, le32_to_cpu(node_blk->in.nid[i]), ftype, TYPE_INDIRECT_NODE, blk_cnt); + if (!ret) + *blk_cnt = *blk_cnt + 1; + else if (ret == -EINVAL) + printf("delete in.nid[i] = 0;\n"); } return 0; } @@ -570,7 +595,8 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr, TYPE_INODE, &blk_cnt); - ASSERT(ret >= 0); + if (ret) + printf("TODO: delete dentry\n"); i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; dentries++; @@ -618,35 +644,34 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, fsck->chk.valid_blk_cnt++; - if (ftype == F2FS_FT_DIR) { - fsck_chk_dentry_blk(sbi, blk_addr, child_cnt, + if (ftype == F2FS_FT_DIR) + return fsck_chk_dentry_blk(sbi, blk_addr, child_cnt, child_files, last_blk); - } - return 0; } -int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) +void fsck_chk_orphan_node(struct f2fs_sb_info *sbi) { - int ret = 0; u32 blk_cnt = 0; - block_t start_blk, orphan_blkaddr, i, j; struct f2fs_orphan_block *orphan_blk; struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); if (!is_set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG)) - return 0; + return; + + if (config.fix_cnt) + return; start_blk = __start_cp_addr(sbi) + 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); - orphan_blkaddr = __start_sum_addr(sbi) - 1; - orphan_blk = calloc(BLOCK_SZ, 1); for (i = 0; i < orphan_blkaddr; i++) { - dev_read_block(orphan_blk, start_blk + i); + int ret = dev_read_block(orphan_blk, start_blk + i); + + ASSERT(ret >= 0); for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { nid_t ino = le32_to_cpu(orphan_blk->ino[j]); @@ -654,47 +679,42 @@ int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) blk_cnt = 1; ret = fsck_chk_node_blk(sbi, NULL, ino, F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt); - ASSERT(ret >= 0); + if (ret == -EINVAL) + printf("TODO: nothing?\n"); } memset(orphan_blk, 0, BLOCK_SZ); } free(orphan_blk); - return 0; } -int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, - u32 x_nid, u32 *blk_cnt) +void fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, + u32 x_nid, u32 *blk_cnt) { - struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + struct f2fs_node *node_blk = NULL; struct node_info ni; if (x_nid == 0x0) - return 0; + return; - if (f2fs_test_bit(x_nid, fsck->nat_area_bitmap) != 0x0) { - f2fs_clear_bit(x_nid, fsck->nat_area_bitmap); - } else { - ASSERT_MSG("xattr_nid duplicated [0x%x]\n", x_nid); + node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); + ASSERT(node_blk != NULL); + + /* Sanity check */ + if (sanity_check_nid(sbi, x_nid, node_blk, + F2FS_FT_XATTR, TYPE_XATTR, &ni)) { + /* TODO: drop xattr node */ + printf("drop xattr node\n"); + goto out; } *blk_cnt = *blk_cnt + 1; - fsck->chk.valid_blk_cnt++; - fsck->chk.valid_node_cnt++; - - get_node_info(sbi, x_nid, &ni); - - if (f2fs_test_main_bitmap(sbi, ni.blk_addr) != 0) { - ASSERT_MSG("Duplicated node block for x_attr. " - "x_nid[0x%x] block addr[0x%x]\n", - x_nid, ni.blk_addr); - } f2fs_set_main_bitmap(sbi, ni.blk_addr); - DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid); - return 0; +out: + free(node_blk); } -int fsck_init(struct f2fs_sb_info *sbi) +void fsck_init(struct f2fs_sb_info *sbi) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct f2fs_sm_info *sm_i = SM_I(sbi); @@ -718,7 +738,7 @@ int fsck_init(struct f2fs_sb_info *sbi) build_sit_area_bitmap(sbi); tree_mark = calloc(tree_mark_size, 1); - return 0; + ASSERT(tree_mark != NULL); } int fsck_verify(struct f2fs_sb_info *sbi) diff --git a/fsck/fsck.h b/fsck/fsck.h index b673646..aecfa9a 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -59,7 +59,8 @@ enum NODE_TYPE { TYPE_INODE = 37, TYPE_DIRECT_NODE = 43, TYPE_INDIRECT_NODE = 53, - TYPE_DOUBLE_INDIRECT_NODE = 67 + TYPE_DOUBLE_INDIRECT_NODE = 67, + TYPE_XATTR = 77 }; struct hard_link_node { @@ -76,11 +77,11 @@ enum seg_type { SEG_TYPE_MAX, }; -extern int fsck_chk_xattr_blk(struct f2fs_sb_info *, u32, u32, u32 *); -extern int fsck_chk_orphan_node(struct f2fs_sb_info *); +extern void fsck_chk_xattr_blk(struct f2fs_sb_info *, u32, u32, u32 *); +extern void fsck_chk_orphan_node(struct f2fs_sb_info *); extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32, enum FILE_TYPE, enum NODE_TYPE, u32 *); -extern int fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE, +extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE, struct f2fs_node *, u32 *, struct node_info *); extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32, enum FILE_TYPE, struct f2fs_node *, u32 *, @@ -102,7 +103,7 @@ extern int get_sum_entry(struct f2fs_sb_info *, u32, struct f2fs_summary *); extern void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); extern void build_nat_area_bitmap(struct f2fs_sb_info *); extern int build_sit_area_bitmap(struct f2fs_sb_info *); -extern int fsck_init(struct f2fs_sb_info *); +extern void fsck_init(struct f2fs_sb_info *); extern int fsck_verify(struct f2fs_sb_info *); extern void fsck_free(struct f2fs_sb_info *); extern int f2fs_do_mount(struct f2fs_sb_info *); diff --git a/fsck/main.c b/fsck/main.c index 266e9b5..7e3bb49 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -131,44 +131,29 @@ void f2fs_parse_options(int argc, char *argv[]) config.device_name = argv[optind]; } -int do_fsck(struct f2fs_sb_info *sbi) +static void do_fsck(struct f2fs_sb_info *sbi) { u32 blk_cnt; - int ret; config.bug_on = 0; - ret = fsck_init(sbi); - if (ret < 0) - return ret; + fsck_init(sbi); fsck_chk_orphan_node(sbi); /* Traverse all block recursively from root inode */ blk_cnt = 1; - ret = fsck_chk_node_blk(sbi, - NULL, - sbi->root_ino_num, - F2FS_FT_DIR, - TYPE_INODE, - &blk_cnt); - if (ret < 0) - goto out1; - - ret = fsck_verify(sbi); -out1: + fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num, + F2FS_FT_DIR, TYPE_INODE, &blk_cnt); + fsck_verify(sbi); fsck_free(sbi); - return ret; } -int do_dump(struct f2fs_sb_info *sbi) +static void do_dump(struct f2fs_sb_info *sbi) { struct dump_option *opt = (struct dump_option *)config.private; - int ret; - ret = fsck_init(sbi); - if (ret < 0) - return ret; + fsck_init(sbi); if (opt->end_sit == -1) opt->end_sit = SM_I(sbi)->main_segments; @@ -182,15 +167,12 @@ int do_dump(struct f2fs_sb_info *sbi) dump_inode_from_blkaddr(sbi, opt->blk_addr); goto cleanup; } - dump_node(sbi, opt->nid); - cleanup: fsck_free(sbi); - return 0; } -int main (int argc, char **argv) +int main(int argc, char **argv) { struct f2fs_sb_info *sbi; int ret = 0; @@ -215,10 +197,10 @@ fsck_again: switch (config.func) { case FSCK: - ret = do_fsck(sbi); + do_fsck(sbi); break; case DUMP: - ret = do_dump(sbi); + do_dump(sbi); break; } @@ -248,5 +230,5 @@ retry: f2fs_finalize_device(&config); printf("\nDone.\n"); - return ret; + return 0; } diff --git a/fsck/mount.c b/fsck/mount.c index ab5f7f3..a766157 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -1020,7 +1020,8 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) struct node_info ni; ni.nid = nid + i; - if ((nid + i) == F2FS_NODE_INO(sbi) || (nid + i) == F2FS_META_INO(sbi)) { + if ((nid + i) == F2FS_NODE_INO(sbi) || + (nid + i) == F2FS_META_INO(sbi)) { ASSERT(nat_block->entries[i].block_addr != 0x0); continue; } diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index dace9aa..c3cc2aa 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -413,6 +413,9 @@ enum { OFFSET_BIT_SHIFT }; +#define XATTR_NODE_OFFSET ((((unsigned int)-1) << OFFSET_BIT_SHIFT) \ + >> OFFSET_BIT_SHIFT) + struct node_footer { __le32 nid; /* node id */ __le32 ino; /* inode nunmber */ @@ -640,6 +643,7 @@ enum FILE_TYPE { F2FS_FT_MAX, /* added for fsck */ F2FS_FT_ORPHAN, + F2FS_FT_XATTR, }; /* from f2fs/segment.h */ -- cgit v1.2.3 From 1ce70c67e3a801158adde211f0004d3ea4653067 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 27 Aug 2014 17:13:23 -0700 Subject: fsck.f2fs: cleanup mount.c Signed-off-by: Jaegeuk Kim --- fsck/mount.c | 116 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/fsck/mount.c b/fsck/mount.c index a766157..b0dd5c7 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -53,7 +53,7 @@ void print_inode_info(struct f2fs_inode *inode) for (i = 4; i < ADDRS_PER_INODE(inode); i++) { if (inode->i_addr[i] != 0x0) { - printf("i_addr[0x%x] points data block\r\t\t\t\t[0x%4x]\n", + printf("i_addr[0x%x] points data block\r\t\t[0x%4x]\n", i, inode->i_addr[i]); break; } @@ -79,9 +79,11 @@ void print_node_info(struct f2fs_node *node_block) } else { int i; u32 *dump_blk = (u32 *)node_block; - DBG(0, "Node ID [0x%x:%u] is direct node or indirect node.\n", nid, nid); + DBG(0, "Node ID [0x%x:%u] is direct node or indirect node.\n", + nid, nid); for (i = 0; i <= 10; i++) - MSG(0, "[%d]\t\t\t[0x%8x : %d]\n", i, dump_blk[i], dump_blk[i]); + MSG(0, "[%d]\t\t\t[0x%8x : %d]\n", + i, dump_blk[i], dump_blk[i]); } } @@ -211,7 +213,8 @@ int sanity_check_raw_super(struct f2fs_super_block *raw_super) return -1; } - if (F2FS_LOG_SECTORS_PER_BLOCK != le32_to_cpu(raw_super->log_sectors_per_block)) { + if (F2FS_LOG_SECTORS_PER_BLOCK != + le32_to_cpu(raw_super->log_sectors_per_block)) { return -1; } @@ -230,7 +233,7 @@ int validate_super_block(struct f2fs_sb_info *sbi, int block) return 0; free(sbi->raw_super); - MSG(0, "\tCan't find a valid F2FS filesystem in %d superblock\n", block); + MSG(0, "\tCan't find a valid F2FS superblock at 0x%x\n", block); return -EINVAL; } @@ -258,7 +261,8 @@ int init_sb_info(struct f2fs_sb_info *sbi) return 0; } -void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, unsigned long long *version) +void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, + unsigned long long *version) { void *cp_page_1, *cp_page_2; struct f2fs_checkpoint *cp_block; @@ -360,7 +364,8 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) cp_blk_no = le32_to_cpu(raw_sb->cp_blkaddr); if (cur_page == cp2) - cp_blk_no += 1 << le32_to_cpu(raw_sb->log_blocks_per_seg); + cp_blk_no += 1 << + le32_to_cpu(raw_sb->log_blocks_per_seg); /* copy sit bitmap */ for (i = 1; i < cp_blks; i++) { unsigned char *ckpt = (unsigned char *)sbi->ckpt; @@ -515,7 +520,8 @@ int read_compacted_summaries(struct f2fs_sb_info *sbi) memcpy(&curseg->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE); curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); - memcpy(&curseg->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE); + memcpy(&curseg->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE, + SUM_JOURNAL_SIZE); offset = 2 * SUM_JOURNAL_SIZE; for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { @@ -538,7 +544,8 @@ int read_compacted_summaries(struct f2fs_sb_info *sbi) s = (struct f2fs_summary *)(kaddr + offset); curseg->sum_blk->entries[j] = *s; offset += SUMMARY_SIZE; - if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE - SUM_FOOTER_SIZE) + if (offset + SUMMARY_SIZE <= + PAGE_CACHE_SIZE - SUM_FOOTER_SIZE) continue; memset(kaddr, 0, PAGE_SIZE); dev_read_block(kaddr, start++); @@ -597,18 +604,22 @@ int read_normal_summaries(struct f2fs_sb_info *sbi, int type) if (IS_DATASEG(type)) { segno = le32_to_cpu(ckpt->cur_data_segno[type]); - blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type - CURSEG_HOT_DATA]); + blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type - + CURSEG_HOT_DATA]); 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); } else { - segno = le32_to_cpu(ckpt->cur_node_segno[type - CURSEG_HOT_NODE]); - blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type - CURSEG_HOT_NODE]); + segno = le32_to_cpu(ckpt->cur_node_segno[type - + CURSEG_HOT_NODE]); + blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type - + CURSEG_HOT_NODE]); if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) - blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, type - CURSEG_HOT_NODE); + blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, + type - CURSEG_HOT_NODE); else blk_addr = GET_SUM_BLKADDR(sbi, segno); } @@ -688,7 +699,8 @@ inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) ASSERT(segno <= end_segno); } -struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, unsigned int segno) +struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, + unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno); @@ -746,7 +758,8 @@ struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi, return &sit_i->sentries[segno]; } -int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum_blk) +int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, + struct f2fs_summary_block *sum_blk) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct curseg_info *curseg; @@ -758,7 +771,8 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summ if (segno == ckpt->cur_node_segno[type]) { curseg = CURSEG_I(sbi, CURSEG_HOT_NODE + type); memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ); - return SEG_TYPE_CUR_NODE; /* current node seg was not stored */ + /* current node seg was not stored */ + return SEG_TYPE_CUR_NODE; } } @@ -767,8 +781,10 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summ curseg = CURSEG_I(sbi, type); memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ); ASSERT(!IS_SUM_NODE_SEG(sum_blk->footer)); - DBG(2, "segno [0x%x] is current data seg[0x%x]\n", segno, type); - return SEG_TYPE_CUR_DATA; /* current data seg was not stored */ + DBG(2, "segno [0x%x] is current data seg[0x%x]\n", + segno, type); + /* current data seg was not stored */ + return SEG_TYPE_CUR_DATA; } } @@ -782,7 +798,8 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summ } -int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, struct f2fs_summary *sum_entry) +int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, + struct f2fs_summary *sum_entry) { struct f2fs_summary_block *sum_blk; u32 segno, offset; @@ -795,8 +812,8 @@ int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, struct f2fs_summary *s ret = get_sum_block(sbi, segno, sum_blk); - memcpy(sum_entry, &(sum_blk->entries[offset]), sizeof(struct f2fs_summary)); - + memcpy(sum_entry, &(sum_blk->entries[offset]), + sizeof(struct f2fs_summary)); free(sum_blk); return ret; } @@ -955,12 +972,14 @@ int build_sit_area_bitmap(struct f2fs_sb_info *sbi) fsck->chk.sit_valid_blocks = sum_vblocks; fsck->chk.sit_free_segs = free_segs; - DBG(1, "Blocks [0x%x : %d] Free Segs [0x%x : %d]\n\n", sum_vblocks, sum_vblocks, + DBG(1, "Blocks [0x%x : %d] Free Segs [0x%x : %d]\n\n", + sum_vblocks, sum_vblocks, free_segs, free_segs); return 0; } -int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_entry *raw_nat) +int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, + struct f2fs_nat_entry *raw_nat) { struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); struct f2fs_summary_block *sum = curseg->sum_blk; @@ -968,7 +987,8 @@ int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_ent for (i = 0; i < nats_in_cursum(sum); i++) { if (le32_to_cpu(nid_in_journal(sum, i)) == nid) { - memcpy(raw_nat, &nat_in_journal(sum, i), sizeof(struct f2fs_nat_entry)); + memcpy(raw_nat, &nat_in_journal(sum, i), + sizeof(struct f2fs_nat_entry)); DBG(3, "==> Found nid [0x%x] in nat cache\n", nid); return i; } @@ -994,7 +1014,8 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); /* Alloc & build nat entry bitmap */ - nr_nat_blks = (le32_to_cpu(raw_sb->segment_count_nat) / 2) << sbi->log_blocks_per_seg; + nr_nat_blks = (le32_to_cpu(raw_sb->segment_count_nat) / 2) << + sbi->log_blocks_per_seg; fsck->nr_nat_entries = nr_nat_blks * NAT_ENTRY_PER_BLOCK; fsck->nat_area_bitmap_sz = (fsck->nr_nat_entries + 7) / 8; @@ -1005,8 +1026,8 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) seg_off = block_off >> sbi->log_blocks_per_seg; block_addr = (pgoff_t)(nm_i->nat_blkaddr + - (seg_off << sbi->log_blocks_per_seg << 1) + - (block_off & ((1 << sbi->log_blocks_per_seg) - 1))); + (seg_off << sbi->log_blocks_per_seg << 1) + + (block_off & ((1 << sbi->log_blocks_per_seg) - 1))); if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) block_addr += sbi->blocks_per_seg; @@ -1026,34 +1047,35 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) continue; } - if (lookup_nat_in_journal(sbi, nid + i, &raw_nat) >= 0) { + if (lookup_nat_in_journal(sbi, nid + i, + &raw_nat) >= 0) { node_info_from_raw_nat(&ni, &raw_nat); if (ni.blk_addr != 0x0) { - f2fs_set_bit(nid + i, fsck->nat_area_bitmap); + f2fs_set_bit(nid + i, + fsck->nat_area_bitmap); fsck->chk.valid_nat_entry_cnt++; - DBG(3, "nid[0x%x] in nat cache\n", nid + i); + DBG(3, "nid[0x%x] in nat cache\n", + nid + i); } } else { - node_info_from_raw_nat(&ni, &nat_block->entries[i]); - if (ni.blk_addr != 0) { - ASSERT(nid + i != 0x0); - - DBG(3, "nid[0x%8x] in nat entry [0x%16x] [0x%8x]\n", - nid + i, - ni.blk_addr, - ni.ino); - - f2fs_set_bit(nid + i, fsck->nat_area_bitmap); - fsck->chk.valid_nat_entry_cnt++; - } + node_info_from_raw_nat(&ni, + &nat_block->entries[i]); + if (ni.blk_addr == 0) + continue; + ASSERT(nid + i != 0x0); + + DBG(3, "nid[0x%8x] addr[0x%16x] ino[0x%8x]\n", + nid + i, ni.blk_addr, ni.ino); + f2fs_set_bit(nid + i, fsck->nat_area_bitmap); + fsck->chk.valid_nat_entry_cnt++; } } } free(nat_block); DBG(1, "valid nat entries (block_addr != 0x0) [0x%8x : %u]\n", - fsck->chk.valid_nat_entry_cnt, fsck->chk.valid_nat_entry_cnt); - + fsck->chk.valid_nat_entry_cnt, + fsck->chk.valid_nat_entry_cnt); } int f2fs_do_mount(struct f2fs_sb_info *sbi) @@ -1085,9 +1107,11 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi) print_ckpt_info(sbi); 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->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->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; -- cgit v1.2.3 From 48863d422ee4c9f01f0dfc9cff12240f5e3883e2 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 27 Aug 2014 17:15:55 -0700 Subject: fsck.f2fs: give a chance to recover sit entries This patch skips initial verfication on SIT entries, which checks the number of valid blocks from its bitmap. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 2 +- fsck/fsck.h | 2 +- fsck/mount.c | 39 +++++++++++++-------------------------- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 9ebe2be..49d9ccc 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -634,7 +634,7 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, is_valid_ssa_data_blk(sbi, blk_addr, parent_nid, idx_in_node, ver); if (f2fs_test_sit_bitmap(sbi, blk_addr) == 0) - ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]\n", blk_addr); + ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", blk_addr); if (f2fs_test_main_bitmap(sbi, blk_addr) != 0) ASSERT_MSG("Duplicated data [0x%x]. pnid[0x%x] idx[0x%x]", diff --git a/fsck/fsck.h b/fsck/fsck.h index aecfa9a..a3f03fd 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -102,7 +102,7 @@ extern int get_sum_block(struct f2fs_sb_info *, unsigned int, extern int get_sum_entry(struct f2fs_sb_info *, u32, struct f2fs_summary *); extern void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); extern void build_nat_area_bitmap(struct f2fs_sb_info *); -extern int build_sit_area_bitmap(struct f2fs_sb_info *); +extern void build_sit_area_bitmap(struct f2fs_sb_info *); extern void fsck_init(struct f2fs_sb_info *); extern int fsck_verify(struct f2fs_sb_info *); extern void fsck_free(struct f2fs_sb_info *); diff --git a/fsck/mount.c b/fsck/mount.c index b0dd5c7..4880848 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -726,18 +726,22 @@ void check_block_count(struct f2fs_sb_info *sbi, int valid_blocks = 0; unsigned int i; - /* check segment usage */ - ASSERT(GET_SIT_VBLOCKS(raw_sit) <= sbi->blocks_per_seg); + if (GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg) + ASSERT_MSG("Invalid SIT vblocks: segno=0x%x, %u", + segno, GET_SIT_VBLOCKS(raw_sit)); /* check boundary of a given segment number */ - ASSERT(segno <= end_segno); + if (segno > end_segno) + ASSERT_MSG("Invalid SEGNO: 0x%x", segno); /* check bitmap with valid block count */ - for (i = 0; i < sbi->blocks_per_seg; i++) - if (f2fs_test_bit(i, (char *)raw_sit->valid_map)) - valid_blocks++; - ASSERT(GET_SIT_VBLOCKS(raw_sit) == valid_blocks); + for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++) + valid_blocks += get_bits_in_byte(raw_sit->valid_map[i]); + + if (GET_SIT_VBLOCKS(raw_sit) != valid_blocks) + ASSERT_MSG("Wrong SIT valid blocks: segno=0x%x, %u vs. %u", + segno, GET_SIT_VBLOCKS(raw_sit), valid_blocks); } void seg_info_from_raw_sit(struct seg_entry *se, @@ -918,18 +922,14 @@ int build_segment_manager(struct f2fs_sb_info *sbi) return 0; } -int build_sit_area_bitmap(struct f2fs_sb_info *sbi) +void build_sit_area_bitmap(struct f2fs_sb_info *sbi) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct f2fs_sm_info *sm_i = SM_I(sbi); unsigned int segno = 0; - int j = 0; char *ptr = NULL; - u32 sum_vblocks = 0; u32 free_segs = 0; - u32 vblocks = 0; - struct seg_entry *se; fsck->sit_area_bitmap_sz = sm_i->main_segments * SIT_VBLOCK_MAP_SIZE; @@ -938,20 +938,13 @@ int build_sit_area_bitmap(struct f2fs_sb_info *sbi) ASSERT(fsck->sit_area_bitmap_sz == fsck->main_area_bitmap_sz); - for (segno = 0; segno < sm_i->main_segments; segno++) { + for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) { se = get_seg_entry(sbi, segno); memcpy(ptr, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); ptr += SIT_VBLOCK_MAP_SIZE; - vblocks = 0; - for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++) { - vblocks += get_bits_in_byte(se->cur_valid_map[j]); - } - ASSERT(vblocks == se->valid_blocks); - 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 || @@ -962,20 +955,16 @@ int build_sit_area_bitmap(struct f2fs_sb_info *sbi) } else { free_segs++; } - } else { - ASSERT(se->valid_blocks <= 512); sum_vblocks += se->valid_blocks; } } - fsck->chk.sit_valid_blocks = sum_vblocks; fsck->chk.sit_free_segs = free_segs; DBG(1, "Blocks [0x%x : %d] Free Segs [0x%x : %d]\n\n", sum_vblocks, sum_vblocks, free_segs, free_segs); - return 0; } int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, @@ -1003,14 +992,12 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) struct f2fs_nm_info *nm_i = NM_I(sbi); struct f2fs_nat_block *nat_block; u32 nid, nr_nat_blks; - pgoff_t block_off; pgoff_t block_addr; int seg_off; int ret; unsigned int i; - nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); /* Alloc & build nat entry bitmap */ -- cgit v1.2.3 From 634dfb15526b3a70a6454e6573693a11f8a94cea Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 29 Aug 2014 11:46:25 -0700 Subject: fsck.f2fs: fix inode block inconsistency This patch is to fix inode block inconsistency such as iblocks and ilinks. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 61 +++++++++++++++++++++++++++++++++---------------------- include/f2fs_fs.h | 1 + lib/libf2fs_io.c | 5 +++++ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 49d9ccc..17cf29b 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -319,6 +319,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, u32 i_links = le32_to_cpu(node_blk->i.i_links); u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks); unsigned int idx = 0; + int need_fix = 0; int ret; if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) @@ -339,8 +340,11 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, if (find_and_dec_hard_link_list(sbi, nid)) { ASSERT_MSG("[0x%x] needs more i_links=0x%x", nid, i_links); - if (config.fix_cnt) - printf("TODO: i_links++\n"); + if (config.fix_cnt) { + node_blk->i.i_links = + cpu_to_le32(i_links + 1); + need_fix = 1; + } } /* No need to go deep into the node */ return; @@ -366,8 +370,12 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, &child_cnt, &child_files, (i_blocks == *blk_cnt), ftype, nid, idx, ni->version); - if (!ret) + if (!ret) { *blk_cnt = *blk_cnt + 1; + } else if (config.fix_cnt) { + node_blk->i.i_addr[idx] = 0; + need_fix = 1; + } } } @@ -386,10 +394,12 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, ret = fsck_chk_node_blk(sbi, &node_blk->i, le32_to_cpu(node_blk->i.i_nid[idx]), ftype, ntype, blk_cnt); - if (!ret) + if (!ret) { *blk_cnt = *blk_cnt + 1; - else if (config.fix_cnt) - printf("TODO delete i_nid[idx] = 0;\n"); + } else if (config.fix_cnt) { + node_blk->i.i_nid[idx] = 0; + need_fix = 1; + } } } check: @@ -404,28 +414,31 @@ check: le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, (u32)i_blocks); - if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || - (i_blocks != *blk_cnt)) { - if (!config.fix_cnt) - print_node_info(node_blk); - - /* node_blk, ni.blkaddr, child_cnt, *blk_cnt */ - if (config.fix_cnt) - printf("TODO fix_inode_block\n"); - else - print_node_info(node_blk); - DBG(1, "blk cnt [0x%x]\n", *blk_cnt); - DBG(1, "child cnt [0x%x]\n", child_cnt); - } - if (i_blocks != *blk_cnt) + + if (i_blocks != *blk_cnt) { ASSERT_MSG("ino: 0x%x has i_blocks: %lu, but has %u blocks", - nid, i_blocks, *blk_cnt); - if (ftype == F2FS_FT_DIR && i_links != child_cnt) + nid, i_blocks, *blk_cnt); + if (config.fix_cnt) { + node_blk->i.i_blocks = cpu_to_le64(*blk_cnt); + need_fix = 1; + } + } + if (ftype == F2FS_FT_DIR && i_links != child_cnt) { ASSERT_MSG("ino: 0x%x has i_links: %u but real links: %u", - nid, i_links, child_cnt); + nid, i_links, child_cnt); + if (config.fix_cnt) { + node_blk->i.i_links = cpu_to_le32(child_cnt); + need_fix = 1; + } + } + if (ftype == F2FS_FT_ORPHAN && i_links) ASSERT_MSG("ino: 0x%x is orphan inode, but has i_links: %u", - nid, i_links); + nid, i_links); + if (need_fix) { + ret = dev_write_block(node_blk, ni->blk_addr); + ASSERT(ret >= 0); + } } int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index c3cc2aa..3b75bff 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -676,6 +676,7 @@ extern void f2fs_finalize_device(struct f2fs_configuration *); extern int dev_read(void *, __u64, size_t); extern int dev_write(void *, __u64, size_t); +extern int dev_write_block(void *, __u64); extern int dev_write_dump(void *, __u64, size_t); /* All bytes in the buffer must be 0 use dev_fill(). */ extern int dev_fill(void *, __u64, size_t); diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index d5ced53..0c89ee4 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -46,6 +46,11 @@ int dev_write(void *buf, __u64 offset, size_t len) return 0; } +int dev_write_block(void *buf, __u64 blk_addr) +{ + return dev_write(buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE); +} + int dev_write_dump(void *buf, __u64 offset, size_t len) { if (lseek64(config.dump_fd, (off64_t)offset, SEEK_SET) < 0) -- cgit v1.2.3 From 48ffea7ba8669f372cb372f870a12e6faf02bc36 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 28 Aug 2014 10:27:17 -0700 Subject: fsck.f2fs: add fixing messeages Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 9 +++++++++ include/f2fs_fs.h | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/fsck/fsck.c b/fsck/fsck.c index 17cf29b..00f5b27 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -344,6 +344,9 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, node_blk->i.i_links = cpu_to_le32(i_links + 1); need_fix = 1; + FIX_MSG("File: 0x%x " + "i_links= 0x%x -> 0x%x", + nid, i_links, i_links + 1); } } /* No need to go deep into the node */ @@ -375,6 +378,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, } else if (config.fix_cnt) { node_blk->i.i_addr[idx] = 0; need_fix = 1; + FIX_MSG("[0x%x] i_addr[%d] = 0", nid, idx); } } } @@ -399,6 +403,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, } else if (config.fix_cnt) { node_blk->i.i_nid[idx] = 0; need_fix = 1; + FIX_MSG("[0x%x] i_nid[%d] = 0", nid, idx); } } } @@ -421,6 +426,8 @@ check: if (config.fix_cnt) { node_blk->i.i_blocks = cpu_to_le64(*blk_cnt); need_fix = 1; + FIX_MSG("[0x%x] i_blocks=0x%lx -> 0x%x", + nid, i_blocks, *blk_cnt); } } if (ftype == F2FS_FT_DIR && i_links != child_cnt) { @@ -429,6 +436,8 @@ check: if (config.fix_cnt) { node_blk->i.i_links = cpu_to_le32(child_cnt); need_fix = 1; + FIX_MSG("Dir: 0x%x i_links= 0x%x -> 0x%x", + nid, i_links, child_cnt); } } diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 3b75bff..7242690 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -54,6 +54,12 @@ typedef unsigned long pgoff_t; /* * Debugging interfaces */ +#define FIX_MSG(fmt, ...) \ + do { \ + printf("[FIX] (%s:%4d) ", __func__, __LINE__); \ + printf(" --> "fmt"\n", ##__VA_ARGS__); \ + } while (0) + #define ASSERT_MSG(fmt, ...) \ do { \ printf("[ASSERT] (%s:%4d) ", __func__, __LINE__); \ -- cgit v1.2.3 From 32edfeaac782dd7c9583eacf098e5794df341f07 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 29 Aug 2014 11:26:57 -0700 Subject: fsck.f2fs: remove dentry if its inode block is corrupted Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 00f5b27..2a47b4c 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -617,8 +617,21 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr, TYPE_INODE, &blk_cnt); - if (ret) - printf("TODO: delete dentry\n"); + if (ret && config.fix_cnt) { + int j; + int slots = (name_len + F2FS_SLOT_LEN - 1) / + F2FS_SLOT_LEN; + for (j = 0; j < slots; j++) + clear_bit(i + j, + (unsigned long *)de_blk->dentry_bitmap); + FIX_MSG("Unlink [0x%x] - %s len[0x%x], type[0x%x]", + le32_to_cpu(de_blk->dentry[i].ino), + name, name_len, + de_blk->dentry[i].file_type); + i += slots; + free(name); + continue; + } i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; dentries++; -- cgit v1.2.3 From a89223b2206d8dc70e7ff56d6db4449563d6b38f Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 28 Aug 2014 10:50:51 -0700 Subject: fsck.f2fs: corrupted orphan inode will be removed Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 2a47b4c..914dcb9 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -712,10 +712,8 @@ void fsck_chk_orphan_node(struct f2fs_sb_info *sbi) nid_t ino = le32_to_cpu(orphan_blk->ino[j]); DBG(1, "[%3d] ino [0x%x]\n", i, ino); blk_cnt = 1; - ret = fsck_chk_node_blk(sbi, NULL, ino, + fsck_chk_node_blk(sbi, NULL, ino, F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt); - if (ret == -EINVAL) - printf("TODO: nothing?\n"); } memset(orphan_blk, 0, BLOCK_SZ); } -- cgit v1.2.3 From 1bc74e1eede28d039ca080c4530033bd473b63e3 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 28 Aug 2014 10:56:14 -0700 Subject: fsck.f2fs: remove corrupted xattr block Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 65 ++++++++++++++++++++++++++++++++++--------------------------- fsck/fsck.h | 1 - 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 914dcb9..53a64b7 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -266,6 +266,34 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid, return 0; } +static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, + u32 x_nid, u32 *blk_cnt) +{ + struct f2fs_node *node_blk = NULL; + struct node_info ni; + int ret = 0; + + if (x_nid == 0x0) + return 0; + + node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); + ASSERT(node_blk != NULL); + + /* Sanity check */ + if (sanity_check_nid(sbi, x_nid, node_blk, + F2FS_FT_XATTR, TYPE_XATTR, &ni)) { + ret = -EINVAL; + goto out; + } + + *blk_cnt = *blk_cnt + 1; + f2fs_set_main_bitmap(sbi, ni.blk_addr); + DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid); +out: + free(node_blk); + return ret; +} + int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, u32 nid, enum FILE_TYPE ftype, enum NODE_TYPE ntype, u32 *blk_cnt) @@ -354,8 +382,14 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, } } - fsck_chk_xattr_blk(sbi, nid, - le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt); + if (fsck_chk_xattr_blk(sbi, nid, + le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt) && + config.fix_cnt) { + node_blk->i.i_xattr_nid = 0; + need_fix = 1; + FIX_MSG("Remove xattr block: 0x%x, x_nid = 0x%x", + nid, le32_to_cpu(node_blk->i.i_xattr_nid)); + } if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV || ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK) @@ -720,33 +754,6 @@ void fsck_chk_orphan_node(struct f2fs_sb_info *sbi) free(orphan_blk); } -void fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, - u32 x_nid, u32 *blk_cnt) -{ - struct f2fs_node *node_blk = NULL; - struct node_info ni; - - if (x_nid == 0x0) - return; - - node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); - ASSERT(node_blk != NULL); - - /* Sanity check */ - if (sanity_check_nid(sbi, x_nid, node_blk, - F2FS_FT_XATTR, TYPE_XATTR, &ni)) { - /* TODO: drop xattr node */ - printf("drop xattr node\n"); - goto out; - } - - *blk_cnt = *blk_cnt + 1; - f2fs_set_main_bitmap(sbi, ni.blk_addr); - DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid); -out: - free(node_blk); -} - void fsck_init(struct f2fs_sb_info *sbi) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); diff --git a/fsck/fsck.h b/fsck/fsck.h index a3f03fd..85cc931 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -77,7 +77,6 @@ enum seg_type { SEG_TYPE_MAX, }; -extern void fsck_chk_xattr_blk(struct f2fs_sb_info *, u32, u32, u32 *); extern void fsck_chk_orphan_node(struct f2fs_sb_info *); extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32, enum FILE_TYPE, enum NODE_TYPE, u32 *); -- cgit v1.2.3 From 1dc1edfbcbaa20f876f7958e2c7423ebef48a9da Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 28 Aug 2014 13:49:04 -0700 Subject: fsck.f2fs: handle correctly segment summary entries Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 58 ++++++++++++++++-------------- fsck/mount.c | 113 ++++++++++++++++++++++++++--------------------------------- 2 files changed, 80 insertions(+), 91 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 53a64b7..0a76c19 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -114,34 +114,28 @@ static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_summary sum_entry; ret = get_sum_entry(sbi, blk_addr, &sum_entry); - ASSERT(ret >= 0); - if (ret == SEG_TYPE_DATA || ret == SEG_TYPE_CUR_DATA) { - ASSERT_MSG("Summary footer is not for node segment\n"); - } else if (ret == SEG_TYPE_NODE) { - if (le32_to_cpu(sum_entry.nid) != nid) { - DBG(0, "nid [0x%x]\n", nid); - DBG(0, "target blk_addr [0x%x]\n", blk_addr); - DBG(0, "summary blk_addr [0x%x]\n", + if (ret != SEG_TYPE_NODE && ret != SEG_TYPE_CUR_NODE) { + ASSERT_MSG("Summary footer is not for node segment"); + return -EINVAL; + } + + if (le32_to_cpu(sum_entry.nid) != nid) { + DBG(0, "nid [0x%x]\n", nid); + DBG(0, "target blk_addr [0x%x]\n", blk_addr); + DBG(0, "summary blk_addr [0x%x]\n", GET_SUM_BLKADDR(sbi, - GET_SEGNO(sbi, blk_addr))); - DBG(0, "seg no / offset [0x%x / 0x%x]\n", + GET_SEGNO(sbi, blk_addr))); + DBG(0, "seg no / offset [0x%x / 0x%x]\n", GET_SEGNO(sbi, blk_addr), - OFFSET_IN_SEG(sbi, blk_addr)); - DBG(0, "summary_entry.nid [0x%x]\n", + OFFSET_IN_SEG(sbi, blk_addr)); + DBG(0, "summary_entry.nid [0x%x]\n", le32_to_cpu(sum_entry.nid)); - DBG(0, "--> node block's nid [0x%x]\n", nid); - ASSERT_MSG("Invalid node seg summary\n"); - return -EINVAL; - } - return 0; - } else if (ret == SEG_TYPE_CUR_NODE) { - /* current node segment has no ssa */ - return 0; - } else { - ASSERT_MSG("Invalid return value of 'get_sum_entry'"); + DBG(0, "--> node block's nid [0x%x]\n", nid); + ASSERT_MSG("Invalid node seg summary\n"); + return -EINVAL; } - return -EINVAL; + return 0; } static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, @@ -151,7 +145,11 @@ static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, struct f2fs_summary sum_entry; ret = get_sum_entry(sbi, blk_addr, &sum_entry); - ASSERT(ret == SEG_TYPE_DATA || ret == SEG_TYPE_CUR_DATA); + + if (ret != SEG_TYPE_DATA && ret != SEG_TYPE_CUR_DATA) { + ASSERT_MSG("Summary footer is not for data segment"); + return -EINVAL; + } if (le32_to_cpu(sum_entry.nid) != parent_nid || sum_entry.version != version || @@ -169,8 +167,9 @@ static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, DBG(0, "Target data block addr [0x%x]\n", blk_addr); ASSERT_MSG("Invalid data seg summary\n"); + return -EINVAL; } - return 1; + return 0; } static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid, @@ -697,10 +696,15 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, if (!IS_VALID_BLK_ADDR(sbi, blk_addr)) { ASSERT_MSG("blkaddres is not valid. [0x%x]", blk_addr); - return 0; + return -EINVAL; } - is_valid_ssa_data_blk(sbi, blk_addr, parent_nid, idx_in_node, ver); + if (is_valid_ssa_data_blk(sbi, blk_addr, parent_nid, + idx_in_node, ver)) { + ASSERT_MSG("summary data block is not valid. [0x%x]", + parent_nid); + return -EINVAL; + } if (f2fs_test_sit_bitmap(sbi, blk_addr) == 0) ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", blk_addr); diff --git a/fsck/mount.c b/fsck/mount.c index 4880848..fb5b261 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -495,26 +495,35 @@ int build_sit_info(struct f2fs_sb_info *sbi) void reset_curseg(struct f2fs_sb_info *sbi, int type) { struct curseg_info *curseg = CURSEG_I(sbi, type); + struct summary_footer *sum_footer; curseg->segno = curseg->next_segno; curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno); curseg->next_blkoff = 0; curseg->next_segno = NULL_SEGNO; + sum_footer = &(curseg->sum_blk->footer); + memset(sum_footer, 0, sizeof(struct summary_footer)); + if (IS_DATASEG(type)) + SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA); + if (IS_NODESEG(type)) + SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE); } -int read_compacted_summaries(struct f2fs_sb_info *sbi) +static void read_compacted_summaries(struct f2fs_sb_info *sbi) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct curseg_info *curseg; + unsigned int i, j, offset; block_t start; char *kaddr; - unsigned int i, j, offset; + int ret; start = start_sum_block(sbi); kaddr = (char *)malloc(PAGE_SIZE); - dev_read_block(kaddr, start++); + ret = dev_read_block(kaddr, start++); + ASSERT(ret >= 0); curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); memcpy(&curseg->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE); @@ -548,52 +557,40 @@ int read_compacted_summaries(struct f2fs_sb_info *sbi) PAGE_CACHE_SIZE - SUM_FOOTER_SIZE) continue; memset(kaddr, 0, PAGE_SIZE); - dev_read_block(kaddr, start++); + ret = dev_read_block(kaddr, start++); + ASSERT(ret >= 0); offset = 0; } } - free(kaddr); - return 0; } -int restore_node_summary(struct f2fs_sb_info *sbi, +static void restore_node_summary(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum_blk) { struct f2fs_node *node_blk; struct f2fs_summary *sum_entry; - void *page; block_t addr; unsigned int i; + int ret; - page = malloc(PAGE_SIZE); - if (!page) - return -ENOMEM; + node_blk = malloc(F2FS_BLKSIZE); + ASSERT(node_blk); /* scan the node segment */ addr = START_BLOCK(sbi, segno); sum_entry = &sum_blk->entries[0]; for (i = 0; i < sbi->blocks_per_seg; i++, sum_entry++) { - if (dev_read_block(page, addr)) - goto out; - - node_blk = (struct f2fs_node *)page; + ret = dev_read_block(node_blk, addr); + ASSERT(ret >= 0); sum_entry->nid = node_blk->footer.nid; - /* do not change original value */ -#if 0 - sum_entry->version = 0; - sum_entry->ofs_in_node = 0; -#endif addr++; - } -out: - free(page); - return 0; + free(node_blk); } -int read_normal_summaries(struct f2fs_sb_info *sbi, int type) +static void read_normal_summaries(struct f2fs_sb_info *sbi, int type) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct f2fs_summary_block *sum_blk; @@ -601,6 +598,7 @@ int read_normal_summaries(struct f2fs_sb_info *sbi, int type) unsigned short blk_off; unsigned int segno = 0; block_t blk_addr = 0; + int ret; if (IS_DATASEG(type)) { segno = le32_to_cpu(ckpt->cur_data_segno[type]); @@ -625,26 +623,11 @@ int read_normal_summaries(struct f2fs_sb_info *sbi, int type) } sum_blk = (struct f2fs_summary_block *)malloc(PAGE_SIZE); - dev_read_block(sum_blk, blk_addr); - - if (IS_NODESEG(type)) { - if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) { - struct f2fs_summary *sum_entry = &sum_blk->entries[0]; - unsigned int i; - for (i = 0; i < sbi->blocks_per_seg; i++, sum_entry++) { - /* do not change original value */ -#if 0 - sum_entry->version = 0; - sum_entry->ofs_in_node = 0; -#endif - } - } else { - if (restore_node_summary(sbi, segno, sum_blk)) { - free(sum_blk); - return -EINVAL; - } - } - } + ret = dev_read_block(sum_blk, blk_addr); + ASSERT(ret >= 0); + + if (IS_NODESEG(type) && !is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) + restore_node_summary(sbi, segno, sum_blk); curseg = CURSEG_I(sbi, type); memcpy(curseg->sum_blk, sum_blk, PAGE_CACHE_SIZE); @@ -653,44 +636,38 @@ int read_normal_summaries(struct f2fs_sb_info *sbi, int type) curseg->alloc_type = ckpt->alloc_type[type]; curseg->next_blkoff = blk_off; free(sum_blk); - - return 0; } -int restore_curseg_summaries(struct f2fs_sb_info *sbi) +static void restore_curseg_summaries(struct f2fs_sb_info *sbi) { int type = CURSEG_HOT_DATA; if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) { - if (read_compacted_summaries(sbi)) - return -EINVAL; + read_compacted_summaries(sbi); type = CURSEG_HOT_NODE; } - for (; type <= CURSEG_COLD_NODE; type++) { - if (read_normal_summaries(sbi, type)) - return -EINVAL; - } - return 0; + for (; type <= CURSEG_COLD_NODE; type++) + read_normal_summaries(sbi, type); } -int build_curseg(struct f2fs_sb_info *sbi) +static void build_curseg(struct f2fs_sb_info *sbi) { struct curseg_info *array; int i; array = malloc(sizeof(*array) * NR_CURSEG_TYPE); + ASSERT(array); SM_I(sbi)->curseg_array = array; for (i = 0; i < NR_CURSEG_TYPE; i++) { array[i].sum_blk = malloc(PAGE_CACHE_SIZE); - if (!array[i].sum_blk) - return -ENOMEM; + ASSERT(array[i].sum_blk); array[i].segno = NULL_SEGNO; array[i].next_blkoff = 0; } - return restore_curseg_summaries(sbi); + restore_curseg_summaries(sbi); } inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) @@ -774,8 +751,13 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, for (type = 0; type < NR_CURSEG_NODE_TYPE; type++) { if (segno == ckpt->cur_node_segno[type]) { curseg = CURSEG_I(sbi, CURSEG_HOT_NODE + type); + if (!IS_SUM_NODE_SEG(curseg->sum_blk->footer)) { + ASSERT_MSG("segno [0x%x] indicates a data " + "segment, but should be node", + segno); + return -EINVAL; + } memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ); - /* current node seg was not stored */ return SEG_TYPE_CUR_NODE; } } @@ -783,11 +765,15 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, for (type = 0; type < NR_CURSEG_DATA_TYPE; type++) { if (segno == ckpt->cur_data_segno[type]) { curseg = CURSEG_I(sbi, type); - memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ); - ASSERT(!IS_SUM_NODE_SEG(sum_blk->footer)); + if (IS_SUM_NODE_SEG(curseg->sum_blk->footer)) { + ASSERT_MSG("segno [0x%x] indicates a node " + "segment, but should be data", + segno); + return -EINVAL; + } DBG(2, "segno [0x%x] is current data seg[0x%x]\n", segno, type); - /* current data seg was not stored */ + memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ); return SEG_TYPE_CUR_DATA; } } @@ -815,7 +801,6 @@ int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, sum_blk = calloc(BLOCK_SZ, 1); ret = get_sum_block(sbi, segno, sum_blk); - memcpy(sum_entry, &(sum_blk->entries[offset]), sizeof(struct f2fs_summary)); free(sum_blk); -- cgit v1.2.3 From b700e313b4ad390fce7f610c51d0bb2dc52661bb Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 28 Aug 2014 14:55:07 -0700 Subject: fsck.f2fs: fix checkpoint - fix nat entries - fix sit entries - fix checkpoint Signed-off-by: Jaegeuk Kim --- fsck/f2fs.h | 1 + fsck/fsck.c | 84 ++++++++++++++++++++++++++++++++++ fsck/fsck.h | 3 ++ fsck/mount.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 227 insertions(+), 5 deletions(-) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index 2adffd8..8c31981 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -126,6 +126,7 @@ struct f2fs_sb_info { struct f2fs_nm_info *nm_info; struct f2fs_sm_info *sm_info; struct f2fs_checkpoint *ckpt; + int cur_cp; struct list_head orphan_inode_list; unsigned int n_orphans; diff --git a/fsck/fsck.c b/fsck/fsck.c index 0a76c19..8df489d 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -785,6 +785,64 @@ void fsck_init(struct f2fs_sb_info *sbi) ASSERT(tree_mark != NULL); } +static void fix_nat_entries(struct f2fs_sb_info *sbi) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + int i; + + for (i = 0; i < fsck->nr_nat_entries; i++) + if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) + nullify_nat_entry(sbi, i); +} + +static void fix_checkpoint(struct f2fs_sb_info *sbi) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + struct f2fs_super_block *raw_sb = sbi->raw_super; + struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi); + unsigned long long cp_blk_no; + int i, ret; + u_int32_t crc = 0; + + ckp->ckpt_flags = cpu_to_le32(CP_UMOUNT_FLAG); + ckp->cp_pack_total_block_count = + cpu_to_le32(8 + le32_to_cpu(raw_sb->cp_payload)); + ckp->cp_pack_start_sum = cpu_to_le32(1 + + le32_to_cpu(raw_sb->cp_payload)); + + ckp->free_segment_count = cpu_to_le32(fsck->chk.free_segs); + ckp->valid_block_count = cpu_to_le32(fsck->chk.valid_blk_cnt); + ckp->valid_node_count = cpu_to_le32(fsck->chk.valid_node_cnt); + ckp->valid_inode_count = cpu_to_le32(fsck->chk.valid_inode_cnt); + + crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET); + *((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) = + cpu_to_le32(crc); + + cp_blk_no = le32_to_cpu(raw_sb->cp_blkaddr); + if (sbi->cur_cp == 2) + cp_blk_no += 1 << le32_to_cpu(raw_sb->log_blocks_per_seg); + + ret = dev_write_block(ckp, cp_blk_no++); + ASSERT(ret >= 0); + + for (i = 0; i < le32_to_cpu(raw_sb->cp_payload); i++) { + ret = dev_write_block(((unsigned char *)ckp) + i * F2FS_BLKSIZE, + cp_blk_no++); + ASSERT(ret >= 0); + } + + for (i = 0; i < NO_CHECK_TYPE; i++) { + struct curseg_info *curseg = CURSEG_I(sbi, i); + + ret = dev_write_block(curseg->sum_blk, cp_blk_no++); + ASSERT(ret >= 0); + } + + ret = dev_write_block(ckp, cp_blk_no++); + ASSERT(ret >= 0); +} + int fsck_verify(struct f2fs_sb_info *sbi) { unsigned int i = 0; @@ -875,6 +933,32 @@ int fsck_verify(struct f2fs_sb_info *sbi) ret = EXIT_ERR_CODE; config.bug_on = 1; } + + printf("[FSCK] free segment_count matched with CP "); + if (le32_to_cpu(F2FS_CKPT(sbi)->free_segment_count) == + fsck->chk.sit_free_segs) { + printf(" [Ok..] [0x%x]\n", fsck->chk.sit_free_segs); + } else { + printf(" [Fail] [0x%x]\n", fsck->chk.sit_free_segs); + ret = EXIT_ERR_CODE; + config.bug_on = 1; + } + + printf("[FSCK] other corrupted bugs "); + if (config.bug_on == 0) { + printf(" [Ok..]\n"); + } else { + printf(" [Fail]\n"); + ret = EXIT_ERR_CODE; + config.bug_on = 1; + } + + /* fix global metadata */ + if (config.bug_on && config.fix_cnt) { + fix_nat_entries(sbi); + rewrite_sit_area_bitmap(sbi); + fix_checkpoint(sbi); + } return ret; } diff --git a/fsck/fsck.h b/fsck/fsck.h index 85cc931..64b9984 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -31,6 +31,7 @@ struct f2fs_fsck { u32 multi_hard_link_files; u64 sit_valid_blocks; u32 sit_free_segs; + u32 free_segs; } chk; struct hard_link_node *hard_link_list_head; @@ -100,6 +101,8 @@ extern int get_sum_block(struct f2fs_sb_info *, unsigned int, struct f2fs_summary_block *); extern int get_sum_entry(struct f2fs_sb_info *, u32, struct f2fs_summary *); extern void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); +extern void nullify_nat_entry(struct f2fs_sb_info *, u32); +extern void rewrite_sit_area_bitmap(struct f2fs_sb_info *); extern void build_nat_area_bitmap(struct f2fs_sb_info *); extern void build_sit_area_bitmap(struct f2fs_sb_info *); extern void fsck_init(struct f2fs_sb_info *); diff --git a/fsck/mount.c b/fsck/mount.c index fb5b261..a41320f 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -326,6 +326,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) unsigned long long cp1_version = 0, cp2_version = 0; unsigned long long cp_start_blk_no; unsigned int cp_blks = 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); + int ret; sbi->ckpt = malloc(cp_blks * blk_size); if (!sbi->ckpt) @@ -342,14 +343,19 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version); if (cp1 && cp2) { - if (ver_after(cp2_version, cp1_version)) + if (ver_after(cp2_version, cp1_version)) { cur_page = cp2; - else + sbi->cur_cp = 2; + } else { cur_page = cp1; + sbi->cur_cp = 1; + } } else if (cp1) { cur_page = cp1; + sbi->cur_cp = 1; } else if (cp2) { cur_page = cp2; + sbi->cur_cp = 2; } else { free(cp1); free(cp2); @@ -369,7 +375,8 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) /* copy sit bitmap */ for (i = 1; i < cp_blks; i++) { unsigned char *ckpt = (unsigned char *)sbi->ckpt; - dev_read_block(cur_page, cp_blk_no + i); + ret = dev_read_block(cur_page, cp_blk_no + i); + ASSERT(ret >= 0); memcpy(ckpt + i * blk_size, cur_page, blk_size); } } @@ -496,6 +503,7 @@ void reset_curseg(struct f2fs_sb_info *sbi, int type) { struct curseg_info *curseg = CURSEG_I(sbi, type); struct summary_footer *sum_footer; + struct seg_entry *se; curseg->segno = curseg->next_segno; curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno); @@ -508,6 +516,8 @@ void reset_curseg(struct f2fs_sb_info *sbi, int type) SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA); if (IS_NODESEG(type)) SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE); + se = get_seg_entry(sbi, curseg->segno); + se->type = type; } static void read_compacted_summaries(struct f2fs_sb_info *sbi) @@ -676,13 +686,14 @@ inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) ASSERT(segno <= end_segno); } -struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, +static struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno); block_t blk_addr = sit_i->sit_base_addr + offset; struct f2fs_sit_block *sit_blk = calloc(BLOCK_SZ, 1); + int ret; check_seg_range(sbi, segno); @@ -690,11 +701,28 @@ struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, if (f2fs_test_bit(offset, sit_i->sit_bitmap)) blk_addr += sit_i->sit_blocks; - dev_read_block(sit_blk, blk_addr); + ret = dev_read_block(sit_blk, blk_addr); + ASSERT(ret >= 0); return sit_blk; } +void rewrite_current_sit_page(struct f2fs_sb_info *sbi, + unsigned int segno, struct f2fs_sit_block *sit_blk) +{ + struct sit_info *sit_i = SIT_I(sbi); + unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno); + block_t blk_addr = sit_i->sit_base_addr + offset; + int ret; + + /* calculate sit block address */ + if (f2fs_test_bit(offset, sit_i->sit_bitmap)) + blk_addr += sit_i->sit_blocks; + + ret = dev_write_block(sit_blk, blk_addr); + ASSERT(ret >= 0); +} + void check_block_count(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_sit_entry *raw_sit) { @@ -719,6 +747,10 @@ void check_block_count(struct f2fs_sb_info *sbi, if (GET_SIT_VBLOCKS(raw_sit) != valid_blocks) ASSERT_MSG("Wrong SIT valid blocks: segno=0x%x, %u vs. %u", segno, GET_SIT_VBLOCKS(raw_sit), valid_blocks); + + if (GET_SIT_TYPE(raw_sit) >= NO_CHECK_TYPE) + ASSERT_MSG("Wrong SIT type: segno=0x%x, %u", + segno, GET_SIT_TYPE(raw_sit)); } void seg_info_from_raw_sit(struct seg_entry *se, @@ -952,6 +984,62 @@ void build_sit_area_bitmap(struct f2fs_sb_info *sbi) free_segs, free_segs); } +void rewrite_sit_area_bitmap(struct f2fs_sb_info *sbi) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); + struct sit_info *sit_i = SIT_I(sbi); + unsigned int segno = 0; + struct f2fs_summary_block *sum = curseg->sum_blk; + char *ptr = NULL; + + /* remove sit journal */ + sum->n_sits = 0; + + fsck->chk.free_segs = 0; + + ptr = fsck->main_area_bitmap; + + for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) { + struct f2fs_sit_block *sit_blk; + struct f2fs_sit_entry *sit; + struct seg_entry *se; + u16 valid_blocks = 0; + u16 type; + int i; + + sit_blk = get_current_sit_page(sbi, segno); + sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)]; + memcpy(sit->valid_map, ptr, SIT_VBLOCK_MAP_SIZE); + + /* update valid block count */ + for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++) + valid_blocks += get_bits_in_byte(sit->valid_map[i]); + + se = get_seg_entry(sbi, segno); + type = se->type; + if (type >= NO_CHECK_TYPE) { + ASSERT(valid_blocks); + type = 0; + } + sit->vblocks = cpu_to_le16((type << SIT_VBLOCKS_SHIFT) | + valid_blocks); + rewrite_current_sit_page(sbi, segno, sit_blk); + free(sit_blk); + + if (valid_blocks == 0 && + 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) + fsck->chk.free_segs++; + + ptr += SIT_VBLOCK_MAP_SIZE; + } +} + int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_entry *raw_nat) { @@ -970,6 +1058,51 @@ int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, return -1; } +void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid) +{ + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct f2fs_nat_block *nat_block; + pgoff_t block_off; + pgoff_t block_addr; + int seg_off, entry_off; + int ret; + int i = 0; + + /* check in journal */ + for (i = 0; i < nats_in_cursum(sum); i++) { + if (le32_to_cpu(nid_in_journal(sum, i)) == nid) { + memset(&nat_in_journal(sum, i), 0, + sizeof(struct f2fs_nat_entry)); + FIX_MSG("Remove nid [0x%x] in nat journal\n", nid); + return; + } + } + nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); + + block_off = nid / NAT_ENTRY_PER_BLOCK; + entry_off = nid % NAT_ENTRY_PER_BLOCK; + + seg_off = block_off >> sbi->log_blocks_per_seg; + block_addr = (pgoff_t)(nm_i->nat_blkaddr + + (seg_off << sbi->log_blocks_per_seg << 1) + + (block_off & ((1 << sbi->log_blocks_per_seg) - 1))); + + if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) + block_addr += sbi->blocks_per_seg; + + ret = dev_read_block(nat_block, block_addr); + ASSERT(ret >= 0); + + memset(&nat_block->entries[entry_off], 0, + sizeof(struct f2fs_nat_entry)); + + ret = dev_write_block(nat_block, block_addr); + ASSERT(ret >= 0); + free(nat_block); +} + void build_nat_area_bitmap(struct f2fs_sb_info *sbi) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); @@ -984,6 +1117,7 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) unsigned int i; nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); + ASSERT(nat_block); /* Alloc & build nat entry bitmap */ nr_nat_blks = (le32_to_cpu(raw_sb->segment_count_nat) / 2) << -- cgit v1.2.3 From a6b2870ddb760ab2e2f662db0c09f220d02c6d9e Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 28 Aug 2014 16:55:45 -0700 Subject: fsck.f2fs: check next block is free or not If block allocation is made to the next block offset, we should drop that block. Signed-off-by: Jaegeuk Kim --- fsck/f2fs.h | 19 +++++++++++++++++-- fsck/fsck.c | 27 +++++++++++++++++++++++++++ fsck/mount.c | 46 +++++++++++++++++++++------------------------- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index 8c31981..f674ede 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -266,10 +266,15 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi) #define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \ (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg) -#define FREE_I_START_SEGNO(sbi) GET_SEGNO_FROM_SEG0(sbi, SM_I(sbi)->main_blkaddr) +#define GET_BLKOFF_FROM_SEG0(sbi, blk_addr) \ + (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & (sbi->blocks_per_seg - 1)) + +#define FREE_I_START_SEGNO(sbi) \ + GET_SEGNO_FROM_SEG0(sbi, SM_I(sbi)->main_blkaddr) #define GET_R2L_SEGNO(sbi, segno) (segno + FREE_I_START_SEGNO(sbi)) -#define START_BLOCK(sbi, segno) (SM_I(sbi)->main_blkaddr + (segno << sbi->log_blocks_per_seg)) +#define START_BLOCK(sbi, segno) (SM_I(sbi)->main_blkaddr + \ + (segno << sbi->log_blocks_per_seg)) static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type) { @@ -311,6 +316,8 @@ static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid) static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr) { + int i; + if (addr >= F2FS_RAW_SUPER(sbi)->block_count || addr < SM_I(sbi)->main_blkaddr) { DBG(0, "block addr [0x%x]\n", addr); @@ -318,6 +325,14 @@ static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr) ASSERT(addr >= SM_I(sbi)->main_blkaddr); return 0; } + + for (i = 0; i < NO_CHECK_TYPE; i++) { + struct curseg_info *curseg = CURSEG_I(sbi, i); + + if (START_BLOCK(sbi, curseg->segno) + + curseg->next_blkoff == addr) + return 0; + } return 1; } diff --git a/fsck/fsck.c b/fsck/fsck.c index 8df489d..560b541 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -843,6 +843,24 @@ static void fix_checkpoint(struct f2fs_sb_info *sbi) ASSERT(ret >= 0); } +int check_curseg_offset(struct f2fs_sb_info *sbi) +{ + int i; + + for (i = 0; i < NO_CHECK_TYPE; i++) { + struct curseg_info *curseg = CURSEG_I(sbi, i); + struct seg_entry *se; + + se = get_seg_entry(sbi, curseg->segno); + if (f2fs_test_bit(curseg->next_blkoff, + (const char *)se->cur_valid_map) == 1) { + ASSERT_MSG("Next block offset is not free, type:%d", i); + return -EINVAL; + } + } + return 0; +} + int fsck_verify(struct f2fs_sb_info *sbi) { unsigned int i = 0; @@ -944,6 +962,15 @@ int fsck_verify(struct f2fs_sb_info *sbi) config.bug_on = 1; } + printf("[FSCK] next block offset is free "); + if (check_curseg_offset(sbi) == 0) { + printf(" [Ok..]\n"); + } else { + printf(" [Fail]\n"); + ret = EXIT_ERR_CODE; + config.bug_on = 1; + } + printf("[FSCK] other corrupted bugs "); if (config.bug_on == 0) { printf(" [Ok..]\n"); diff --git a/fsck/mount.c b/fsck/mount.c index a41320f..2bbd3c5 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -505,11 +505,6 @@ void reset_curseg(struct f2fs_sb_info *sbi, int type) struct summary_footer *sum_footer; struct seg_entry *se; - curseg->segno = curseg->next_segno; - curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno); - curseg->next_blkoff = 0; - curseg->next_segno = NULL_SEGNO; - sum_footer = &(curseg->sum_blk->footer); memset(sum_footer, 0, sizeof(struct summary_footer)); if (IS_DATASEG(type)) @@ -522,7 +517,6 @@ void reset_curseg(struct f2fs_sb_info *sbi, int type) static void read_compacted_summaries(struct f2fs_sb_info *sbi) { - struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct curseg_info *curseg; unsigned int i, j, offset; block_t start; @@ -545,18 +539,14 @@ static void read_compacted_summaries(struct f2fs_sb_info *sbi) offset = 2 * SUM_JOURNAL_SIZE; for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { unsigned short blk_off; - unsigned int segno; + struct curseg_info *curseg = CURSEG_I(sbi, i); - curseg = CURSEG_I(sbi, i); - segno = le32_to_cpu(ckpt->cur_data_segno[i]); - blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]); - curseg->next_segno = segno; reset_curseg(sbi, i); - curseg->alloc_type = ckpt->alloc_type[i]; - curseg->next_blkoff = blk_off; if (curseg->alloc_type == SSR) blk_off = sbi->blocks_per_seg; + else + blk_off = curseg->next_blkoff; for (j = 0; j < blk_off; j++) { struct f2fs_summary *s; @@ -605,16 +595,12 @@ static void read_normal_summaries(struct f2fs_sb_info *sbi, int type) struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct f2fs_summary_block *sum_blk; struct curseg_info *curseg; - unsigned short blk_off; unsigned int segno = 0; block_t blk_addr = 0; int ret; if (IS_DATASEG(type)) { segno = le32_to_cpu(ckpt->cur_data_segno[type]); - blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type - - CURSEG_HOT_DATA]); - if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type); else @@ -622,9 +608,6 @@ static void read_normal_summaries(struct f2fs_sb_info *sbi, int type) } else { segno = le32_to_cpu(ckpt->cur_node_segno[type - CURSEG_HOT_NODE]); - blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type - - CURSEG_HOT_NODE]); - if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, type - CURSEG_HOT_NODE); @@ -641,10 +624,7 @@ static void read_normal_summaries(struct f2fs_sb_info *sbi, int type) curseg = CURSEG_I(sbi, type); memcpy(curseg->sum_blk, sum_blk, PAGE_CACHE_SIZE); - curseg->next_segno = segno; reset_curseg(sbi, type); - curseg->alloc_type = ckpt->alloc_type[type]; - curseg->next_blkoff = blk_off; free(sum_blk); } @@ -663,7 +643,10 @@ static void restore_curseg_summaries(struct f2fs_sb_info *sbi) static void build_curseg(struct f2fs_sb_info *sbi) { + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct curseg_info *array; + unsigned short blk_off; + unsigned int segno; int i; array = malloc(sizeof(*array) * NR_CURSEG_TYPE); @@ -674,8 +657,21 @@ static void build_curseg(struct f2fs_sb_info *sbi) for (i = 0; i < NR_CURSEG_TYPE; i++) { array[i].sum_blk = malloc(PAGE_CACHE_SIZE); ASSERT(array[i].sum_blk); - array[i].segno = NULL_SEGNO; - array[i].next_blkoff = 0; + if (i <= CURSEG_COLD_DATA) { + blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]); + segno = le32_to_cpu(ckpt->cur_data_segno[i]); + } + if (i > CURSEG_COLD_DATA) { + blk_off = le16_to_cpu(ckpt->cur_node_blkoff[i - + CURSEG_HOT_NODE]); + segno = le32_to_cpu(ckpt->cur_node_segno[i - + CURSEG_HOT_NODE]); + } + array[i].segno = segno; + array[i].zone = GET_ZONENO_FROM_SEGNO(sbi, segno); + array[i].next_segno = NULL_SEGNO; + array[i].next_blkoff = blk_off; + array[i].alloc_type = ckpt->alloc_type[i]; } restore_curseg_summaries(sbi); } -- cgit v1.2.3 From 7d96d138a3788f9b951849ae2910e77a59dd9535 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 29 Aug 2014 17:15:09 -0700 Subject: fsck.f2fs: remove list.h Just use list_head only. Signed-off-by: Jaegeuk Kim --- fsck/f2fs.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index f674ede..edb1480 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -26,7 +26,6 @@ #include #include -#include #include #define EXIT_ERR_CODE (-1) @@ -34,6 +33,10 @@ typecheck(unsigned long long, b) && \ ((long long)((a) - (b)) > 0)) +struct list_head { + struct list_head *next, *prev; +}; + enum { NAT_BITMAP, SIT_BITMAP -- cgit v1.2.3 From a6a7ac8e9db8f834bdf517394b90f6503c412b9f Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 2 Sep 2014 10:52:56 -0700 Subject: fsck.f2fs: avoid build warnings Signed-off-by: Jaegeuk Kim --- fsck/dump.c | 4 ++-- fsck/fsck.c | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index 54f9a52..4bb906f 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -140,8 +140,8 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype, { struct node_info ni; struct f2fs_node *node_blk; - u32 idx, skip = 0; - int i; + u32 skip = 0; + u32 i, idx; switch (ntype) { case TYPE_DIRECT_NODE: diff --git a/fsck/fsck.c b/fsck/fsck.c index 560b541..3fd9784 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -454,12 +454,13 @@ check: (u32)i_blocks); if (i_blocks != *blk_cnt) { - ASSERT_MSG("ino: 0x%x has i_blocks: %lu, but has %u blocks", + ASSERT_MSG("ino: 0x%x has i_blocks: %08"PRIx64", " + "but has %u blocks", nid, i_blocks, *blk_cnt); if (config.fix_cnt) { node_blk->i.i_blocks = cpu_to_le64(*blk_cnt); need_fix = 1; - FIX_MSG("[0x%x] i_blocks=0x%lx -> 0x%x", + FIX_MSG("[0x%x] i_blocks=0x%08"PRIx64" -> 0x%x", nid, i_blocks, *blk_cnt); } } @@ -788,7 +789,7 @@ void fsck_init(struct f2fs_sb_info *sbi) static void fix_nat_entries(struct f2fs_sb_info *sbi) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); - int i; + u32 i; for (i = 0; i < fsck->nr_nat_entries; i++) if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) @@ -801,7 +802,8 @@ static void fix_checkpoint(struct f2fs_sb_info *sbi) struct f2fs_super_block *raw_sb = sbi->raw_super; struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi); unsigned long long cp_blk_no; - int i, ret; + u32 i; + int ret; u_int32_t crc = 0; ckp->ckpt_flags = cpu_to_le32(CP_UMOUNT_FLAG); -- cgit v1.2.3 From 7eb6c5a03b78d8673030e89ce15345d69d5e5777 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 2 Sep 2014 18:07:35 -0700 Subject: fsck.f2fs: add auto_fix feature This patch adds an auto_fix feature which fixes inconsistency of f2fs images. E.g., With this option, -a, fsck.f2fs tries to fix inconsistency only if its valid checkpoint has CP_FSCK_FLAG, written by previous bug_on cases. So, normally it does fix nothing, so that there is no performance regression. But, if a sort of corruption was reported by the f2fs module, this tries to fix potential corrupted partition. Signed-off-by: Jaegeuk Kim --- fsck/main.c | 26 ++++++++++++++++---------- fsck/mount.c | 14 +++++++++++++- include/f2fs_fs.h | 2 ++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/fsck/main.c b/fsck/main.c index 7e3bb49..e20eac2 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -40,23 +40,27 @@ void f2fs_parse_options(int argc, char *argv[]) char *prog = basename(argv[0]); if (!strcmp("fsck.f2fs", prog)) { - const char *option_string = "d:tf"; + const char *option_string = "ad:ft"; config.func = FSCK; while ((option = getopt(argc, argv, option_string)) != EOF) { switch (option) { + case 'a': + config.auto_fix = 1; + MSG(0, "Info: Fix the reported corruption.\n"); + break; case 'd': config.dbg_lv = atoi(optarg); MSG(0, "Info: Debug level = %d\n", config.dbg_lv); break; - case 't': - config.dbg_lv = -1; - break; case 'f': config.fix_on = 1; MSG(0, "Info: Force to fix corruption\n"); break; + case 't': + config.dbg_lv = -1; + break; default: MSG(0, "\tError: Unknown option %c\n", option); fsck_usage(); @@ -135,8 +139,6 @@ static void do_fsck(struct f2fs_sb_info *sbi) { u32 blk_cnt; - config.bug_on = 0; - fsck_init(sbi); fsck_chk_orphan_node(sbi); @@ -192,7 +194,12 @@ fsck_again: gfsck.sbi.fsck = &gfsck; sbi = &gfsck.sbi; - if (f2fs_do_mount(sbi) < 0) + ret = f2fs_do_mount(sbi); + if (ret == 1) { + free(sbi->ckpt); + free(sbi->raw_super); + goto out; + } else if (ret < 0) return -1; switch (config.func) { @@ -205,9 +212,9 @@ fsck_again: } f2fs_do_umount(sbi); - +out: if (config.func == FSCK && config.bug_on) { - if (config.fix_on == 0) { + if (config.fix_on == 0 && !config.auto_fix) { char ans[255] = {0}; retry: printf("Do you want to fix this partition? [Y/N] "); @@ -226,7 +233,6 @@ retry: if (config.fix_cnt > 0 && config.fix_cnt < 4) goto fsck_again; } - f2fs_finalize_device(&config); printf("\nDone.\n"); diff --git a/fsck/mount.c b/fsck/mount.c index 2bbd3c5..5a12bb1 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -1183,6 +1183,7 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi) int f2fs_do_mount(struct f2fs_sb_info *sbi) { int ret; + sbi->active_logs = NR_CURSEG_TYPE; ret = validate_super_block(sbi, 0); if (ret) { @@ -1208,6 +1209,17 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi) print_ckpt_info(sbi); + if (config.auto_fix) { + u32 flag = le32_to_cpu(sbi->ckpt->ckpt_flags); + + if (flag & CP_FSCK_FLAG) + config.fix_cnt = 1; + else + return 1; + } + + config.bug_on = 0; + 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); @@ -1227,7 +1239,7 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi) return -1; } - return ret; + return 0; } void f2fs_do_umount(struct f2fs_sb_info *sbi) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 7242690..6467791 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -185,6 +185,7 @@ struct f2fs_configuration { int fix_on; int fix_cnt; int bug_on; + int auto_fix; } __attribute__((packed)); #ifdef CONFIG_64BIT @@ -290,6 +291,7 @@ struct f2fs_super_block { /* * For checkpoint */ +#define CP_FSCK_FLAG 0x00000010 #define CP_ERROR_FLAG 0x00000008 #define CP_COMPACT_SUM_FLAG 0x00000004 #define CP_ORPHAN_PRESENT_FLAG 0x00000002 -- cgit v1.2.3 From cfeb015e887db6edbd13ad41597d82f1e565fc33 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 3 Sep 2014 19:41:44 -0700 Subject: f2fs: rearrange options to remove redundant check This patch summarizes the usage of options. -a : auto_fix, fix corruption, only if f2fs reported some potential errors -f : force, fix corruption entire partition None : prompt, if fsck.f2fs detets any corruption Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 18 +++++++++--------- fsck/main.c | 17 +++++++++-------- fsck/mount.c | 2 +- include/f2fs_fs.h | 1 - 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 3fd9784..d0819c4 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -367,7 +367,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, if (find_and_dec_hard_link_list(sbi, nid)) { ASSERT_MSG("[0x%x] needs more i_links=0x%x", nid, i_links); - if (config.fix_cnt) { + if (config.fix_on) { node_blk->i.i_links = cpu_to_le32(i_links + 1); need_fix = 1; @@ -383,7 +383,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, if (fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt) && - config.fix_cnt) { + config.fix_on) { node_blk->i.i_xattr_nid = 0; need_fix = 1; FIX_MSG("Remove xattr block: 0x%x, x_nid = 0x%x", @@ -408,7 +408,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, ftype, nid, idx, ni->version); if (!ret) { *blk_cnt = *blk_cnt + 1; - } else if (config.fix_cnt) { + } else if (config.fix_on) { node_blk->i.i_addr[idx] = 0; need_fix = 1; FIX_MSG("[0x%x] i_addr[%d] = 0", nid, idx); @@ -433,7 +433,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, ftype, ntype, blk_cnt); if (!ret) { *blk_cnt = *blk_cnt + 1; - } else if (config.fix_cnt) { + } else if (config.fix_on) { node_blk->i.i_nid[idx] = 0; need_fix = 1; FIX_MSG("[0x%x] i_nid[%d] = 0", nid, idx); @@ -457,7 +457,7 @@ check: ASSERT_MSG("ino: 0x%x has i_blocks: %08"PRIx64", " "but has %u blocks", nid, i_blocks, *blk_cnt); - if (config.fix_cnt) { + if (config.fix_on) { node_blk->i.i_blocks = cpu_to_le64(*blk_cnt); need_fix = 1; FIX_MSG("[0x%x] i_blocks=0x%08"PRIx64" -> 0x%x", @@ -467,7 +467,7 @@ check: if (ftype == F2FS_FT_DIR && i_links != child_cnt) { ASSERT_MSG("ino: 0x%x has i_links: %u but real links: %u", nid, i_links, child_cnt); - if (config.fix_cnt) { + if (config.fix_on) { node_blk->i.i_links = cpu_to_le32(child_cnt); need_fix = 1; FIX_MSG("Dir: 0x%x i_links= 0x%x -> 0x%x", @@ -651,7 +651,7 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr, TYPE_INODE, &blk_cnt); - if (ret && config.fix_cnt) { + if (ret && config.fix_on) { int j; int slots = (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; @@ -734,7 +734,7 @@ void fsck_chk_orphan_node(struct f2fs_sb_info *sbi) if (!is_set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG)) return; - if (config.fix_cnt) + if (config.fix_on) return; start_blk = __start_cp_addr(sbi) + 1 + @@ -983,7 +983,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) } /* fix global metadata */ - if (config.bug_on && config.fix_cnt) { + if (config.bug_on && config.fix_on) { fix_nat_entries(sbi); rewrite_sit_area_bitmap(sbi); fix_checkpoint(sbi); diff --git a/fsck/main.c b/fsck/main.c index e20eac2..2af3daf 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -17,7 +17,10 @@ void fsck_usage() { MSG(0, "\nUsage: fsck.f2fs [options] device\n"); MSG(0, "[options]:\n"); + MSG(0, " -a check/fix potential corruption, reported by f2fs\n"); MSG(0, " -d debug level [default:0]\n"); + MSG(0, " -f check/fix entire partition\n"); + MSG(0, " -t show directory tree [-d -1]\n"); exit(1); } @@ -214,24 +217,22 @@ fsck_again: f2fs_do_umount(sbi); out: if (config.func == FSCK && config.bug_on) { - if (config.fix_on == 0 && !config.auto_fix) { + if (config.fix_on == 0 && config.auto_fix == 0) { char ans[255] = {0}; retry: printf("Do you want to fix this partition? [Y/N] "); ret = scanf("%s", ans); ASSERT(ret >= 0); if (!strcasecmp(ans, "y")) - config.fix_cnt++; + config.fix_on = 1; else if (!strcasecmp(ans, "n")) - config.fix_cnt = 0; + config.fix_on = 0; else goto retry; - } else { - config.fix_cnt++; + + if (config.fix_on) + goto fsck_again; } - /* avoid infinite trials */ - if (config.fix_cnt > 0 && config.fix_cnt < 4) - goto fsck_again; } f2fs_finalize_device(&config); diff --git a/fsck/mount.c b/fsck/mount.c index 5a12bb1..415f977 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -1213,7 +1213,7 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi) u32 flag = le32_to_cpu(sbi->ckpt->ckpt_flags); if (flag & CP_FSCK_FLAG) - config.fix_cnt = 1; + config.fix_on = 1; else return 1; } diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 6467791..6367e05 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -183,7 +183,6 @@ struct f2fs_configuration { int func; void *private; int fix_on; - int fix_cnt; int bug_on; int auto_fix; } __attribute__((packed)); -- cgit v1.2.3 From d834ae7ec2b4dd3cf606f4bb047e2ea11e19fedf Mon Sep 17 00:00:00 2001 From: dhacker29 Date: Thu, 9 Oct 2014 08:32:04 -0500 Subject: f2fs-tools: add support for building for android Change-Id: I11a6197c8beb0a1a430ce37f55ce1bddec0ab584 --- Android.mk | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ fsck/f2fs.h | 4 +++ fsck/fsck_f2fs_main.c | 21 ++++++++++++++ fsck/main.c | 6 ++++ include/f2fs_fs.h | 8 ++++++ include/f2fs_version.h | 4 +++ lib/libf2fs.c | 6 ++++ lib/libf2fs_io.c | 4 +++ mkfs/f2fs_format.c | 42 ++++++++++++++++++++++++++++ mkfs/f2fs_format_main.c | 10 +++++++ mkfs/f2fs_format_utils.c | 4 +++ mkfs/f2fs_format_utils.h | 4 +++ mkfs/main.c | 21 ++++++++++++++ tools/f2fstat.c | 4 +++ tools/f2fstat_main.c | 21 ++++++++++++++ tools/fibmap.c | 4 +++ tools/fibmap_main.c | 21 ++++++++++++++ 17 files changed, 255 insertions(+) create mode 100644 Android.mk create mode 100644 fsck/fsck_f2fs_main.c create mode 100644 include/f2fs_version.h create mode 100644 mkfs/main.c create mode 100644 tools/f2fstat_main.c create mode 100644 tools/fibmap_main.c diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..406df2c --- /dev/null +++ b/Android.mk @@ -0,0 +1,71 @@ +LOCAL_PATH:= $(call my-dir) + +LOCAL_CFLAGS := -DANDROID + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := mkfs/f2fs_format.c mkfs/f2fs_format_main.c mkfs/f2fs_format_utils.c lib/libf2fs.c lib/libf2fs_io.c +LOCAL_MODULE := libmake_f2fs +LOCAL_MODULE_TAGS := optional +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := mkfs/main.c +LOCAL_MODULE := mkfs.f2fs +LOCAL_MODULE_TAGS := optional +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_STATIC_LIBRARIES := libmake_f2fs libcutils liblog libc +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := fsck/main.c fsck/fsck.c fsck/dump.c fsck/mount.c lib/libf2fs.c lib/libf2fs_io.c +LOCAL_MODULE := libfsck_f2fs +LOCAL_MODULE_TAGS := optional +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := fsck/fsck_f2fs_main.c +LOCAL_MODULE := fsck.f2fs +LOCAL_MODULE_TAGS := optional +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_STATIC_LIBRARIES := libfsck_f2fs libcutils liblog libc +include $(BUILD_EXECUTABLE) + +SYMLINKS := $(addprefix $(TARGET_OUT)/bin/,dump.f2fs) +$(SYMLINKS): + @echo "Symlink: $@ -> /system/bin/fsck.f2fs" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf ../bin/fsck.f2fs $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS) + +ALL_MODULES.$(LOCAL_MODULE).INSTALLED := \ + $(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(SYMLINKS) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := tools/fibmap.c +LOCAL_MODULE := libfibmap_f2fs +LOCAL_MODULE_TAGS := optional +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := tools/fibmap_main.c +LOCAL_MODULE := fibmap.f2fs +LOCAL_MODULE_TAGS := optional +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_STATIC_LIBRARIES := libfibmap_f2fs libcutils liblog libc +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := tools/f2fstat.c +LOCAL_MODULE := libf2fstat_f2fs +LOCAL_MODULE_TAGS := optional +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := tools/f2fstat_main.c +LOCAL_MODULE := f2fstat +LOCAL_MODULE_TAGS := optional +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_STATIC_LIBRARIES := libf2fstat_f2fs libcutils liblog libc +include $(BUILD_EXECUTABLE) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index edb1480..ef045e0 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -26,7 +26,11 @@ #include #include +#ifndef ANDROID #include +#else +#include "include/f2fs_fs.h" +#endif #define EXIT_ERR_CODE (-1) #define ver_after(a, b) (typecheck(unsigned long long, a) && \ diff --git a/fsck/fsck_f2fs_main.c b/fsck/fsck_f2fs_main.c new file mode 100644 index 0000000..ca09916 --- /dev/null +++ b/fsck/fsck_f2fs_main.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +extern int fsck_f2fs_main(int argc, char **argv); + +int main(int argc, char **argv) { + return fsck_f2fs_main(argc, argv); +} diff --git a/fsck/main.c b/fsck/main.c index 2af3daf..d9c0e77 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -177,7 +177,11 @@ cleanup: fsck_free(sbi); } +#ifndef ANDROID int main(int argc, char **argv) +#else +int fsck_f2fs_main(int argc, char **argv) +#endif { struct f2fs_sb_info *sbi; int ret = 0; @@ -186,8 +190,10 @@ int main(int argc, char **argv) f2fs_parse_options(argc, argv); +#ifndef ANDROID if (f2fs_dev_is_umounted(&config) < 0) return -1; +#endif /* Get device */ if (f2fs_get_device_info(&config) < 0) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 6367e05..8b744aa 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -15,6 +15,10 @@ #ifdef HAVE_CONFIG_H #include +#else +#ifdef ANDROID +#include "include/f2fs_version.h" +#endif #endif typedef u_int64_t u64; @@ -142,7 +146,9 @@ typedef unsigned long pgoff_t; snprintf(buf, len, #member) /* these are defined in kernel */ +#ifndef PAGE_SIZE #define PAGE_SIZE 4096 +#endif #define PAGE_CACHE_SIZE 4096 #define BITS_PER_BYTE 8 #define F2FS_SUPER_MAGIC 0xF2F52010 /* F2FS Magic Number */ @@ -677,7 +683,9 @@ extern u_int32_t f2fs_cal_crc32(u_int32_t, void *, int); extern int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len); extern void f2fs_init_configuration(struct f2fs_configuration *); +#ifndef ANDROID extern int f2fs_dev_is_umounted(struct f2fs_configuration *); +#endif extern int f2fs_get_device_info(struct f2fs_configuration *); extern void f2fs_finalize_device(struct f2fs_configuration *); diff --git a/include/f2fs_version.h b/include/f2fs_version.h new file mode 100644 index 0000000..9a10fb8 --- /dev/null +++ b/include/f2fs_version.h @@ -0,0 +1,4 @@ +#define F2FS_MAJOR_VERSION 1 +#define F2FS_MINOR_VERSION 4 +#define F2FS_TOOLS_VERSION "1.4.0" +#define F2FS_TOOLS_DATE "2014-09-18" diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 01ef4e9..651138e 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -21,7 +21,11 @@ #include #include +#ifndef ANDROID #include +#else +#include "include/f2fs_fs.h" +#endif void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf) { @@ -363,6 +367,7 @@ void f2fs_init_configuration(struct f2fs_configuration *c) c->trim = 1; } +#ifndef ANDROID static int is_mounted(const char *mpt, const char *device) { FILE *file = NULL; @@ -417,6 +422,7 @@ int f2fs_dev_is_umounted(struct f2fs_configuration *c) } return 0; } +#endif int f2fs_get_device_info(struct f2fs_configuration *c) { diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index 0c89ee4..7cd71de 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -21,7 +21,11 @@ #include #include +#ifndef ANDROID #include +#else +#include "include/f2fs_fs.h" +#endif struct f2fs_configuration config; diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index e300731..e09baf5 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -16,9 +16,14 @@ #include #include #include +#ifndef ANDROID #include #include "f2fs_fs.h" +#else +#include "include/f2fs_fs.h" +#endif + #include "f2fs_format_utils.h" extern struct f2fs_configuration config; @@ -91,6 +96,43 @@ static void configure_extension_list(void) free(config.extension_list); } +#ifdef ANDROID +/* + This generates a version 4 universally unique identifier (UUID). + The format is: xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx + where each x is 4 bits populated by /dev/urandom. + The algorithm is derived from Theodore T'so's original e2fsprogs source. + + 16 bytes will be written to the passed pointer, so allocate + at least that much space before calling uuid_generate. +*/ +#define RANDOM "/dev/urandom" +void uuid_generate(unsigned char *uuid) +{ + int fd; + + fd = open(RANDOM, O_RDONLY); + if(-1 == fd) + { + perror("Error while opening " RANDOM); + return; + } + + if(16 != read(fd, uuid, 16)) + { + perror("Error while reading from " RANDOM); + } + + uuid[6] &= 0x0F; + uuid[6] |= 0x40; + + uuid[8] &= 0x3F; + uuid[8] |= 0x80; + + close(fd); +} +#endif + static int f2fs_prepare_super_block(void) { u_int32_t blk_size_bytes; diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c index 19c52e4..0c9e5e8 100644 --- a/mkfs/f2fs_format_main.c +++ b/mkfs/f2fs_format_main.c @@ -17,9 +17,13 @@ #include #include //#include +#ifndef ANDROID #include #include "f2fs_fs.h" +#else +#include "include/f2fs_fs.h" +#endif #include "f2fs_format_utils.h" extern struct f2fs_configuration config; @@ -111,7 +115,11 @@ static void f2fs_parse_options(int argc, char *argv[]) * config.segs_per_sec; } +#ifndef ANDROID int main(int argc, char *argv[]) +#else +int make_f2fs_main(int argc, char *argv[]) +#endif { MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n", F2FS_TOOLS_VERSION, @@ -120,8 +128,10 @@ int main(int argc, char *argv[]) f2fs_parse_options(argc, argv); +#ifndef ANDROID if (f2fs_dev_is_umounted(&config) < 0) return -1; +#endif if (f2fs_get_device_info(&config) < 0) return -1; diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c index 9892a8f..6792ce0 100644 --- a/mkfs/f2fs_format_utils.c +++ b/mkfs/f2fs_format_utils.c @@ -13,7 +13,11 @@ #include #include +#ifndef ANDROID #include "f2fs_fs.h" +#else +#include "include/f2fs_fs.h" +#endif #ifdef HAVE_LINUX_FS_H #include diff --git a/mkfs/f2fs_format_utils.h b/mkfs/f2fs_format_utils.h index 9eb2cea..9f531ee 100644 --- a/mkfs/f2fs_format_utils.h +++ b/mkfs/f2fs_format_utils.h @@ -8,7 +8,11 @@ */ #define _LARGEFILE64_SOURCE +#ifndef ANDROID #include "f2fs_fs.h" +#else +#include "include/f2fs_fs.h" +#endif extern struct f2fs_configuration config; diff --git a/mkfs/main.c b/mkfs/main.c new file mode 100644 index 0000000..29dd742 --- /dev/null +++ b/mkfs/main.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +extern int make_f2fs_main(int argc, char **argv); + +int main(int argc, char **argv) { + return make_f2fs_main(argc, argv); +} diff --git a/tools/f2fstat.c b/tools/f2fstat.c index c9c1d30..4301a43 100644 --- a/tools/f2fstat.c +++ b/tools/f2fstat.c @@ -218,7 +218,11 @@ void print_head(void) fprintf(stderr, "util node data free valid dirty prefree node dent meta sit nat fnid cp gc ssr lfs total node meta\n"); } +#ifndef ANDROID int main(int argc, char *argv[]) +#else +int f2fstat_main(int argc, char *argv[]) +#endif { char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %5ld %5ld %3ld %3ld %3ld %6ld %6ld %6ld %6ld %6ld\n"; int head_interval; diff --git a/tools/f2fstat_main.c b/tools/f2fstat_main.c new file mode 100644 index 0000000..9704dbe --- /dev/null +++ b/tools/f2fstat_main.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +extern int f2fstat_main(int argc, char **argv); + +int main(int argc, char **argv) { + return f2fstat_main(argc, argv); +} diff --git a/tools/fibmap.c b/tools/fibmap.c index a6a112b..e4086b1 100644 --- a/tools/fibmap.c +++ b/tools/fibmap.c @@ -80,7 +80,11 @@ out: } +#ifndef ANDROID int main(int argc, char *argv[]) +#else +int fibmap_main(int argc, char *argv[]) +#endif { int fd; int ret = 0; diff --git a/tools/fibmap_main.c b/tools/fibmap_main.c new file mode 100644 index 0000000..05cc30c --- /dev/null +++ b/tools/fibmap_main.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +extern int fibmap_main(int argc, char **argv); + +int main(int argc, char **argv) { + return fibmap_main(argc, argv); +} -- cgit v1.2.3 From 99b0cb5b37c8b2f8a424c965b74d9c5bfde23427 Mon Sep 17 00:00:00 2001 From: Huexxx Date: Thu, 6 Feb 2014 03:03:00 -0600 Subject: f2fs-tools: show version on all tools Change-Id: I6e718bd42d5a4436c0247758bbed9f7de6c4aee0 --- fsck/main.c | 6 ++++++ tools/f2fstat.c | 7 +++++++ tools/fibmap.c | 7 +++++++ 3 files changed, 20 insertions(+) diff --git a/fsck/main.c b/fsck/main.c index d9c0e77..5b5f8be 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -45,6 +45,9 @@ void f2fs_parse_options(int argc, char *argv[]) if (!strcmp("fsck.f2fs", prog)) { const char *option_string = "ad:ft"; + MSG(0, "\n\tF2FS-tools: fsck.f2fs Ver: %s (%s)\n\n", + F2FS_TOOLS_VERSION, F2FS_TOOLS_DATE); + config.func = FSCK; while ((option = getopt(argc, argv, option_string)) != EOF) { switch (option) { @@ -81,6 +84,9 @@ void f2fs_parse_options(int argc, char *argv[]) .blk_addr = -1, }; + MSG(0, "\n\tF2FS-tools: dump.f2fs Ver: %s (%s)\n\n", + F2FS_TOOLS_VERSION, F2FS_TOOLS_DATE); + config.func = DUMP; while ((option = getopt(argc, argv, option_string)) != EOF) { int ret = 0; diff --git a/tools/f2fstat.c b/tools/f2fstat.c index 4301a43..76b6644 100644 --- a/tools/f2fstat.c +++ b/tools/f2fstat.c @@ -5,6 +5,10 @@ #include #include +#ifdef ANDROID +#include "include/f2fs_version.h" +#endif + #ifdef DEBUG #define dbg(fmt, args...) printf(fmt, __VA_ARGS__); #else @@ -232,6 +236,9 @@ int f2fstat_main(int argc, char *argv[]) .partname = { 0, }, }; + printf("\n\tF2FS-tools: f2fstat Ver: %s (%s)\n\n", + F2FS_TOOLS_VERSION, F2FS_TOOLS_DATE); + parse_option(argc, argv, &opt); head_interval = opt.interval; diff --git a/tools/fibmap.c b/tools/fibmap.c index e4086b1..8c6fd97 100644 --- a/tools/fibmap.c +++ b/tools/fibmap.c @@ -13,6 +13,10 @@ #include #include +#ifdef ANDROID +#include "include/f2fs_version.h" +#endif + struct file_ext { __u32 f_pos; __u32 start_blk; @@ -96,6 +100,9 @@ int fibmap_main(int argc, char *argv[]) __u32 start_lba; __u32 blknum; + printf("\n\tF2FS-tools: fibmap.f2fs Ver: %s (%s)\n\n", + F2FS_TOOLS_VERSION, F2FS_TOOLS_DATE); + if (argc != 2) { fprintf(stderr, "No filename\n"); exit(-1); -- cgit v1.2.3 From a0c8a0bae42c89abea80335058b2f24e681b74ae Mon Sep 17 00:00:00 2001 From: Huexxx Date: Thu, 6 Feb 2014 10:39:00 -0600 Subject: f2fs-tools: remove printf warnings * getopt() itself warns with a message. Change-Id: I3feabc278a839b825c5f305f3790ee7a3684c88e --- fsck/main.c | 2 -- mkfs/f2fs_format_main.c | 1 - 2 files changed, 3 deletions(-) diff --git a/fsck/main.c b/fsck/main.c index 5b5f8be..31eeeed 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -68,7 +68,6 @@ void f2fs_parse_options(int argc, char *argv[]) config.dbg_lv = -1; break; default: - MSG(0, "\tError: Unknown option %c\n", option); fsck_usage(); break; } @@ -124,7 +123,6 @@ void f2fs_parse_options(int argc, char *argv[]) &dump_opt.blk_addr); break; default: - MSG(0, "\tError: Unknown option %c\n", option); dump_usage(); break; } diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c index 0c9e5e8..fa92845 100644 --- a/mkfs/f2fs_format_main.c +++ b/mkfs/f2fs_format_main.c @@ -92,7 +92,6 @@ static void f2fs_parse_options(int argc, char *argv[]) MSG(0, "Info: Trim is %s\n", config.trim ? "enabled": "disabled"); break; default: - MSG(0, "\tError: Unknown option %c\n",option); mkfs_usage(); break; } -- cgit v1.2.3 From 65040c58338f5170cde64bd47146ef1832b13ed5 Mon Sep 17 00:00:00 2001 From: Huexxx Date: Thu, 6 Feb 2014 10:39:00 -0600 Subject: f2fstat: fix command-line options * In ARM, the char type is always defined as unsigned (which is allowed by the C standard). This caused the terminator return value of getopt (-1) was being converted to 255 and thus never matched the loop exit condition. Change-Id: Idf17801080d7bcb86f09db11301a4763d92e335e --- tools/f2fstat.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/f2fstat.c b/tools/f2fstat.c index 76b6644..89dd7ff 100644 --- a/tools/f2fstat.c +++ b/tools/f2fstat.c @@ -195,8 +195,13 @@ void usage(void) void parse_option(int argc, char *argv[], struct options *opt) { +#ifndef ANDROID char option; const char *option_string = "d:i:p:h"; +#else + int option; + const char *option_string = "d:i:p:"; +#endif while ((option = getopt(argc, argv, option_string)) != EOF) { switch (option) { -- cgit v1.2.3 From 4f5a66a6eb77baa896d3adfb12139a830573f609 Mon Sep 17 00:00:00 2001 From: dhacker29 Date: Thu, 29 Aug 2013 02:04:00 -0500 Subject: fibmap: fix void conflicting with dedupe Change-Id: Iae9a3a853dd51358e3f964fb6d934053b51b656c --- tools/fibmap.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/fibmap.c b/tools/fibmap.c index 8c6fd97..ce30850 100644 --- a/tools/fibmap.c +++ b/tools/fibmap.c @@ -33,7 +33,11 @@ void print_ext(struct file_ext *ext) ext->end_blk, ext->blk_count); } +#ifndef ANDROID void print_stat(struct stat64 *st) +#else +void fibmap_print_stat(struct stat64 *st) +#endif { printf("--------------------------------------------\n"); printf("dev [%d:%d]\n", major(st->st_dev), minor(st->st_dev)); @@ -130,7 +134,11 @@ int fibmap_main(int argc, char *argv[]) printf("\n----------------file info-------------------\n"); printf("%s :\n", filename); +#ifndef ANDROID print_stat(&st); +#else + fibmap_print_stat(&st); +#endif printf("file_pos start_blk end_blk blks\n"); blknum = 0; -- cgit v1.2.3