All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature
@ 2018-02-23  3:17 Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 1/7] fsck.f2fs: fix typo Sheng Yong
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:17 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

v2->v1:
  * discard obsolete dnodes after all inodes are created.
  * add new error message if file type (i_mode) is totally wrong.
  * change "-O lost+found" to "-O lost_found".
  * only set filename and bitmap in the second slot of lost+found dentry.
  * handle inode_crtime when creating lost+found inode.
  * fix endiain issue.
  * fix memory leak in fsck_failed_reconnect_file{_dnode|_idnode|_didnode}.
  * translate i_mode to FILE_TYPE instead of F2FS_FT_REG_FILE when
    reconnecting files.
  * get_node_info() reads nat block again if nat entry is invalid.
---o<---

Commit 390fe587b1 ("fsck.f2fs: support restore lost files into
./lost_found/") restores unreachable files, which have no parent directory
or their parent directories are removed by fsck, to ./lost_found directory.

However, it has several limitations:
  1. ./lost_found dir does not locate inside f2fs, thus it may needs
     another partition to save ./lost_found.
  2. encrypted files are not supported to be restored.
  3. some xattrs may be lost, it depends on whether dump_node() enables
     dumping such xattrs.
  4. not support restoring files on Android devices (the same reason as
     #1).

In order to address the above limitations, the LOST_FOUND feature is
introduced. This is an ext4-style lost+found. It tries to restore
unreachable files into /lost+found directory inside f2fs.

If LOST_FOUND feature is switched on when mkfs, /lost+found directory is
created by mkfs. It can also be created by mkdir manually. It should be
located right under root directory.

If fsck detects unreachable nids, it scans all these nids, and skips non-
inode or directory inode nodes. For the left nids, they are all file inodes.
Fsck then checks these inodes and update corresponding counters and bitmaps.

From now on, the filesystem is in a "consistent" state, fsck can allocate
blocks safely and start reconnecting files to lost+found. The reconnection
adds new dentry in lost+found and update metadata (i_name, i_pino) of file
inode. If reconnection fails, fsck will clear the counters and bitmaps.
Files reconnected to lost+found will be renamed after its ino number.

However, because of lost+found directory, f2fs should avoid to encrypting
root directory. So f2fs should also check if LOST_FOUND feature is enabled
or not.

I create testcases which inject faults to generate unreachable nids. To
enable LOST_FOUND, we should give "-O lost_found" to mkfs.

	# mkfs.f2fs -O lost_found -O encrypt test.img
	# tree /data/
	/data/
	├── dir
	│   ├── foo
	│   └── subdir
	│       └── bar
	├── encrypt-dir
	│   ├── encrypt-foo
	│   └── encrypt-subdir
	│       └── encrypt-bar
	└── lost+found

	5 directories, 4 files

Testcases:
1) corrupt nat_entry->blk_addr of dir [PASS]
2) corrupt nat_entry->blk_addr of encrypt-dir [PASS]
3) remove lost+found, then corrupt nat_entry->blk_addr of dir [PASS]

Any comments and tests are appreciated.

Thanks,
Sheng


Sheng Yong (7):
  fsck.f2fs: fix typo
  mkfs.f2fs: introduce mkfs parameters in f2fs_configuration
  f2fs-tools: init f2fs_configuration as 0
  fsck.f2fs: integrate sanity_check_inode to __check_inode_mode
  mkfs.f2fs: create lost+found directory
  fsck.f2fs: read nat block if nat entry is invalid
  fsck.f2fs: reconnect unreachable files to lost+found

 fsck/dir.c              |  19 ++-
 fsck/fsck.c             | 421 +++++++++++++++++++++++++++++++++++++++++++++---
 fsck/fsck.h             |   3 +
 fsck/main.c             |   2 +-
 fsck/mount.c            |   9 +-
 include/f2fs_fs.h       |  11 ++
 lib/libf2fs.c           |  18 +--
 mkfs/f2fs_format.c      | 291 +++++++++++++++++++++++++++------
 mkfs/f2fs_format_main.c |   2 +
 9 files changed, 686 insertions(+), 90 deletions(-)

-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH v2 1/7] fsck.f2fs: fix typo
  2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
@ 2018-02-23  3:17 ` Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 2/7] mkfs.f2fs: introduce mkfs parameters in f2fs_configuration Sheng Yong
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:17 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fsck/main.c b/fsck/main.c
index 804f71a..bbf82c3 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -137,7 +137,7 @@ static void error_out(char *prog)
 	else if (!strcmp("sload.f2fs", prog))
 		sload_usage();
 	else
-		MSG(0, "\nWrong progam.\n");
+		MSG(0, "\nWrong program.\n");
 }
 
 void f2fs_parse_options(int argc, char *argv[])
-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH v2 2/7] mkfs.f2fs: introduce mkfs parameters in f2fs_configuration
  2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 1/7] fsck.f2fs: fix typo Sheng Yong
@ 2018-02-23  3:17 ` Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 3/7] f2fs-tools: init f2fs_configuration as 0 Sheng Yong
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:17 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

Introduce new parameters in f2fs_configuration for mkfs:
  * next_free_nid: save the next free nid
  * quota_inum: save how many blocks are used for quota inodes
  * quota_dnum: save how many blocks are used for quota data

Use these parameters to avoid duplicated count of these values. And
discard obsolete dnodes after all inodes are created.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 include/f2fs_fs.h  |  5 ++++
 mkfs/f2fs_format.c | 85 ++++++++++++++++++++++++++----------------------------
 2 files changed, 46 insertions(+), 44 deletions(-)

diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 548a3e8..ca4522d 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -365,6 +365,11 @@ struct f2fs_configuration {
 	int large_nat_bitmap;
 	__le32 feature;			/* defined features */
 
+	/* mkfs parameters */
+	u_int32_t next_free_nid;
+	u_int32_t quota_inum;
+	u_int32_t quota_dnum;
+
 	/* defragmentation parameters */
 	int defrag_shrink;
 	u_int64_t defrag_start;
diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index 4fb429e..5eaeff4 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -159,7 +159,6 @@ static int f2fs_prepare_super_block(void)
 	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;
-	u_int32_t next_ino;
 	enum quota_type qtype;
 	int i;
 
@@ -411,7 +410,7 @@ static int f2fs_prepare_super_block(void)
 	set_sb(node_ino, 1);
 	set_sb(meta_ino, 2);
 	set_sb(root_ino, 3);
-	next_ino = 4;
+	c.next_free_nid = 4;
 
 	if (c.feature & cpu_to_le32(F2FS_FEATURE_QUOTA_INO)) {
 		quotatype_bits = QUOTA_USR_BIT | QUOTA_GRP_BIT;
@@ -422,9 +421,9 @@ static int f2fs_prepare_super_block(void)
 	for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++) {
 		if (!((1 << qtype) & quotatype_bits))
 			continue;
-		sb->qf_ino[qtype] = cpu_to_le32(next_ino++);
+		sb->qf_ino[qtype] = cpu_to_le32(c.next_free_nid++);
 		MSG(0, "Info: add quota type = %u => %u\n",
-					qtype, next_ino - 1);
+					qtype, c.next_free_nid - 1);
 	}
 
 	if (total_zones <= 6) {
@@ -558,7 +557,6 @@ static int f2fs_write_check_point_pack(void)
 	char *sum_compact, *sum_compact_p;
 	struct f2fs_summary *sum_entry;
 	enum quota_type qtype;
-	u_int32_t quota_inum, quota_dnum;
 	int off;
 	int ret = -1;
 
@@ -610,16 +608,9 @@ static int f2fs_write_check_point_pack(void)
 		set_cp(cur_data_segno[i], 0xffffffff);
 	}
 
-	quota_inum = quota_dnum = 0;
-	for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++)
-		if (sb->qf_ino[qtype]) {
-			quota_inum++;
-			quota_dnum += QUOTA_DATA(qtype);
-		}
-
-	set_cp(cur_node_blkoff[0], 1 + quota_inum);
-	set_cp(cur_data_blkoff[0], 1 + quota_dnum);
-	set_cp(valid_block_count, 2 + quota_inum + quota_dnum);
+	set_cp(cur_node_blkoff[0], 1 + c.quota_inum);
+	set_cp(cur_data_blkoff[0], 1 + c.quota_dnum);
+	set_cp(valid_block_count, 2 + c.quota_inum + c.quota_dnum);
 	set_cp(rsvd_segment_count, c.reserved_segments);
 	set_cp(overprov_segment_count, (get_sb(segment_count_main) -
 			get_cp(rsvd_segment_count)) *
@@ -651,9 +642,9 @@ static int f2fs_write_check_point_pack(void)
 
 	set_cp(ckpt_flags, flags);
 	set_cp(cp_pack_start_sum, 1 + get_sb(cp_payload));
-	set_cp(valid_node_count, 1 + quota_inum);
-	set_cp(valid_inode_count, 1 + quota_inum);
-	set_cp(next_free_nid, get_sb(root_ino) + 1 + quota_inum);
+	set_cp(valid_node_count, 1 + c.quota_inum);
+	set_cp(valid_inode_count, 1 + c.quota_inum);
+	set_cp(next_free_nid, c.next_free_nid);
 	set_cp(sit_ver_bitmap_bytesize, ((get_sb(segment_count_sit) / 2) <<
 			get_sb(log_blocks_per_seg)) / 8);
 
@@ -711,7 +702,7 @@ static int f2fs_write_check_point_pack(void)
 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
 
 	journal = &sum->journal;
-	journal->n_nats = cpu_to_le16(1 + quota_inum);
+	journal->n_nats = cpu_to_le16(1 + c.quota_inum);
 	journal->nat_j.entries[0].nid = sb->root_ino;
 	journal->nat_j.entries[0].ne.version = 0;
 	journal->nat_j.entries[0].ne.ino = sb->root_ino;
@@ -741,9 +732,9 @@ static int f2fs_write_check_point_pack(void)
 	journal->sit_j.entries[0].segno = cp->cur_node_segno[0];
 	journal->sit_j.entries[0].se.vblocks =
 				cpu_to_le16((CURSEG_HOT_NODE << 10) |
-						(1 + quota_inum));
+						(1 + c.quota_inum));
 	f2fs_set_bit(0, (char *)journal->sit_j.entries[0].se.valid_map);
-	for (i = 1; i <= quota_inum; i++)
+	for (i = 1; i <= c.quota_inum; i++)
 		f2fs_set_bit(i, (char *)journal->sit_j.entries[0].se.valid_map);
 	journal->sit_j.entries[1].segno = cp->cur_node_segno[1];
 	journal->sit_j.entries[1].se.vblocks =
@@ -756,9 +747,9 @@ static int f2fs_write_check_point_pack(void)
 	journal->sit_j.entries[3].segno = cp->cur_data_segno[0];
 	journal->sit_j.entries[3].se.vblocks =
 				cpu_to_le16((CURSEG_HOT_DATA << 10) |
-						(1 + quota_dnum));
+						(1 + c.quota_dnum));
 	f2fs_set_bit(0, (char *)journal->sit_j.entries[3].se.valid_map);
-	for (i = 1; i <= quota_dnum; i++)
+	for (i = 1; i <= c.quota_dnum; i++)
 		f2fs_set_bit(i, (char *)journal->sit_j.entries[3].se.valid_map);
 
 	journal->sit_j.entries[4].segno = cp->cur_data_segno[1];
@@ -951,31 +942,36 @@ static int f2fs_write_super_block(void)
 }
 
 #ifndef WITH_ANDROID
-static int discard_obsolete_dnode(struct f2fs_node *raw_node, u_int64_t offset)
+static int f2fs_discard_obsolete_dnode(void)
 {
-	u_int64_t next_blkaddr = 0;
+	struct f2fs_node *raw_node;
+	u_int64_t next_blkaddr = 0, offset;
 	u64 end_blkaddr = (get_sb(segment_count_main) <<
 			get_sb(log_blocks_per_seg)) + get_sb(main_blkaddr);
 	u_int64_t start_inode_pos = get_sb(main_blkaddr);
 	u_int64_t last_inode_pos;
-	enum quota_type qtype;
-	u_int32_t quota_inum = 0;
 
-	for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++)
-		if (sb->qf_ino[qtype]) quota_inum++;
+	if (c.zoned_mode)
+		return 0;
+
+	raw_node = calloc(sizeof(struct f2fs_node), 1);
+	if (!raw_node)
+		return -1;
+
+	/* avoid power-off-recovery based on roll-forward policy */
+	offset = get_sb(main_blkaddr);
+	offset += c.cur_seg[CURSEG_WARM_NODE] * c.blks_per_seg;
 
-	/* only root inode was written before truncating dnodes */
 	last_inode_pos = start_inode_pos +
-		c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg + quota_inum;
+		c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg + c.quota_inum;
 
-	if (c.zoned_mode)
-		return 0;
 	do {
 		if (offset < get_sb(main_blkaddr) || offset >= end_blkaddr)
 			break;
 
 		if (dev_read_block(raw_node, offset)) {
 			MSG(1, "\tError: While traversing direct node!!!\n");
+			free(raw_node);
 			return -1;
 		}
 
@@ -985,6 +981,7 @@ static int discard_obsolete_dnode(struct f2fs_node *raw_node, u_int64_t offset)
 		DBG(1, "\tDiscard dnode, at offset 0x%08"PRIx64"\n", offset);
 		if (dev_write_block(raw_node, offset)) {
 			MSG(1, "\tError: While discarding direct node!!!\n");
+			free(raw_node);
 			return -1;
 		}
 		offset = next_blkaddr;
@@ -993,6 +990,7 @@ static int discard_obsolete_dnode(struct f2fs_node *raw_node, u_int64_t offset)
 			break;
 	} while (1);
 
+	free(raw_node);
 	return 0;
 }
 #endif
@@ -1078,17 +1076,6 @@ static int f2fs_write_root_inode(void)
 		return -1;
 	}
 
-	/* avoid power-off-recovery based on roll-forward policy */
-	main_area_node_seg_blk_offset = get_sb(main_blkaddr);
-	main_area_node_seg_blk_offset += c.cur_seg[CURSEG_WARM_NODE] *
-					c.blks_per_seg;
-
-#ifndef WITH_ANDROID
-	if (discard_obsolete_dnode(raw_node, main_area_node_seg_blk_offset)) {
-		free(raw_node);
-		return -1;
-	}
-#endif
 	free(raw_node);
 	return 0;
 }
@@ -1154,6 +1141,7 @@ static int f2fs_write_default_quota(int qtype, unsigned int blkaddr,
 	DBG(1, "\tWriting quota data, at offset %08x, %08x\n",
 					blkaddr, blkaddr + 1);
 	free(filebuf);
+	c.quota_dnum += QUOTA_DATA(qtype);
 	return 0;
 }
 
@@ -1255,6 +1243,7 @@ static int f2fs_write_qf_inode(int qtype)
 	}
 
 	free(raw_node);
+	c.quota_inum++;
 	return 0;
 }
 
@@ -1375,6 +1364,14 @@ static int f2fs_create_root_dir(void)
 		}
 	}
 
+#ifndef WITH_ANDROID
+	err = f2fs_discard_obsolete_dnode();
+	if (err < 0) {
+		MSG(1, "\tError: Failed to discard obsolete dnode!!!\n");
+		goto exit;
+	}
+#endif
+
 	err = f2fs_update_nat_root();
 	if (err < 0) {
 		MSG(1, "\tError: Failed to update NAT for root!!!\n");
-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH v2 3/7] f2fs-tools: init f2fs_configuration as 0
  2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 1/7] fsck.f2fs: fix typo Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 2/7] mkfs.f2fs: introduce mkfs parameters in f2fs_configuration Sheng Yong
@ 2018-02-23  3:17 ` Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 4/7] fsck.f2fs: integrate sanity_check_inode to __check_inode_mode Sheng Yong
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:17 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
---
 lib/libf2fs.c | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index e8b1842..0c684d5 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -586,24 +586,17 @@ void f2fs_init_configuration(void)
 {
 	int i;
 
+	memset(&c, 0, sizeof(struct f2fs_configuration));
 	c.ndevs = 1;
-	c.total_sectors = 0;
-	c.sector_size = 0;
 	c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
 	c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
 	c.rootdev_name = get_rootdev();
 	c.wanted_total_sectors = -1;
-	c.zoned_mode = 0;
-	c.zoned_model = 0;
-	c.zone_blocks = 0;
-#ifdef WITH_ANDROID
-	c.preserve_limits = 0;
-#else
+#ifndef WITH_ANDROID
 	c.preserve_limits = 1;
 #endif
 
 	for (i = 0; i < MAX_DEVICES; i++) {
-		memset(&c.devices[i], 0, sizeof(struct device_info));
 		c.devices[i].fd = -1;
 		c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
 		c.devices[i].end_blkaddr = -1;
@@ -611,19 +604,12 @@ void f2fs_init_configuration(void)
 	}
 
 	/* calculated by overprovision ratio */
-	c.reserved_segments = 0;
-	c.overprovision = 0;
 	c.segs_per_sec = 1;
 	c.secs_per_zone = 1;
 	c.segs_per_zone = 1;
-	c.heap = 0;
 	c.vol_label = "";
 	c.trim = 1;
-	c.trimmed = 0;
-	c.ro = 0;
 	c.kd = -1;
-	c.dry_run = 0;
-	c.large_nat_bitmap = 0;
 	c.fixed_time = -1;
 }
 
-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH v2 4/7] fsck.f2fs: integrate sanity_check_inode to __check_inode_mode
  2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
                   ` (2 preceding siblings ...)
  2018-02-23  3:17 ` [RFC PATCH v2 3/7] f2fs-tools: init f2fs_configuration as 0 Sheng Yong
@ 2018-02-23  3:17 ` Sheng Yong
  2018-02-23  3:17 ` [RFC PATCH v2 5/7] mkfs.f2fs: create lost+found directory Sheng Yong
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:17 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

In sanity_check_nid, __check_inode_mode will check i_mode value of an
inode. So integrate sanity_check_inode to __check_inode_mode to clean
up the code.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/fsck.c | 33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 0a37f7a..f6391e9 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -334,6 +334,15 @@ static int __check_inode_mode(u32 nid, enum FILE_TYPE ftype, u32 mode)
 {
 	if (ftype >= F2FS_FT_MAX)
 		return 0;
+	/* f2fs_iget will return -EIO if mode is not valid file type */
+	if (!S_ISLNK(mode) && !S_ISREG(mode) && !S_ISDIR(mode) &&
+	    !S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode) &&
+	    !S_ISSOCK(mode)) {
+		ASSERT_MSG("inode [0x%x] unknown file type i_mode [0x%x]",
+			   nid, mode);
+		return -1;
+	}
+
 	if (S_ISLNK(mode) && ftype != F2FS_FT_SYMLINK)
 		goto err;
 	if (S_ISREG(mode) && ftype != F2FS_FT_REG_FILE)
@@ -350,7 +359,8 @@ static int __check_inode_mode(u32 nid, enum FILE_TYPE ftype, u32 mode)
 		goto err;
 	return 0;
 err:
-	ASSERT_MSG("mismatch i_mode [0x%x] [0x%x vs. 0x%x]", nid, ftype, mode);
+	ASSERT_MSG("inode [0x%x] mismatch i_mode [0x%x vs. 0x%x]",
+		   nid, ftype, mode);
 	return -1;
 }
 
@@ -465,25 +475,6 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
 	return 0;
 }
 
-static int sanity_check_inode(struct f2fs_sb_info *sbi, struct f2fs_node *node)
-{
-	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
-	struct f2fs_inode *fi = &node->i;
-
-	if (!(le16_to_cpu(fi->i_mode) & S_IFMT)) {
-		ASSERT_MSG("i_mode is not valid. [0x%x]", le16_to_cpu(fi->i_mode));
-		goto remove_node;
-	}
-
-	return 0;
-
-remove_node:
-	f2fs_set_bit(le32_to_cpu(node->footer.ino), fsck->nat_area_bitmap);
-	fsck->chk.valid_blk_cnt--;
-	fsck->chk.valid_node_cnt--;
-	return -EINVAL;
-}
-
 static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino,
 					u32 x_nid, u32 *blk_cnt)
 {
@@ -528,8 +519,6 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
 	if (ntype == TYPE_INODE) {
 		struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
 
-		if (sanity_check_inode(sbi, node_blk))
-			goto err;
 		fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni, child);
 		quota_add_inode_usage(fsck->qctx, nid, &node_blk->i);
 	} else {
-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH v2 5/7] mkfs.f2fs: create lost+found directory
  2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
                   ` (3 preceding siblings ...)
  2018-02-23  3:17 ` [RFC PATCH v2 4/7] fsck.f2fs: integrate sanity_check_inode to __check_inode_mode Sheng Yong
@ 2018-02-23  3:17 ` Sheng Yong
  2018-02-28  5:25   ` Jaegeuk Kim
  2018-02-23  3:18 ` [RFC PATCH v2 6/7] fsck.f2fs: read nat block if nat entry is invalid Sheng Yong
  2018-02-23  3:18 ` [RFC PATCH v2 7/7] fsck.f2fs: reconnect unreachable files to lost+found Sheng Yong
  6 siblings, 1 reply; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:17 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

This patch introduces a new feature F2FS_FEATURE_LOST_FOUND. It can be
switched on by indicating `-O lost_found'. If LOST_FOUND feature is
enabled, an empty directory lost+found is created by mkfs.

This is a preparation for fsck. During fsck, the directory is used to
save unreachable files, which have no parent directory or their parent
directory is removed by fsck. Encrypted files are also allowed to be
saved here.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/mount.c            |   3 +
 include/f2fs_fs.h       |   6 ++
 mkfs/f2fs_format.c      | 224 +++++++++++++++++++++++++++++++++++++++++++++---
 mkfs/f2fs_format_main.c |   2 +
 4 files changed, 223 insertions(+), 12 deletions(-)

diff --git a/fsck/mount.c b/fsck/mount.c
index 46cb571..6482721 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -460,6 +460,9 @@ void print_sb_state(struct f2fs_super_block *sb)
 	if (f & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
 		MSG(0, "%s", " inode_crtime");
 	}
+	if (f & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) {
+		MSG(0, "%s", " lost_found");
+	}
 	MSG(0, "\n");
 	MSG(0, "Info: superblock encrypt level = %d, salt = ",
 					sb->encryption_level);
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index ca4522d..093c402 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -291,6 +291,8 @@ static inline uint64_t bswap_64(uint64_t val)
 
 #define VERSION_LEN	256
 
+#define LPF "lost+found"
+
 enum f2fs_config_func {
 	MKFS,
 	FSCK,
@@ -369,6 +371,9 @@ struct f2fs_configuration {
 	u_int32_t next_free_nid;
 	u_int32_t quota_inum;
 	u_int32_t quota_dnum;
+	u_int32_t lpf_inum;
+	u_int32_t lpf_dnum;
+	u_int32_t lpf_ino;
 
 	/* defragmentation parameters */
 	int defrag_shrink;
@@ -557,6 +562,7 @@ enum {
 #define F2FS_FEATURE_FLEXIBLE_INLINE_XATTR	0x0040
 #define F2FS_FEATURE_QUOTA_INO		0x0080
 #define F2FS_FEATURE_INODE_CRTIME	0x0100
+#define F2FS_FEATURE_LOST_FOUND		0x0200
 
 #define MAX_VOLUME_NAME		512
 
diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index 5eaeff4..4145c79 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -426,6 +426,9 @@ static int f2fs_prepare_super_block(void)
 					qtype, c.next_free_nid - 1);
 	}
 
+	if (c.feature & cpu_to_le32(F2FS_FEATURE_LOST_FOUND))
+		c.lpf_ino = c.next_free_nid++;
+
 	if (total_zones <= 6) {
 		MSG(1, "\tError: %d zones: Need more zones "
 			"by shrinking zone size\n", total_zones);
@@ -608,9 +611,10 @@ static int f2fs_write_check_point_pack(void)
 		set_cp(cur_data_segno[i], 0xffffffff);
 	}
 
-	set_cp(cur_node_blkoff[0], 1 + c.quota_inum);
-	set_cp(cur_data_blkoff[0], 1 + c.quota_dnum);
-	set_cp(valid_block_count, 2 + c.quota_inum + c.quota_dnum);
+	set_cp(cur_node_blkoff[0], 1 + c.quota_inum + c.lpf_inum);
+	set_cp(cur_data_blkoff[0], 1 + c.quota_dnum + c.lpf_dnum);
+	set_cp(valid_block_count, 2 + c.quota_inum + c.quota_dnum +
+			c.lpf_inum + c.lpf_dnum);
 	set_cp(rsvd_segment_count, c.reserved_segments);
 	set_cp(overprov_segment_count, (get_sb(segment_count_main) -
 			get_cp(rsvd_segment_count)) *
@@ -642,8 +646,8 @@ static int f2fs_write_check_point_pack(void)
 
 	set_cp(ckpt_flags, flags);
 	set_cp(cp_pack_start_sum, 1 + get_sb(cp_payload));
-	set_cp(valid_node_count, 1 + c.quota_inum);
-	set_cp(valid_inode_count, 1 + c.quota_inum);
+	set_cp(valid_node_count, 1 + c.quota_inum + c.lpf_inum);
+	set_cp(valid_inode_count, 1 + c.quota_inum + c.lpf_inum);
 	set_cp(next_free_nid, c.next_free_nid);
 	set_cp(sit_ver_bitmap_bytesize, ((get_sb(segment_count_sit) / 2) <<
 			get_sb(log_blocks_per_seg)) / 8);
@@ -702,7 +706,7 @@ static int f2fs_write_check_point_pack(void)
 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
 
 	journal = &sum->journal;
-	journal->n_nats = cpu_to_le16(1 + c.quota_inum);
+	journal->n_nats = cpu_to_le16(1 + c.quota_inum + c.lpf_inum);
 	journal->nat_j.entries[0].nid = sb->root_ino;
 	journal->nat_j.entries[0].ne.version = 0;
 	journal->nat_j.entries[0].ne.ino = sb->root_ino;
@@ -723,6 +727,16 @@ static int f2fs_write_check_point_pack(void)
 		i++;
 	}
 
+	if (c.lpf_inum) {
+		journal->nat_j.entries[i].nid = cpu_to_le32(c.lpf_ino);
+		journal->nat_j.entries[i].ne.version = 0;
+		journal->nat_j.entries[i].ne.ino = cpu_to_le32(c.lpf_ino);
+		journal->nat_j.entries[i].ne.block_addr = cpu_to_le32(
+				get_sb(main_blkaddr) +
+				get_cp(cur_node_segno[0]) *
+				c.blks_per_seg + i);
+	}
+
 	memcpy(sum_compact_p, &journal->n_nats, SUM_JOURNAL_SIZE);
 	sum_compact_p += SUM_JOURNAL_SIZE;
 
@@ -732,10 +746,13 @@ static int f2fs_write_check_point_pack(void)
 	journal->sit_j.entries[0].segno = cp->cur_node_segno[0];
 	journal->sit_j.entries[0].se.vblocks =
 				cpu_to_le16((CURSEG_HOT_NODE << 10) |
-						(1 + c.quota_inum));
+						(1 + c.quota_inum + c.lpf_inum));
 	f2fs_set_bit(0, (char *)journal->sit_j.entries[0].se.valid_map);
 	for (i = 1; i <= c.quota_inum; i++)
 		f2fs_set_bit(i, (char *)journal->sit_j.entries[0].se.valid_map);
+	if (c.lpf_inum)
+		f2fs_set_bit(i, (char *)journal->sit_j.entries[0].se.valid_map);
+
 	journal->sit_j.entries[1].segno = cp->cur_node_segno[1];
 	journal->sit_j.entries[1].se.vblocks =
 				cpu_to_le16((CURSEG_WARM_NODE << 10));
@@ -747,10 +764,12 @@ static int f2fs_write_check_point_pack(void)
 	journal->sit_j.entries[3].segno = cp->cur_data_segno[0];
 	journal->sit_j.entries[3].se.vblocks =
 				cpu_to_le16((CURSEG_HOT_DATA << 10) |
-						(1 + c.quota_dnum));
+						(1 + c.quota_dnum + c.lpf_dnum));
 	f2fs_set_bit(0, (char *)journal->sit_j.entries[3].se.valid_map);
 	for (i = 1; i <= c.quota_dnum; i++)
 		f2fs_set_bit(i, (char *)journal->sit_j.entries[3].se.valid_map);
+	if (c.lpf_dnum)
+		f2fs_set_bit(i, (char *)journal->sit_j.entries[3].se.valid_map);
 
 	journal->sit_j.entries[4].segno = cp->cur_data_segno[1];
 	journal->sit_j.entries[4].se.vblocks =
@@ -780,6 +799,11 @@ static int f2fs_write_check_point_pack(void)
 		off += QUOTA_DATA(qtype);
 	}
 
+	if (c.lpf_dnum) {
+		(sum_entry + off)->nid = cpu_to_le32(c.lpf_ino);
+		(sum_entry + off)->ofs_in_node = 0;
+	}
+
 	/* warm data summary, nothing to do */
 	/* cold data summary, nothing to do */
 
@@ -804,6 +828,11 @@ static int f2fs_write_check_point_pack(void)
 		sum->entries[1 + i].ofs_in_node = 0;
 		i++;
 	}
+	if (c.lpf_inum) {
+		i++;
+		sum->entries[i].nid = cpu_to_le32(c.lpf_ino);
+		sum->entries[i].ofs_in_node = 0;
+	}
 
 	cp_seg_blk++;
 	DBG(1, "\tWriting Segment summary for HOT_NODE, at offset 0x%08"PRIx64"\n",
@@ -963,7 +992,7 @@ static int f2fs_discard_obsolete_dnode(void)
 	offset += c.cur_seg[CURSEG_WARM_NODE] * c.blks_per_seg;
 
 	last_inode_pos = start_inode_pos +
-		c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg + c.quota_inum;
+		c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg + c.quota_inum + c.lpf_inum;
 
 	do {
 		if (offset < get_sb(main_blkaddr) || offset >= end_blkaddr)
@@ -1016,7 +1045,10 @@ static int f2fs_write_root_inode(void)
 			c.blks_per_seg + 1);
 
 	raw_node->i.i_mode = cpu_to_le16(0x41ed);
-	raw_node->i.i_links = cpu_to_le32(2);
+	if (c.lpf_ino)
+		raw_node->i.i_links = cpu_to_le32(3);
+	else
+		raw_node->i.i_links = cpu_to_le32(2);
 	raw_node->i.i_uid = cpu_to_le32(getuid());
 	raw_node->i.i_gid = cpu_to_le32(getgid());
 
@@ -1122,10 +1154,16 @@ static int f2fs_write_default_quota(int qtype, unsigned int blkaddr,
 	dqblk.dqb_pad = cpu_to_le32(0);
 	dqblk.dqb_ihardlimit = cpu_to_le64(0);
 	dqblk.dqb_isoftlimit = cpu_to_le64(0);
-	dqblk.dqb_curinodes = cpu_to_le64(1);
+	if (c.lpf_ino)
+		dqblk.dqb_curinodes = cpu_to_le64(2);
+	else
+		dqblk.dqb_curinodes = cpu_to_le64(1);
 	dqblk.dqb_bhardlimit = cpu_to_le64(0);
 	dqblk.dqb_bsoftlimit = cpu_to_le64(0);
-	dqblk.dqb_curspace = cpu_to_le64(4096);
+	if (c.lpf_ino)
+		dqblk.dqb_curspace = cpu_to_le64(8192);
+	else
+		dqblk.dqb_curspace = cpu_to_le64(4096);
 	dqblk.dqb_btime = cpu_to_le64(0);
 	dqblk.dqb_itime = cpu_to_le64(0);
 
@@ -1300,6 +1338,142 @@ static int f2fs_update_nat_root(void)
 	return 0;
 }
 
+static u_int64_t f2fs_add_default_dentry_lpf(void)
+{
+	struct f2fs_dentry_block *dent_blk;
+	u_int64_t data_blk_offset = 0;
+
+	dent_blk = calloc(F2FS_BLKSIZE, 1);
+	if (dent_blk == NULL) {
+		MSG(1, "\tError: Calloc Failed for dent_blk!!!\n");
+		return -1;
+	}
+
+	dent_blk->dentry[0].hash_code = 0;
+	dent_blk->dentry[0].ino = cpu_to_le32(c.lpf_ino);
+	dent_blk->dentry[0].name_len = cpu_to_le16(1);
+	dent_blk->dentry[0].file_type = F2FS_FT_DIR;
+	memcpy(dent_blk->filename[0], ".", 1);
+
+	dent_blk->dentry[1].hash_code = 0;
+	dent_blk->dentry[1].ino = sb->root_ino;
+	dent_blk->dentry[1].name_len = cpu_to_le16(2);
+	dent_blk->dentry[1].file_type = F2FS_FT_DIR;
+	memcpy(dent_blk->filename[1], "..", 2);
+
+	test_and_set_bit_le(0, dent_blk->dentry_bitmap);
+	test_and_set_bit_le(1, dent_blk->dentry_bitmap);
+
+	data_blk_offset = get_sb(main_blkaddr);
+	data_blk_offset += c.cur_seg[CURSEG_HOT_DATA] * c.blks_per_seg +
+		1 + c.quota_dnum;
+
+	DBG(1, "\tWriting default dentry lost+found, at offset 0x%08"PRIx64"\n",
+			data_blk_offset);
+	if (dev_write_block(dent_blk, data_blk_offset)) {
+		MSG(1, "\tError While writing the dentry_blk to disk!!!\n");
+		free(dent_blk);
+		return -1;
+	}
+
+	free(dent_blk);
+	c.lpf_dnum++;
+	return data_blk_offset;
+}
+
+static int f2fs_write_lpf_inode(void)
+{
+	struct f2fs_node *raw_node;
+	u_int64_t blk_size_bytes, data_blk_nor;
+	u_int64_t main_area_node_seg_blk_offset;
+	int err = 0;
+
+	ASSERT(c.lpf_ino);
+
+	raw_node = calloc(F2FS_BLKSIZE, 1);
+	if (raw_node == NULL) {
+		MSG(1, "\tError: Calloc Failed for raw_node!!!\n");
+		return -1;
+	}
+
+	raw_node->footer.nid = cpu_to_le32(c.lpf_ino);
+	raw_node->footer.ino = raw_node->footer.nid;
+	raw_node->footer.cp_ver = cpu_to_le64(1);
+	raw_node->footer.next_blkaddr = cpu_to_le32(
+			get_sb(main_blkaddr) +
+			c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg +
+			1 + c.quota_inum + 1);
+
+	raw_node->i.i_mode = cpu_to_le16(0x41c0); /* 0700 */
+	raw_node->i.i_links = cpu_to_le32(2);
+	raw_node->i.i_uid = cpu_to_le32(getuid());
+	raw_node->i.i_gid = cpu_to_le32(getgid());
+
+	blk_size_bytes = 1 << get_sb(log_blocksize);
+	raw_node->i.i_size = cpu_to_le64(1 * blk_size_bytes); /* dentry */
+	raw_node->i.i_blocks = cpu_to_le64(2);
+
+	raw_node->i.i_atime = cpu_to_le32(time(NULL));
+	raw_node->i.i_atime_nsec = 0;
+	raw_node->i.i_ctime = cpu_to_le32(time(NULL));
+	raw_node->i.i_ctime_nsec = 0;
+	raw_node->i.i_mtime = cpu_to_le32(time(NULL));
+	raw_node->i.i_mtime_nsec = 0;
+	raw_node->i.i_generation = 0;
+	raw_node->i.i_xattr_nid = 0;
+	raw_node->i.i_flags = 0;
+	raw_node->i.i_pino = le32_to_cpu(sb->root_ino);
+	raw_node->i.i_namelen = le32_to_cpu(strlen(LPF));
+	memcpy(raw_node->i.i_name, LPF, strlen(LPF));
+	raw_node->i.i_current_depth = cpu_to_le32(1);
+	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
+
+	if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
+		raw_node->i.i_inline = F2FS_EXTRA_ATTR;
+		raw_node->i.i_extra_isize =
+			cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
+	}
+
+	if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA))
+		raw_node->i.i_projid = cpu_to_le32(F2FS_DEF_PROJID);
+
+	if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
+		raw_node->i.i_crtime = cpu_to_le32(time(NULL));
+		raw_node->i.i_crtime_nsec = 0;
+	}
+
+	data_blk_nor = f2fs_add_default_dentry_lpf();
+	if (data_blk_nor < 0) {
+		MSG(1, "\tError: Failed to add default dentries for lost+found!!!\n");
+		err = -1;
+		goto exit;
+	}
+	raw_node->i.i_addr[get_extra_isize(raw_node)] = cpu_to_le32(data_blk_nor);
+
+	if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
+		raw_node->i.i_inode_checksum =
+			cpu_to_le32(f2fs_inode_chksum(raw_node));
+
+	main_area_node_seg_blk_offset = get_sb(main_blkaddr);
+	main_area_node_seg_blk_offset += c.cur_seg[CURSEG_HOT_NODE] *
+		c.blks_per_seg + c.quota_inum + 1;
+
+	DBG(1, "\tWriting lost+found inode (hot node), %x %x %x at offset 0x%08"PRIu64"\n",
+			get_sb(main_blkaddr),
+			c.cur_seg[CURSEG_HOT_NODE],
+			c.blks_per_seg, main_area_node_seg_blk_offset);
+	if (dev_write_block(raw_node, main_area_node_seg_blk_offset)) {
+		MSG(1, "\tError: While writing the raw_node to disk!!!\n");
+		err = -1;
+		goto exit;
+	}
+
+	c.lpf_inum++;
+exit:
+	free(raw_node);
+	return err;
+}
+
 static int f2fs_add_default_dentry_root(void)
 {
 	struct f2fs_dentry_block *dent_blk = NULL;
@@ -1327,6 +1501,23 @@ static int f2fs_add_default_dentry_root(void)
 	test_and_set_bit_le(0, dent_blk->dentry_bitmap);
 	test_and_set_bit_le(1, dent_blk->dentry_bitmap);
 
+	if (c.lpf_ino) {
+		int len = strlen(LPF);
+		f2fs_hash_t hash = f2fs_dentry_hash((unsigned char *)LPF, len);
+
+		dent_blk->dentry[2].hash_code = cpu_to_le32(hash);
+		dent_blk->dentry[2].ino = cpu_to_le32(c.lpf_ino);
+		dent_blk->dentry[2].name_len = cpu_to_le16(len);
+		dent_blk->dentry[2].file_type = F2FS_FT_DIR;
+		memcpy(dent_blk->filename[2], LPF, F2FS_SLOT_LEN);
+
+		memcpy(dent_blk->filename[3], LPF + F2FS_SLOT_LEN,
+				len - F2FS_SLOT_LEN);
+
+		test_and_set_bit_le(2, dent_blk->dentry_bitmap);
+		test_and_set_bit_le(3, dent_blk->dentry_bitmap);
+	}
+
 	data_blk_offset = get_sb(main_blkaddr);
 	data_blk_offset += c.cur_seg[CURSEG_HOT_DATA] *
 				c.blks_per_seg;
@@ -1364,6 +1555,14 @@ static int f2fs_create_root_dir(void)
 		}
 	}
 
+	if (c.feature & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) {
+		err = f2fs_write_lpf_inode();
+		if (err < 0) {
+			MSG(1, "\tError: Failed to write lost+found inode!!!\n");
+			goto exit;
+		}
+	}
+
 #ifndef WITH_ANDROID
 	err = f2fs_discard_obsolete_dnode();
 	if (err < 0) {
@@ -1437,6 +1636,7 @@ int f2fs_format_device(void)
 		MSG(0, "\tError: Failed to write the Super Block!!!\n");
 		goto exit;
 	}
+
 exit:
 	if (err)
 		MSG(0, "\tError: Could not format the device!!!\n");
diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c
index 120eeba..aeda5f4 100644
--- a/mkfs/f2fs_format_main.c
+++ b/mkfs/f2fs_format_main.c
@@ -95,6 +95,8 @@ static void parse_feature(const char *features)
 		c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
 	} else if (!strcmp(features, "inode_crtime")) {
 		c.feature |= cpu_to_le32(F2FS_FEATURE_INODE_CRTIME);
+	} else if (!strcmp(features, "lost_found")) {
+		c.feature |= cpu_to_le32(F2FS_FEATURE_LOST_FOUND);
 	} else {
 		MSG(0, "Error: Wrong features\n");
 		mkfs_usage();
-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH v2 6/7] fsck.f2fs: read nat block if nat entry is invalid
  2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
                   ` (4 preceding siblings ...)
  2018-02-23  3:17 ` [RFC PATCH v2 5/7] mkfs.f2fs: create lost+found directory Sheng Yong
@ 2018-02-23  3:18 ` Sheng Yong
  2018-02-23  3:18 ` [RFC PATCH v2 7/7] fsck.f2fs: reconnect unreachable files to lost+found Sheng Yong
  6 siblings, 0 replies; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:18 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

fsck will cache all valid nat entries in memory. But when we try to
get a nat entry which is not cached, for example allocate a new nid
during reconnecting files, we need to read the uncached nat entry
from nat block again.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/mount.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fsck/mount.c b/fsck/mount.c
index 6482721..b8e7643 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1600,7 +1600,9 @@ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
 	ni->nid = nid;
 	if (c.func == FSCK) {
 		node_info_from_raw_nat(ni, &(F2FS_FSCK(sbi)->entries[nid]));
-		return;
+		if (ni->blk_addr)
+			return;
+		/* nat entry is not cached, read it */
 	}
 
 	get_nat_entry(sbi, nid, &raw_nat);
-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH v2 7/7] fsck.f2fs: reconnect unreachable files to lost+found
  2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
                   ` (5 preceding siblings ...)
  2018-02-23  3:18 ` [RFC PATCH v2 6/7] fsck.f2fs: read nat block if nat entry is invalid Sheng Yong
@ 2018-02-23  3:18 ` Sheng Yong
       [not found]   ` <0c849139-fdbe-9362-770c-ad4e9da57142@huawei.com>
  6 siblings, 1 reply; 10+ messages in thread
From: Sheng Yong @ 2018-02-23  3:18 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: hyojun, miaoxie, linux-f2fs-devel

This patch introduces lost_found feature to fsck. If a file is found
unreachable by fsck. Fsck tries to reconnect the file to lost+found
directory:
  1. Scan all unreachable file inodes, ignore non-inodes ones and
     directories.
  2. Check them and fix incorrupted data to make sure filesystem
     metadata (mainly counters and main/nat bitmap) are all consistent.
  3. Reconnect these files to lost+found. If lost+found does not exist,
     create it first. During reconnecting, expand lost+found's dentry
     block automatically. Reconnected files are renamed after its ino
     number.
  4. If reconnect fails drop the node and restore filesystem metadata.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/dir.c   |  19 ++-
 fsck/fsck.c  | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 fsck/fsck.h  |   3 +
 fsck/mount.c |   2 +
 4 files changed, 409 insertions(+), 3 deletions(-)

diff --git a/fsck/dir.c b/fsck/dir.c
index b2ea18f..567a4e9 100644
--- a/fsck/dir.c
+++ b/fsck/dir.c
@@ -176,6 +176,23 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi,
 	return 0;
 }
 
+/* return ino if file exists, otherwise return 0 */
+nid_t f2fs_lookup(struct f2fs_sb_info *sbi, struct f2fs_node *dir,
+				u8 *name, int len)
+{
+	int err;
+	struct dentry de = {
+		.name = name,
+		.len = len,
+	};
+
+	err = f2fs_find_entry(sbi, dir, &de);
+	if (err == 1)
+		return de.ino;
+	else
+		return 0;
+}
+
 static void f2fs_update_dentry(nid_t ino, int file_type,
 		struct f2fs_dentry_ptr *d,
 		const unsigned char *name, int len, f2fs_hash_t name_hash,
@@ -199,7 +216,7 @@ static void f2fs_update_dentry(nid_t ino, int file_type,
 /*
  * f2fs_add_link - Add a new file(dir) to parent dir.
  */
-static int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent,
+int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent,
 			const unsigned char *name, int name_len, nid_t ino,
 			int file_type, block_t p_blkaddr, int inc_link)
 {
diff --git a/fsck/fsck.c b/fsck/fsck.c
index f6391e9..9a822ef 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -10,6 +10,7 @@
  */
 #include "fsck.h"
 #include "quotaio.h"
+#include <time.h>
 
 char *tree_mark;
 uint32_t tree_mark_size = 256;
@@ -43,6 +44,14 @@ static inline int f2fs_test_main_bitmap(struct f2fs_sb_info *sbi, u32 blk)
 						fsck->main_area_bitmap);
 }
 
+static inline int f2fs_clear_main_bitmap(struct f2fs_sb_info *sbi, u32 blk)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+
+	return f2fs_clear_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);
@@ -453,9 +462,11 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
 
 	/* workaround to fix later */
 	if (ftype != F2FS_FT_ORPHAN ||
-			f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0)
+			f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) {
 		f2fs_clear_bit(nid, fsck->nat_area_bitmap);
-	else
+		/* avoid reusing nid when reconnecting files */
+		f2fs_set_bit(nid, NM_I(sbi)->nid_bitmap);
+	} else
 		ASSERT_MSG("orphan or xattr nid is duplicated [0x%x]\n",
 				nid);
 
@@ -2046,6 +2057,369 @@ int check_sit_types(struct f2fs_sb_info *sbi)
 	return err;
 }
 
+static struct f2fs_node *fsck_get_lpf(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_node *node;
+	struct node_info ni;
+	nid_t lpf_ino;
+	int err;
+
+	/* read root inode first */
+	node = calloc(F2FS_BLKSIZE, 1);
+	ASSERT(node);
+	get_node_info(sbi, F2FS_ROOT_INO(sbi), &ni);
+	err = dev_read_block(node, ni.blk_addr);
+	ASSERT(err >= 0);
+
+	/* lookup lost+found in root directory */
+	lpf_ino = f2fs_lookup(sbi, node, (u8 *)LPF, strlen(LPF));
+	if (lpf_ino) { /* found */
+		get_node_info(sbi, lpf_ino, &ni);
+		err = dev_read_block(node, ni.blk_addr);
+		ASSERT(err >= 0);
+		DBG(1, "Found lost+found 0x%x at blkaddr [0x%x]\n",
+		    lpf_ino, ni.blk_addr);
+		if (!S_ISDIR(le16_to_cpu(node->i.i_mode))) {
+			ASSERT_MSG("lost+found is not directory [0%o]\n",
+				   le16_to_cpu(node->i.i_mode));
+			/* FIXME: give up? */
+			goto out;
+		}
+	} else { /* not found, create it */
+		struct dentry de;
+
+		memset(&de, 0, sizeof(de));
+		de.name = (u8 *) LPF;
+		de.len = strlen(LPF);
+		de.mode = 0x41c0;
+		de.pino = F2FS_ROOT_INO(sbi),
+		de.file_type = F2FS_FT_DIR,
+		de.uid = getuid();
+		de.gid = getgid();
+		de.mtime = time(NULL);
+
+		err = f2fs_mkdir(sbi, &de);
+		if (err) {
+			ASSERT_MSG("Failed create lost+found");
+			goto out;
+		}
+
+		get_node_info(sbi, de.ino, &ni);
+		err = dev_read_block(node, ni.blk_addr);
+		ASSERT(err >= 0);
+		DBG(1, "Create lost+found 0x%x at blkaddr [0x%x]\n",
+		    de.ino, ni.blk_addr);
+	}
+
+	c.lpf_ino = le32_to_cpu(node->footer.ino);
+	return node;
+out:
+	free(node);
+	return NULL;
+}
+
+static int fsck_do_reconnect_file(struct f2fs_sb_info *sbi,
+				  struct f2fs_node *lpf,
+				  struct f2fs_node *fnode)
+{
+	char name[80];
+	size_t namelen;
+	nid_t ino = le32_to_cpu(fnode->footer.ino);
+	struct node_info ni;
+	int ret;
+
+	namelen = snprintf(name, 80, "%u", ino);
+	if (namelen >= 80)
+		/* ignore terminating '\0', should never happen */
+		namelen = 79;
+
+	if (f2fs_lookup(sbi, lpf, (u8 *)name, namelen)) {
+		ASSERT_MSG("Name %s already exist in lost+found", name);
+		return -EEXIST;
+	}
+
+	get_node_info(sbi, le32_to_cpu(lpf->footer.ino), &ni);
+	ret = f2fs_add_link(sbi, lpf, (unsigned char *)name, namelen,
+			    ino, F2FS_FT_REG_FILE, ni.blk_addr, 0);
+	if (ret) {
+		ASSERT_MSG("Failed to add inode [0x%x] to lost+found", ino);
+		return -EINVAL;
+	}
+
+	/* update fnode */
+	memcpy(fnode->i.i_name, name, namelen);
+	fnode->i.i_namelen = cpu_to_le32(namelen);
+	fnode->i.i_pino = c.lpf_ino;
+	get_node_info(sbi, le32_to_cpu(fnode->footer.ino), &ni);
+	ret = dev_write_block(fnode, ni.blk_addr);
+	ASSERT(ret >= 0);
+
+	DBG(1, "Reconnect inode [0x%x] to lost+found\n", ino);
+	return 0;
+}
+
+static void fsck_failed_reconnect_file_dnode(struct f2fs_sb_info *sbi,
+					     nid_t nid)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_node *node;
+	struct node_info ni;
+	u32 addr;
+	int i, err;
+
+	node = calloc(F2FS_BLKSIZE, 1);
+	ASSERT(node);
+
+	get_node_info(sbi, nid, &ni);
+	err = dev_read_block(node, ni.blk_addr);
+	ASSERT(err >= 0);
+
+	fsck->chk.valid_node_cnt--;
+	fsck->chk.valid_blk_cnt--;
+	f2fs_clear_main_bitmap(sbi, ni.blk_addr);
+
+	for (i = 0; i < ADDRS_PER_BLOCK; i++) {
+		addr = le32_to_cpu(node->dn.addr[i]);
+		if (!addr)
+			continue;
+		fsck->chk.valid_blk_cnt--;
+		if (addr == NEW_ADDR)
+			continue;
+		f2fs_clear_main_bitmap(sbi, addr);
+	}
+
+	free(node);
+}
+
+static void fsck_failed_reconnect_file_idnode(struct f2fs_sb_info *sbi,
+					      nid_t nid)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_node *node;
+	struct node_info ni;
+	nid_t tmp;
+	int i, err;
+
+	node = calloc(F2FS_BLKSIZE, 1);
+	ASSERT(node);
+
+	get_node_info(sbi, nid, &ni);
+	err = dev_read_block(node, ni.blk_addr);
+	ASSERT(err >= 0);
+
+	fsck->chk.valid_node_cnt--;
+	fsck->chk.valid_blk_cnt--;
+	f2fs_clear_main_bitmap(sbi, ni.blk_addr);
+
+	for (i = 0; i < NIDS_PER_BLOCK; i++) {
+		tmp = le32_to_cpu(node->in.nid[i]);
+		if (!tmp)
+			continue;
+		fsck_failed_reconnect_file_dnode(sbi, tmp);
+	}
+
+	free(node);
+}
+
+static void fsck_failed_reconnect_file_didnode(struct f2fs_sb_info *sbi,
+					       nid_t nid)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_node *node;
+	struct node_info ni;
+	nid_t tmp;
+	int i, err;
+
+	node = calloc(F2FS_BLKSIZE, 1);
+	ASSERT(node);
+
+	get_node_info(sbi, nid, &ni);
+	err = dev_read_block(node, ni.blk_addr);
+	ASSERT(err >= 0);
+
+	fsck->chk.valid_node_cnt--;
+	fsck->chk.valid_blk_cnt--;
+	f2fs_clear_main_bitmap(sbi, ni.blk_addr);
+
+	for (i = 0; i < NIDS_PER_BLOCK; i++) {
+		tmp = le32_to_cpu(node->in.nid[i]);
+		if (!tmp)
+			continue;
+		fsck_failed_reconnect_file_idnode(sbi, tmp);
+	}
+
+	free(node);
+}
+
+/*
+ * Counters and main_area_bitmap are already changed during checking
+ * inode block, so clear them. There is no need to clear new blocks
+ * allocted to lost+found.
+ */
+static void fsck_failed_reconnect_file(struct f2fs_sb_info *sbi, nid_t ino)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_node *node;
+	struct node_info ni;
+	nid_t nid;
+	int ofs, i, err;
+
+	node = calloc(F2FS_BLKSIZE, 1);
+	ASSERT(node);
+
+	get_node_info(sbi, ino, &ni);
+	err = dev_read_block(node, ni.blk_addr);
+	ASSERT(err >= 0);
+
+	/* clear inode counters */
+	fsck->chk.valid_inode_cnt--;
+	fsck->chk.valid_node_cnt--;
+	fsck->chk.valid_blk_cnt--;
+	f2fs_clear_main_bitmap(sbi, ni.blk_addr);
+
+	/* clear xnid counters */
+	if (node->i.i_xattr_nid) {
+		nid = le32_to_cpu(node->i.i_xattr_nid);
+		fsck->chk.valid_node_cnt--;
+		fsck->chk.valid_blk_cnt--;
+		get_node_info(sbi, nid, &ni);
+		f2fs_clear_main_bitmap(sbi, ni.blk_addr);
+	}
+
+	/* clear data counters */
+	if(!(node->i.i_inline & F2FS_INLINE_DATA)) {
+		ofs = get_extra_isize(node);
+		for (i = 0; i < ADDRS_PER_INODE(&node->i); i++) {
+			block_t addr = le32_to_cpu(node->i.i_addr[ofs + i]);
+			if (!addr)
+				continue;
+			fsck->chk.valid_blk_cnt--;
+			if (addr == NEW_ADDR)
+				continue;
+			f2fs_clear_main_bitmap(sbi, addr);
+		}
+	}
+
+	for (i = 0; i < 5; i++) {
+		nid = le32_to_cpu(node->i.i_nid[i]);
+		if (!nid)
+			continue;
+
+		switch (i) {
+		case 0: /* direct node */
+		case 1:
+			fsck_failed_reconnect_file_dnode(sbi, nid);
+			break;
+		case 2: /* indirect node */
+		case 3:
+			fsck_failed_reconnect_file_idnode(sbi, nid);
+			break;
+		case 4: /* double indirect node */
+			fsck_failed_reconnect_file_didnode(sbi, nid);
+			break;
+		}
+	}
+
+	free(node);
+}
+
+/*
+ * Scan unreachable nids and find only regular file inodes. If these files
+ * are not corrupted, reconnect them to lost+found.
+ *
+ * Since all unreachable nodes are already checked, we can allocate new
+ * blocks safely.
+ *
+ * This function returns the number of files been reconnected.
+ */
+static int fsck_reconnect_file(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_node *lpf_node, *node;
+	struct node_info ni;
+	char *reconnect_bitmap;
+	u32 blk_cnt;
+	nid_t nid;
+	int err, cnt = 0, ftype;
+
+	node = calloc(F2FS_BLKSIZE, 1);
+	ASSERT(node);
+
+	reconnect_bitmap = calloc(fsck->nat_area_bitmap_sz, 1);
+	ASSERT(reconnect_bitmap);
+
+	for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
+		if (f2fs_test_bit(nid, fsck->nat_area_bitmap)) {
+			if (is_qf_ino(F2FS_RAW_SUPER(sbi), nid)) {
+				DBG(1, "Not support quota inode [0x%x]\n",
+				    nid);
+				continue;
+			}
+
+			get_node_info(sbi, nid, &ni);
+			err = dev_read_block(node, ni.blk_addr);
+			ASSERT(err >= 0);
+
+			/* reconnection will restore these nodes if needed */
+			if (node->footer.ino != node->footer.nid) {
+				DBG(1, "Not support non-inode node [0x%x]\n",
+				    nid);
+				continue;
+			}
+
+			if (S_ISDIR(le16_to_cpu(node->i.i_mode))) {
+				DBG(1, "Not support directory inode [0x%x]\n",
+				    nid);
+				continue;
+			}
+
+			ftype = map_de_type(le16_to_cpu(node->i.i_mode));
+			if (sanity_check_nid(sbi, nid, node, ftype,
+					     TYPE_INODE, &ni)) {
+				ASSERT_MSG("Invalid nid [0x%x]\n", nid);
+				continue;
+			}
+
+			DBG(1, "Check inode 0x%x\n", nid);
+			blk_cnt = 1;
+			fsck_chk_inode_blk(sbi, nid, F2FS_FT_REG_FILE,
+					   node, &blk_cnt, &ni, NULL);
+
+			f2fs_set_bit(nid, reconnect_bitmap);
+		}
+	}
+
+	lpf_node = fsck_get_lpf(sbi);
+	if (!lpf_node)
+		goto out;
+
+	for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
+		if (f2fs_test_bit(nid, reconnect_bitmap)) {
+			get_node_info(sbi, nid, &ni);
+			err = dev_read_block(node, ni.blk_addr);
+			ASSERT(err >= 0);
+
+			if (fsck_do_reconnect_file(sbi, lpf_node, node)) {
+				DBG(1, "Failed to reconnect inode [0x%x]\n",
+				    nid);
+				fsck_failed_reconnect_file(sbi, nid);
+				continue;
+			}
+
+			quota_add_inode_usage(fsck->qctx, nid, &node->i);
+
+			DBG(1, "Reconnected inode [0x%x] to lost+found\n", nid);
+			cnt++;
+		}
+	}
+
+out:
+	free(node);
+	free(lpf_node);
+	free(reconnect_bitmap);
+	return cnt;
+}
+
 int fsck_verify(struct f2fs_sb_info *sbi)
 {
 	unsigned int i = 0;
@@ -2057,6 +2431,16 @@ int fsck_verify(struct f2fs_sb_info *sbi)
 
 	printf("\n");
 
+	if (c.feature & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) {
+		for (i = 0; i < fsck->nr_nat_entries; i++)
+			if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0)
+				break;
+		if (i < fsck->nr_nat_entries) {
+			i = fsck_reconnect_file(sbi);
+			printf("[FSCK] Reconnect %u files to lost+found\n", i);
+		}
+	}
+
 	for (i = 0; i < fsck->nr_nat_entries; i++) {
 		if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) {
 			printf("NID[0x%x] is unreachable\n", i);
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 648c2db..8e133fa 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -243,6 +243,9 @@ int f2fs_mkdir(struct f2fs_sb_info *, struct dentry *);
 int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
 int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
 int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);
+nid_t f2fs_lookup(struct f2fs_sb_info *, struct f2fs_node *, u8 *, int);
+int f2fs_add_link(struct f2fs_sb_info *, struct f2fs_node *,
+		const unsigned char *, int, nid_t, int, block_t, int);
 
 /* xattr.c */
 void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
diff --git a/fsck/mount.c b/fsck/mount.c
index b8e7643..545f862 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1587,6 +1587,8 @@ void update_nat_blkaddr(struct f2fs_sb_info *sbi, nid_t ino,
 	if (ino)
 		nat_block->entries[entry_off].ino = cpu_to_le32(ino);
 	nat_block->entries[entry_off].block_addr = cpu_to_le32(newaddr);
+	if (c.func == FSCK)
+		F2FS_FSCK(sbi)->entries[nid] = nat_block->entries[entry_off];
 
 	ret = dev_write_block(nat_block, block_addr);
 	ASSERT(ret >= 0);
-- 
2.14.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH v2 7/7] fsck.f2fs: reconnect unreachable files to lost+found
       [not found]     ` <8abbaedf-ae3b-741f-d36f-d65f96739065@huawei.com>
@ 2018-02-28  5:16       ` Jaegeuk Kim
  0 siblings, 0 replies; 10+ messages in thread
From: Jaegeuk Kim @ 2018-02-28  5:16 UTC (permalink / raw)
  To: Sheng Yong; +Cc: miaoxie, linux-f2fs-devel

On 02/26, Sheng Yong wrote:
> Hi, Chao
> 
> On 2018/2/26 16:23, Chao Yu wrote:
> > On 2018/2/23 11:18, Sheng Yong wrote:
> > > This patch introduces lost_found feature to fsck. If a file is found
> > > unreachable by fsck. Fsck tries to reconnect the file to lost+found
> > > directory:
> > >    1. Scan all unreachable file inodes, ignore non-inodes ones and
> > >       directories.
> > >    2. Check them and fix incorrupted data to make sure filesystem
> > >       metadata (mainly counters and main/nat bitmap) are all consistent.
> > >    3. Reconnect these files to lost+found. If lost+found does not exist,
> > >       create it first. During reconnecting, expand lost+found's dentry
> > >       block automatically. Reconnected files are renamed after its ino
> > >       number.
> > >    4. If reconnect fails drop the node and restore filesystem metadata.
> > > 
> > > Signed-off-by: Sheng Yong <shengyong1@huawei.com>
> > > ---
> > >   fsck/dir.c   |  19 ++-
> > >   fsck/fsck.c  | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> > >   fsck/fsck.h  |   3 +
> > >   fsck/mount.c |   2 +
> > >   4 files changed, 409 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/fsck/dir.c b/fsck/dir.c
> > > index b2ea18f..567a4e9 100644
> > > --- a/fsck/dir.c
> > > +++ b/fsck/dir.c
> > > @@ -176,6 +176,23 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi,
> > >   	return 0;
> > >   }
> [...]
> > > +
> > > +static int fsck_do_reconnect_file(struct f2fs_sb_info *sbi,
> > > +				  struct f2fs_node *lpf,
> > > +				  struct f2fs_node *fnode)
> > > +{
> > > +	char name[80];
> > > +	size_t namelen;
> > > +	nid_t ino = le32_to_cpu(fnode->footer.ino);
> > > +	struct node_info ni;
> > > +	int ret;
> > > +
> > > +	namelen = snprintf(name, 80, "%u", ino);
> > > +	if (namelen >= 80)
> > > +		/* ignore terminating '\0', should never happen */
> > > +		namelen = 79;
> > > +
> > > +	if (f2fs_lookup(sbi, lpf, (u8 *)name, namelen)) {
> > > +		ASSERT_MSG("Name %s already exist in lost+found", name);
> > > +		return -EEXIST;
> > > +	}
> > > +
> > > +	get_node_info(sbi, le32_to_cpu(lpf->footer.ino), &ni);
> > > +	ret = f2fs_add_link(sbi, lpf, (unsigned char *)name, namelen,
> > > +			    ino, F2FS_FT_REG_FILE, ni.blk_addr, 0);
> > 
> > Need to change F2FS_FT_REG_FILE to ftype due to we expect to reconnect all kinds
> > of inode except directory, right?
> > 
> Right. My bad, will fix this in next version. Thanks.

Hi Sheng,

I merged this series except this patch. Please update this one only. :)

Thanks,

> 
> > > +	if (ret) {
> > > +		ASSERT_MSG("Failed to add inode [0x%x] to lost+found", ino);
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	/* update fnode */
> > > +	memcpy(fnode->i.i_name, name, namelen);
> > > +	fnode->i.i_namelen = cpu_to_le32(namelen);
> > > +	fnode->i.i_pino = c.lpf_ino;
> > > +	get_node_info(sbi, le32_to_cpu(fnode->footer.ino), &ni);
> > > +	ret = dev_write_block(fnode, ni.blk_addr);
> > > +	ASSERT(ret >= 0);
> > > +
> > > +	DBG(1, "Reconnect inode [0x%x] to lost+found\n", ino);
> > > +	return 0;
> > > +}
> > > +
> [...]
> > > +
> > > +/*
> > > + * Scan unreachable nids and find only regular file inodes. If these files
> > > + * are not corrupted, reconnect them to lost+found.
> > > + *
> > > + * Since all unreachable nodes are already checked, we can allocate new
> > > + * blocks safely.
> > > + *
> > > + * This function returns the number of files been reconnected.
> > > + */
> > > +static int fsck_reconnect_file(struct f2fs_sb_info *sbi)
> > > +{
> > > +	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
> > > +	struct f2fs_node *lpf_node, *node;
> > > +	struct node_info ni;
> > > +	char *reconnect_bitmap;
> > > +	u32 blk_cnt;
> > > +	nid_t nid;
> > > +	int err, cnt = 0, ftype;
> > > +
> > > +	node = calloc(F2FS_BLKSIZE, 1);
> > > +	ASSERT(node);
> > > +
> > > +	reconnect_bitmap = calloc(fsck->nat_area_bitmap_sz, 1);
> > > +	ASSERT(reconnect_bitmap);
> > > +
> > > +	for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
> > > +		if (f2fs_test_bit(nid, fsck->nat_area_bitmap)) {
> > > +			if (is_qf_ino(F2FS_RAW_SUPER(sbi), nid)) {
> > > +				DBG(1, "Not support quota inode [0x%x]\n",
> > > +				    nid);
> > > +				continue;
> > > +			}
> > > +
> > > +			get_node_info(sbi, nid, &ni);
> > > +			err = dev_read_block(node, ni.blk_addr);
> > > +			ASSERT(err >= 0);
> > > +
> > > +			/* reconnection will restore these nodes if needed */
> > > +			if (node->footer.ino != node->footer.nid) {
> > > +				DBG(1, "Not support non-inode node [0x%x]\n",
> > > +				    nid);
> > > +				continue;
> > > +			}
> > > +
> > > +			if (S_ISDIR(le16_to_cpu(node->i.i_mode))) {
> > > +				DBG(1, "Not support directory inode [0x%x]\n",
> > > +				    nid);
> > > +				continue;
> > > +			}
> > > +
> > > +			ftype = map_de_type(le16_to_cpu(node->i.i_mode));
> > > +			if (sanity_check_nid(sbi, nid, node, ftype,
> > > +					     TYPE_INODE, &ni)) {
> > > +				ASSERT_MSG("Invalid nid [0x%x]\n", nid);
> > > +				continue;
> > > +			}
> > > +
> > > +			DBG(1, "Check inode 0x%x\n", nid);
> > > +			blk_cnt = 1;
> > > +			fsck_chk_inode_blk(sbi, nid, F2FS_FT_REG_FILE,
> > 
> > Ditto,
> > 
> Will fix it :)
> 
> Thanks,
> Sheng
> 
> > Thanks,
> > 
> > > +					   node, &blk_cnt, &ni, NULL);
> > > +
> > > +			f2fs_set_bit(nid, reconnect_bitmap);
> > > +		}
> > > +	}
> > > +
> > > +	lpf_node = fsck_get_lpf(sbi);
> > > +	if (!lpf_node)
> > > +		goto out;
> > > +
> > > +	for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
> > > +		if (f2fs_test_bit(nid, reconnect_bitmap)) {
> > > +			get_node_info(sbi, nid, &ni);
> > > +			err = dev_read_block(node, ni.blk_addr);
> > > +			ASSERT(err >= 0);
> > > +
> > > +			if (fsck_do_reconnect_file(sbi, lpf_node, node)) {
> > > +				DBG(1, "Failed to reconnect inode [0x%x]\n",
> > > +				    nid);
> > > +				fsck_failed_reconnect_file(sbi, nid);
> > > +				continue;
> > > +			}
> > > +
> > > +			quota_add_inode_usage(fsck->qctx, nid, &node->i);
> > > +
> > > +			DBG(1, "Reconnected inode [0x%x] to lost+found\n", nid);
> > > +			cnt++;
> > > +		}
> > > +	}
> > > +
> > > +out:
> > > +	free(node);
> > > +	free(lpf_node);
> > > +	free(reconnect_bitmap);
> > > +	return cnt;
> > > +}
> > > +
> > >   int fsck_verify(struct f2fs_sb_info *sbi)
> > >   {
> > >   	unsigned int i = 0;
> > > @@ -2057,6 +2431,16 @@ int fsck_verify(struct f2fs_sb_info *sbi)
> > >   	printf("\n");
> > > +	if (c.feature & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) {
> > > +		for (i = 0; i < fsck->nr_nat_entries; i++)
> > > +			if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0)
> > > +				break;
> > > +		if (i < fsck->nr_nat_entries) {
> > > +			i = fsck_reconnect_file(sbi);
> > > +			printf("[FSCK] Reconnect %u files to lost+found\n", i);
> > > +		}
> > > +	}
> > > +
> > >   	for (i = 0; i < fsck->nr_nat_entries; i++) {
> > >   		if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) {
> > >   			printf("NID[0x%x] is unreachable\n", i);
> > > diff --git a/fsck/fsck.h b/fsck/fsck.h
> > > index 648c2db..8e133fa 100644
> > > --- a/fsck/fsck.h
> > > +++ b/fsck/fsck.h
> > > @@ -243,6 +243,9 @@ int f2fs_mkdir(struct f2fs_sb_info *, struct dentry *);
> > >   int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
> > >   int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
> > >   int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);
> > > +nid_t f2fs_lookup(struct f2fs_sb_info *, struct f2fs_node *, u8 *, int);
> > > +int f2fs_add_link(struct f2fs_sb_info *, struct f2fs_node *,
> > > +		const unsigned char *, int, nid_t, int, block_t, int);
> > >   /* xattr.c */
> > >   void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
> > > diff --git a/fsck/mount.c b/fsck/mount.c
> > > index b8e7643..545f862 100644
> > > --- a/fsck/mount.c
> > > +++ b/fsck/mount.c
> > > @@ -1587,6 +1587,8 @@ void update_nat_blkaddr(struct f2fs_sb_info *sbi, nid_t ino,
> > >   	if (ino)
> > >   		nat_block->entries[entry_off].ino = cpu_to_le32(ino);
> > >   	nat_block->entries[entry_off].block_addr = cpu_to_le32(newaddr);
> > > +	if (c.func == FSCK)
> > > +		F2FS_FSCK(sbi)->entries[nid] = nat_block->entries[entry_off];
> > >   	ret = dev_write_block(nat_block, block_addr);
> > >   	ASSERT(ret >= 0);
> > > 
> > 
> > 
> > .
> > 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH v2 5/7] mkfs.f2fs: create lost+found directory
  2018-02-23  3:17 ` [RFC PATCH v2 5/7] mkfs.f2fs: create lost+found directory Sheng Yong
@ 2018-02-28  5:25   ` Jaegeuk Kim
  0 siblings, 0 replies; 10+ messages in thread
From: Jaegeuk Kim @ 2018-02-28  5:25 UTC (permalink / raw)
  To: Sheng Yong; +Cc: hyojun, miaoxie, linux-f2fs-devel

On 02/23, Sheng Yong wrote:
> This patch introduces a new feature F2FS_FEATURE_LOST_FOUND. It can be
> switched on by indicating `-O lost_found'. If LOST_FOUND feature is
> enabled, an empty directory lost+found is created by mkfs.
> 
> This is a preparation for fsck. During fsck, the directory is used to
> save unreachable files, which have no parent directory or their parent
> directory is removed by fsck. Encrypted files are also allowed to be
> saved here.
> 
> Signed-off-by: Sheng Yong <shengyong1@huawei.com>
> ---
>  fsck/mount.c            |   3 +
>  include/f2fs_fs.h       |   6 ++
>  mkfs/f2fs_format.c      | 224 +++++++++++++++++++++++++++++++++++++++++++++---
>  mkfs/f2fs_format_main.c |   2 +
>  4 files changed, 223 insertions(+), 12 deletions(-)
> 
> diff --git a/fsck/mount.c b/fsck/mount.c
> index 46cb571..6482721 100644
> --- a/fsck/mount.c
> +++ b/fsck/mount.c
> @@ -460,6 +460,9 @@ void print_sb_state(struct f2fs_super_block *sb)
>  	if (f & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
>  		MSG(0, "%s", " inode_crtime");
>  	}
> +	if (f & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) {
> +		MSG(0, "%s", " lost_found");
> +	}
>  	MSG(0, "\n");
>  	MSG(0, "Info: superblock encrypt level = %d, salt = ",
>  					sb->encryption_level);
> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
> index ca4522d..093c402 100644
> --- a/include/f2fs_fs.h
> +++ b/include/f2fs_fs.h
> @@ -291,6 +291,8 @@ static inline uint64_t bswap_64(uint64_t val)
>  
>  #define VERSION_LEN	256
>  
> +#define LPF "lost+found"
> +
>  enum f2fs_config_func {
>  	MKFS,
>  	FSCK,
> @@ -369,6 +371,9 @@ struct f2fs_configuration {
>  	u_int32_t next_free_nid;
>  	u_int32_t quota_inum;
>  	u_int32_t quota_dnum;
> +	u_int32_t lpf_inum;
> +	u_int32_t lpf_dnum;
> +	u_int32_t lpf_ino;
>  
>  	/* defragmentation parameters */
>  	int defrag_shrink;
> @@ -557,6 +562,7 @@ enum {
>  #define F2FS_FEATURE_FLEXIBLE_INLINE_XATTR	0x0040
>  #define F2FS_FEATURE_QUOTA_INO		0x0080
>  #define F2FS_FEATURE_INODE_CRTIME	0x0100
> +#define F2FS_FEATURE_LOST_FOUND		0x0200
>  
>  #define MAX_VOLUME_NAME		512
>  
> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
> index 5eaeff4..4145c79 100644
> --- a/mkfs/f2fs_format.c
> +++ b/mkfs/f2fs_format.c
> @@ -426,6 +426,9 @@ static int f2fs_prepare_super_block(void)
>  					qtype, c.next_free_nid - 1);
>  	}
>  
> +	if (c.feature & cpu_to_le32(F2FS_FEATURE_LOST_FOUND))
> +		c.lpf_ino = c.next_free_nid++;
> +
>  	if (total_zones <= 6) {
>  		MSG(1, "\tError: %d zones: Need more zones "
>  			"by shrinking zone size\n", total_zones);
> @@ -608,9 +611,10 @@ static int f2fs_write_check_point_pack(void)
>  		set_cp(cur_data_segno[i], 0xffffffff);
>  	}
>  
> -	set_cp(cur_node_blkoff[0], 1 + c.quota_inum);
> -	set_cp(cur_data_blkoff[0], 1 + c.quota_dnum);
> -	set_cp(valid_block_count, 2 + c.quota_inum + c.quota_dnum);
> +	set_cp(cur_node_blkoff[0], 1 + c.quota_inum + c.lpf_inum);
> +	set_cp(cur_data_blkoff[0], 1 + c.quota_dnum + c.lpf_dnum);
> +	set_cp(valid_block_count, 2 + c.quota_inum + c.quota_dnum +
> +			c.lpf_inum + c.lpf_dnum);
>  	set_cp(rsvd_segment_count, c.reserved_segments);
>  	set_cp(overprov_segment_count, (get_sb(segment_count_main) -
>  			get_cp(rsvd_segment_count)) *
> @@ -642,8 +646,8 @@ static int f2fs_write_check_point_pack(void)
>  
>  	set_cp(ckpt_flags, flags);
>  	set_cp(cp_pack_start_sum, 1 + get_sb(cp_payload));
> -	set_cp(valid_node_count, 1 + c.quota_inum);
> -	set_cp(valid_inode_count, 1 + c.quota_inum);
> +	set_cp(valid_node_count, 1 + c.quota_inum + c.lpf_inum);
> +	set_cp(valid_inode_count, 1 + c.quota_inum + c.lpf_inum);
>  	set_cp(next_free_nid, c.next_free_nid);
>  	set_cp(sit_ver_bitmap_bytesize, ((get_sb(segment_count_sit) / 2) <<
>  			get_sb(log_blocks_per_seg)) / 8);
> @@ -702,7 +706,7 @@ static int f2fs_write_check_point_pack(void)
>  	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
>  
>  	journal = &sum->journal;
> -	journal->n_nats = cpu_to_le16(1 + c.quota_inum);
> +	journal->n_nats = cpu_to_le16(1 + c.quota_inum + c.lpf_inum);
>  	journal->nat_j.entries[0].nid = sb->root_ino;
>  	journal->nat_j.entries[0].ne.version = 0;
>  	journal->nat_j.entries[0].ne.ino = sb->root_ino;
> @@ -723,6 +727,16 @@ static int f2fs_write_check_point_pack(void)
>  		i++;
>  	}
>  
> +	if (c.lpf_inum) {
> +		journal->nat_j.entries[i].nid = cpu_to_le32(c.lpf_ino);
> +		journal->nat_j.entries[i].ne.version = 0;
> +		journal->nat_j.entries[i].ne.ino = cpu_to_le32(c.lpf_ino);
> +		journal->nat_j.entries[i].ne.block_addr = cpu_to_le32(
> +				get_sb(main_blkaddr) +
> +				get_cp(cur_node_segno[0]) *
> +				c.blks_per_seg + i);
> +	}
> +
>  	memcpy(sum_compact_p, &journal->n_nats, SUM_JOURNAL_SIZE);
>  	sum_compact_p += SUM_JOURNAL_SIZE;
>  
> @@ -732,10 +746,13 @@ static int f2fs_write_check_point_pack(void)
>  	journal->sit_j.entries[0].segno = cp->cur_node_segno[0];
>  	journal->sit_j.entries[0].se.vblocks =
>  				cpu_to_le16((CURSEG_HOT_NODE << 10) |
> -						(1 + c.quota_inum));
> +						(1 + c.quota_inum + c.lpf_inum));
>  	f2fs_set_bit(0, (char *)journal->sit_j.entries[0].se.valid_map);
>  	for (i = 1; i <= c.quota_inum; i++)
>  		f2fs_set_bit(i, (char *)journal->sit_j.entries[0].se.valid_map);
> +	if (c.lpf_inum)
> +		f2fs_set_bit(i, (char *)journal->sit_j.entries[0].se.valid_map);
> +
>  	journal->sit_j.entries[1].segno = cp->cur_node_segno[1];
>  	journal->sit_j.entries[1].se.vblocks =
>  				cpu_to_le16((CURSEG_WARM_NODE << 10));
> @@ -747,10 +764,12 @@ static int f2fs_write_check_point_pack(void)
>  	journal->sit_j.entries[3].segno = cp->cur_data_segno[0];
>  	journal->sit_j.entries[3].se.vblocks =
>  				cpu_to_le16((CURSEG_HOT_DATA << 10) |
> -						(1 + c.quota_dnum));
> +						(1 + c.quota_dnum + c.lpf_dnum));
>  	f2fs_set_bit(0, (char *)journal->sit_j.entries[3].se.valid_map);
>  	for (i = 1; i <= c.quota_dnum; i++)
>  		f2fs_set_bit(i, (char *)journal->sit_j.entries[3].se.valid_map);
> +	if (c.lpf_dnum)
> +		f2fs_set_bit(i, (char *)journal->sit_j.entries[3].se.valid_map);
>  
>  	journal->sit_j.entries[4].segno = cp->cur_data_segno[1];
>  	journal->sit_j.entries[4].se.vblocks =
> @@ -780,6 +799,11 @@ static int f2fs_write_check_point_pack(void)
>  		off += QUOTA_DATA(qtype);
>  	}
>  
> +	if (c.lpf_dnum) {
> +		(sum_entry + off)->nid = cpu_to_le32(c.lpf_ino);
> +		(sum_entry + off)->ofs_in_node = 0;
> +	}
> +
>  	/* warm data summary, nothing to do */
>  	/* cold data summary, nothing to do */
>  
> @@ -804,6 +828,11 @@ static int f2fs_write_check_point_pack(void)
>  		sum->entries[1 + i].ofs_in_node = 0;
>  		i++;
>  	}
> +	if (c.lpf_inum) {
> +		i++;
> +		sum->entries[i].nid = cpu_to_le32(c.lpf_ino);
> +		sum->entries[i].ofs_in_node = 0;
> +	}
>  
>  	cp_seg_blk++;
>  	DBG(1, "\tWriting Segment summary for HOT_NODE, at offset 0x%08"PRIx64"\n",
> @@ -963,7 +992,7 @@ static int f2fs_discard_obsolete_dnode(void)
>  	offset += c.cur_seg[CURSEG_WARM_NODE] * c.blks_per_seg;
>  
>  	last_inode_pos = start_inode_pos +
> -		c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg + c.quota_inum;
> +		c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg + c.quota_inum + c.lpf_inum;
>  
>  	do {
>  		if (offset < get_sb(main_blkaddr) || offset >= end_blkaddr)
> @@ -1016,7 +1045,10 @@ static int f2fs_write_root_inode(void)
>  			c.blks_per_seg + 1);
>  
>  	raw_node->i.i_mode = cpu_to_le16(0x41ed);
> -	raw_node->i.i_links = cpu_to_le32(2);
> +	if (c.lpf_ino)
> +		raw_node->i.i_links = cpu_to_le32(3);
> +	else
> +		raw_node->i.i_links = cpu_to_le32(2);
>  	raw_node->i.i_uid = cpu_to_le32(getuid());
>  	raw_node->i.i_gid = cpu_to_le32(getgid());
>  
> @@ -1122,10 +1154,16 @@ static int f2fs_write_default_quota(int qtype, unsigned int blkaddr,
>  	dqblk.dqb_pad = cpu_to_le32(0);
>  	dqblk.dqb_ihardlimit = cpu_to_le64(0);
>  	dqblk.dqb_isoftlimit = cpu_to_le64(0);
> -	dqblk.dqb_curinodes = cpu_to_le64(1);
> +	if (c.lpf_ino)
> +		dqblk.dqb_curinodes = cpu_to_le64(2);
> +	else
> +		dqblk.dqb_curinodes = cpu_to_le64(1);
>  	dqblk.dqb_bhardlimit = cpu_to_le64(0);
>  	dqblk.dqb_bsoftlimit = cpu_to_le64(0);
> -	dqblk.dqb_curspace = cpu_to_le64(4096);
> +	if (c.lpf_ino)
> +		dqblk.dqb_curspace = cpu_to_le64(8192);
> +	else
> +		dqblk.dqb_curspace = cpu_to_le64(4096);
>  	dqblk.dqb_btime = cpu_to_le64(0);
>  	dqblk.dqb_itime = cpu_to_le64(0);
>  
> @@ -1300,6 +1338,142 @@ static int f2fs_update_nat_root(void)
>  	return 0;
>  }
>  
> +static u_int64_t f2fs_add_default_dentry_lpf(void)
> +{
> +	struct f2fs_dentry_block *dent_blk;
> +	u_int64_t data_blk_offset = 0;
> +
> +	dent_blk = calloc(F2FS_BLKSIZE, 1);
> +	if (dent_blk == NULL) {
> +		MSG(1, "\tError: Calloc Failed for dent_blk!!!\n");
> +		return -1;
> +	}
> +
> +	dent_blk->dentry[0].hash_code = 0;
> +	dent_blk->dentry[0].ino = cpu_to_le32(c.lpf_ino);
> +	dent_blk->dentry[0].name_len = cpu_to_le16(1);
> +	dent_blk->dentry[0].file_type = F2FS_FT_DIR;
> +	memcpy(dent_blk->filename[0], ".", 1);
> +
> +	dent_blk->dentry[1].hash_code = 0;
> +	dent_blk->dentry[1].ino = sb->root_ino;
> +	dent_blk->dentry[1].name_len = cpu_to_le16(2);
> +	dent_blk->dentry[1].file_type = F2FS_FT_DIR;
> +	memcpy(dent_blk->filename[1], "..", 2);
> +
> +	test_and_set_bit_le(0, dent_blk->dentry_bitmap);
> +	test_and_set_bit_le(1, dent_blk->dentry_bitmap);
> +
> +	data_blk_offset = get_sb(main_blkaddr);
> +	data_blk_offset += c.cur_seg[CURSEG_HOT_DATA] * c.blks_per_seg +
> +		1 + c.quota_dnum;
> +
> +	DBG(1, "\tWriting default dentry lost+found, at offset 0x%08"PRIx64"\n",
> +			data_blk_offset);
> +	if (dev_write_block(dent_blk, data_blk_offset)) {
> +		MSG(1, "\tError While writing the dentry_blk to disk!!!\n");
> +		free(dent_blk);
> +		return -1;
> +	}
> +
> +	free(dent_blk);
> +	c.lpf_dnum++;
> +	return data_blk_offset;
> +}
> +
> +static int f2fs_write_lpf_inode(void)
> +{
> +	struct f2fs_node *raw_node;
> +	u_int64_t blk_size_bytes, data_blk_nor;
> +	u_int64_t main_area_node_seg_blk_offset;
> +	int err = 0;
> +
> +	ASSERT(c.lpf_ino);
> +
> +	raw_node = calloc(F2FS_BLKSIZE, 1);
> +	if (raw_node == NULL) {
> +		MSG(1, "\tError: Calloc Failed for raw_node!!!\n");
> +		return -1;
> +	}
> +
> +	raw_node->footer.nid = cpu_to_le32(c.lpf_ino);
> +	raw_node->footer.ino = raw_node->footer.nid;
> +	raw_node->footer.cp_ver = cpu_to_le64(1);
> +	raw_node->footer.next_blkaddr = cpu_to_le32(
> +			get_sb(main_blkaddr) +
> +			c.cur_seg[CURSEG_HOT_NODE] * c.blks_per_seg +
> +			1 + c.quota_inum + 1);
> +
> +	raw_node->i.i_mode = cpu_to_le16(0x41c0); /* 0700 */
> +	raw_node->i.i_links = cpu_to_le32(2);
> +	raw_node->i.i_uid = cpu_to_le32(getuid());
> +	raw_node->i.i_gid = cpu_to_le32(getgid());
> +
> +	blk_size_bytes = 1 << get_sb(log_blocksize);
> +	raw_node->i.i_size = cpu_to_le64(1 * blk_size_bytes); /* dentry */
> +	raw_node->i.i_blocks = cpu_to_le64(2);
> +
> +	raw_node->i.i_atime = cpu_to_le32(time(NULL));
> +	raw_node->i.i_atime_nsec = 0;
> +	raw_node->i.i_ctime = cpu_to_le32(time(NULL));
> +	raw_node->i.i_ctime_nsec = 0;
> +	raw_node->i.i_mtime = cpu_to_le32(time(NULL));
> +	raw_node->i.i_mtime_nsec = 0;
> +	raw_node->i.i_generation = 0;
> +	raw_node->i.i_xattr_nid = 0;
> +	raw_node->i.i_flags = 0;
> +	raw_node->i.i_pino = le32_to_cpu(sb->root_ino);
> +	raw_node->i.i_namelen = le32_to_cpu(strlen(LPF));
> +	memcpy(raw_node->i.i_name, LPF, strlen(LPF));
> +	raw_node->i.i_current_depth = cpu_to_le32(1);
> +	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
> +
> +	if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
> +		raw_node->i.i_inline = F2FS_EXTRA_ATTR;
> +		raw_node->i.i_extra_isize =
> +			cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
> +	}
> +
> +	if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA))
> +		raw_node->i.i_projid = cpu_to_le32(F2FS_DEF_PROJID);
> +
> +	if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
> +		raw_node->i.i_crtime = cpu_to_le32(time(NULL));
> +		raw_node->i.i_crtime_nsec = 0;
> +	}
> +
> +	data_blk_nor = f2fs_add_default_dentry_lpf();

Could you please check data type of data_blk_nor?

> +	if (data_blk_nor < 0) {

Can't do this.

> +		MSG(1, "\tError: Failed to add default dentries for lost+found!!!\n");
> +		err = -1;
> +		goto exit;
> +	}
> +	raw_node->i.i_addr[get_extra_isize(raw_node)] = cpu_to_le32(data_blk_nor);

cpu_to_le32() is wrong.

Please check all the data types in the series.

Thanks,

> +
> +	if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
> +		raw_node->i.i_inode_checksum =
> +			cpu_to_le32(f2fs_inode_chksum(raw_node));
> +
> +	main_area_node_seg_blk_offset = get_sb(main_blkaddr);
> +	main_area_node_seg_blk_offset += c.cur_seg[CURSEG_HOT_NODE] *
> +		c.blks_per_seg + c.quota_inum + 1;
> +
> +	DBG(1, "\tWriting lost+found inode (hot node), %x %x %x at offset 0x%08"PRIu64"\n",
> +			get_sb(main_blkaddr),
> +			c.cur_seg[CURSEG_HOT_NODE],
> +			c.blks_per_seg, main_area_node_seg_blk_offset);
> +	if (dev_write_block(raw_node, main_area_node_seg_blk_offset)) {
> +		MSG(1, "\tError: While writing the raw_node to disk!!!\n");
> +		err = -1;
> +		goto exit;
> +	}
> +
> +	c.lpf_inum++;
> +exit:
> +	free(raw_node);
> +	return err;
> +}
> +
>  static int f2fs_add_default_dentry_root(void)
>  {
>  	struct f2fs_dentry_block *dent_blk = NULL;
> @@ -1327,6 +1501,23 @@ static int f2fs_add_default_dentry_root(void)
>  	test_and_set_bit_le(0, dent_blk->dentry_bitmap);
>  	test_and_set_bit_le(1, dent_blk->dentry_bitmap);
>  
> +	if (c.lpf_ino) {
> +		int len = strlen(LPF);
> +		f2fs_hash_t hash = f2fs_dentry_hash((unsigned char *)LPF, len);
> +
> +		dent_blk->dentry[2].hash_code = cpu_to_le32(hash);
> +		dent_blk->dentry[2].ino = cpu_to_le32(c.lpf_ino);
> +		dent_blk->dentry[2].name_len = cpu_to_le16(len);
> +		dent_blk->dentry[2].file_type = F2FS_FT_DIR;
> +		memcpy(dent_blk->filename[2], LPF, F2FS_SLOT_LEN);
> +
> +		memcpy(dent_blk->filename[3], LPF + F2FS_SLOT_LEN,
> +				len - F2FS_SLOT_LEN);
> +
> +		test_and_set_bit_le(2, dent_blk->dentry_bitmap);
> +		test_and_set_bit_le(3, dent_blk->dentry_bitmap);
> +	}
> +
>  	data_blk_offset = get_sb(main_blkaddr);
>  	data_blk_offset += c.cur_seg[CURSEG_HOT_DATA] *
>  				c.blks_per_seg;
> @@ -1364,6 +1555,14 @@ static int f2fs_create_root_dir(void)
>  		}
>  	}
>  
> +	if (c.feature & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) {
> +		err = f2fs_write_lpf_inode();
> +		if (err < 0) {
> +			MSG(1, "\tError: Failed to write lost+found inode!!!\n");
> +			goto exit;
> +		}
> +	}
> +
>  #ifndef WITH_ANDROID
>  	err = f2fs_discard_obsolete_dnode();
>  	if (err < 0) {
> @@ -1437,6 +1636,7 @@ int f2fs_format_device(void)
>  		MSG(0, "\tError: Failed to write the Super Block!!!\n");
>  		goto exit;
>  	}
> +
>  exit:
>  	if (err)
>  		MSG(0, "\tError: Could not format the device!!!\n");
> diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c
> index 120eeba..aeda5f4 100644
> --- a/mkfs/f2fs_format_main.c
> +++ b/mkfs/f2fs_format_main.c
> @@ -95,6 +95,8 @@ static void parse_feature(const char *features)
>  		c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
>  	} else if (!strcmp(features, "inode_crtime")) {
>  		c.feature |= cpu_to_le32(F2FS_FEATURE_INODE_CRTIME);
> +	} else if (!strcmp(features, "lost_found")) {
> +		c.feature |= cpu_to_le32(F2FS_FEATURE_LOST_FOUND);
>  	} else {
>  		MSG(0, "Error: Wrong features\n");
>  		mkfs_usage();
> -- 
> 2.14.1

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-02-28  5:25 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-23  3:17 [RFC PATCH v2 0/7] f2fs-tools: introduce F2FS_FEATURE_LOST_FOUND feature Sheng Yong
2018-02-23  3:17 ` [RFC PATCH v2 1/7] fsck.f2fs: fix typo Sheng Yong
2018-02-23  3:17 ` [RFC PATCH v2 2/7] mkfs.f2fs: introduce mkfs parameters in f2fs_configuration Sheng Yong
2018-02-23  3:17 ` [RFC PATCH v2 3/7] f2fs-tools: init f2fs_configuration as 0 Sheng Yong
2018-02-23  3:17 ` [RFC PATCH v2 4/7] fsck.f2fs: integrate sanity_check_inode to __check_inode_mode Sheng Yong
2018-02-23  3:17 ` [RFC PATCH v2 5/7] mkfs.f2fs: create lost+found directory Sheng Yong
2018-02-28  5:25   ` Jaegeuk Kim
2018-02-23  3:18 ` [RFC PATCH v2 6/7] fsck.f2fs: read nat block if nat entry is invalid Sheng Yong
2018-02-23  3:18 ` [RFC PATCH v2 7/7] fsck.f2fs: reconnect unreachable files to lost+found Sheng Yong
     [not found]   ` <0c849139-fdbe-9362-770c-ad4e9da57142@huawei.com>
     [not found]     ` <8abbaedf-ae3b-741f-d36f-d65f96739065@huawei.com>
2018-02-28  5:16       ` Jaegeuk Kim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.