Snap for 5422062 from 4ab6bc23d24ab881ac3a0eaf6629ff4f2ae77d3b to qt-release

Change-Id: I712404a8f193660fa4bf67764ac988f284c3d79b
diff --git a/.gitignore b/.gitignore
index 3f04e85..c1341da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,6 +50,7 @@
 /tools/fibmap.f2fs
 /tools/parse.f2fs
 /tools/f2fscrypt
+/tools/f2fs_io/f2fs_io
 /tools/sg_write_buffer/sg_write_buffer
 
 # cscope files
diff --git a/Android.bp b/Android.bp
index 42abc49..fcaf0d0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -198,4 +198,58 @@
     host_supported: false,
     cflags: ["--static"],
     srcs: ["tools/check_f2fs.c"],
+    product_specific: true,
+}
+
+cc_defaults {
+    name: "tools-defaults",
+    cflags: [
+        "-Wno-unused-function",
+    ],
+    local_include_dirs: [
+        "include",
+    ],
+    target: {
+        windows: {
+            enabled: false,
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+    product_specific: true,
+}
+
+cc_binary {
+    name: "f2fscrypt",
+    defaults: [
+        "tools-defaults",
+    ],
+    shared_libs: [
+        "libext2_uuid",
+    ],
+    srcs: [
+        "tools/f2fscrypt.c",
+        "tools/sha512.c",
+    ],
+}
+
+cc_binary {
+    name: "f2fsstat",
+    defaults: [
+        "tools-defaults",
+    ],
+    srcs: [
+        "tools/f2fstat.c",
+    ],
+}
+
+cc_binary {
+    name: "f2fs.fibmap",
+    defaults: [
+        "tools-defaults",
+    ],
+    srcs: [
+        "tools/fibmap.c",
+    ],
 }
diff --git a/METADATA b/METADATA
index 56231ff..ae27821 100644
--- a/METADATA
+++ b/METADATA
@@ -8,10 +8,10 @@
     type: GIT
     value: "https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git"
   }
-  version: "22d758e2e6af210dc9e6cdf99438f063383ba72f"
+  version: "c6968d44b9c772e3e6c1669c69cfc7d9d044c324"
   last_upgrade_date {
     year: 2019
-    month: 02
-    day: 26
+    month: 03
+    day: 27
   }
 }
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 0d0d5e2..93f01e5 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -369,13 +369,16 @@
 
 static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
 {
-	return (nid <= (NAT_ENTRY_PER_BLOCK *
+	return (nid < (NAT_ENTRY_PER_BLOCK *
 			le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_nat)
 			<< (sbi->log_blocks_per_seg - 1)));
 }
 
 static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
 {
+	if (addr == NULL_ADDR || addr == NEW_ADDR)
+		return 1;
+
 	if (addr >= le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count) ||
 				addr < SM_I(sbi)->main_blkaddr) {
 		DBG(1, "block addr [0x%x]\n", addr);
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 97eea21..a17555c 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 #include "fsck.h"
+#include "xattr.h"
 #include "quotaio.h"
 #include <time.h>
 
@@ -731,15 +732,41 @@
 		if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
 			if (node_blk->i.i_extra_isize >
 				cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE)) {
+				FIX_MSG("ino[0x%x] recover i_extra_isize "
+					"from %u to %lu",
+					nid,
+					le16_to_cpu(node_blk->i.i_extra_isize),
+					F2FS_TOTAL_EXTRA_ATTR_SIZE);
 				node_blk->i.i_extra_isize =
 					cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
 				need_fix = 1;
 			}
 		} else {
+			FIX_MSG("ino[0x%x] remove F2FS_EXTRA_ATTR "
+				"flag in i_inline:%u",
+				nid, node_blk->i.i_inline);
 			/* we don't support tuning F2FS_FEATURE_EXTRA_ATTR now */
 			node_blk->i.i_inline &= ~F2FS_EXTRA_ATTR;
 			need_fix = 1;
 		}
+
+		if ((c.feature &
+			cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR)) &&
+			(node_blk->i.i_inline & F2FS_INLINE_XATTR)) {
+			unsigned int inline_size =
+				le16_to_cpu(node_blk->i.i_inline_xattr_size);
+
+			if (!inline_size ||
+					inline_size > MAX_INLINE_XATTR_SIZE) {
+				FIX_MSG("ino[0x%x] recover inline xattr size "
+					"from %u to %u",
+					nid, inline_size,
+					DEFAULT_INLINE_XATTR_ADDRS);
+				node_blk->i.i_inline_xattr_size =
+					cpu_to_le16(DEFAULT_INLINE_XATTR_ADDRS);
+				need_fix = 1;
+			}
+		}
 	}
 	ofs = get_extra_isize(node_blk);
 
@@ -2007,6 +2034,8 @@
 		orphan_blks = __start_sum_addr(sbi) - 1;
 		flags |= CP_ORPHAN_PRESENT_FLAG;
 	}
+	if (is_set_ckpt_flags(cp, CP_TRIMMED_FLAG))
+		flags |= CP_TRIMMED_FLAG;
 	if (is_set_ckpt_flags(cp, CP_DISABLED_FLAG))
 		flags |= CP_DISABLED_FLAG;
 
diff --git a/fsck/mount.c b/fsck/mount.c
index 3966525..aa64e93 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1066,11 +1066,29 @@
 			f2fs_set_bit(nid, nm_i->nid_bitmap);
 	}
 
+	if (nats_in_cursum(journal) > NAT_JOURNAL_ENTRIES) {
+		MSG(0, "\tError: f2fs_init_nid_bitmap truncate n_nats(%u) to "
+			"NAT_JOURNAL_ENTRIES(%lu)\n",
+			nats_in_cursum(journal), NAT_JOURNAL_ENTRIES);
+		journal->n_nats = cpu_to_le16(NAT_JOURNAL_ENTRIES);
+	}
+
 	for (i = 0; i < nats_in_cursum(journal); i++) {
 		block_t addr;
 
 		addr = le32_to_cpu(nat_in_journal(journal, i).block_addr);
+		if (!IS_VALID_BLK_ADDR(sbi, addr)) {
+			MSG(0, "\tError: f2fs_init_nid_bitmap: addr(%u) is invalid!!!\n", addr);
+			journal->n_nats = cpu_to_le16(i);
+			continue;
+		}
+
 		nid = le32_to_cpu(nid_in_journal(journal, i));
+		if (!IS_VALID_NID(sbi, nid)) {
+			MSG(0, "\tError: f2fs_init_nid_bitmap: nid(%u) is invalid!!!\n", nid);
+			journal->n_nats = cpu_to_le16(i);
+			continue;
+		}
 		if (addr != NULL_ADDR)
 			f2fs_set_bit(nid, nm_i->nid_bitmap);
 	}
@@ -1305,20 +1323,26 @@
 	unsigned int bitmap_size;
 
 	sit_i = malloc(sizeof(struct sit_info));
-	if (!sit_i)
+	if (!sit_i) {
+		MSG(1, "\tError: Malloc failed for build_sit_info!\n");
 		return -ENOMEM;
+	}
 
 	SM_I(sbi)->sit_info = sit_i;
 
 	sit_i->sentries = calloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry), 1);
-	if (!sit_i->sentries)
-		return -ENOMEM;
+	if (!sit_i->sentries) {
+		MSG(1, "\tError: Calloc failed for build_sit_info!\n");
+		goto free_sit_info;
+	}
 
 	for (start = 0; start < TOTAL_SEGS(sbi); start++) {
 		sit_i->sentries[start].cur_valid_map
 			= calloc(SIT_VBLOCK_MAP_SIZE, 1);
-		if (!sit_i->sentries[start].cur_valid_map)
-			return -ENOMEM;
+		if (!sit_i->sentries[start].cur_valid_map) {
+			MSG(1, "\tError: Calloc failed for build_sit_info!!\n");
+			goto free_validity_maps;
+		}
 	}
 
 	sit_segs = get_sb(segment_count_sit) >> 1;
@@ -1326,8 +1350,10 @@
 	src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
 
 	dst_bitmap = malloc(bitmap_size);
-	if (!dst_bitmap)
-		return -ENOMEM;
+	if (!dst_bitmap) {
+		MSG(1, "\tError: Malloc failed for build_sit_info!!\n");
+		goto free_validity_maps;
+	}
 
 	memcpy(dst_bitmap, src_bitmap, bitmap_size);
 
@@ -1340,6 +1366,16 @@
 	sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
 	sit_i->elapsed_time = get_cp(elapsed_time);
 	return 0;
+
+free_validity_maps:
+	for (--start ; start >= 0; --start)
+		free(sit_i->sentries[start].cur_valid_map);
+	free(sit_i->sentries);
+
+free_sit_info:
+	free(sit_i);
+
+	return -ENOMEM;
 }
 
 void reset_curseg(struct f2fs_sb_info *sbi, int type)
@@ -1517,7 +1553,7 @@
 		read_normal_summaries(sbi, type);
 }
 
-static void build_curseg(struct f2fs_sb_info *sbi)
+static int build_curseg(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
 	struct curseg_info *array;
@@ -1526,13 +1562,20 @@
 	int i;
 
 	array = malloc(sizeof(*array) * NR_CURSEG_TYPE);
-	ASSERT(array);
+	if (!array) {
+		MSG(1, "\tError: Malloc failed for build_curseg!\n");
+		return -ENOMEM;
+	}
 
 	SM_I(sbi)->curseg_array = array;
 
 	for (i = 0; i < NR_CURSEG_TYPE; i++) {
 		array[i].sum_blk = malloc(PAGE_CACHE_SIZE);
-		ASSERT(array[i].sum_blk);
+		if (!array[i].sum_blk) {
+			MSG(1, "\tError: Malloc failed for build_curseg!!\n");
+			goto seg_cleanup;
+		}
+
 		if (i <= CURSEG_COLD_DATA) {
 			blk_off = get_cp(cur_data_blkoff[i]);
 			segno = get_cp(cur_data_segno[i]);
@@ -1551,6 +1594,14 @@
 		array[i].alloc_type = cp->alloc_type[i];
 	}
 	restore_curseg_summaries(sbi);
+	return 0;
+
+seg_cleanup:
+	for(--i ; i >=0; --i)
+		free(array[i].sum_blk);
+	free(array);
+
+	return -ENOMEM;
 }
 
 static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
@@ -1836,7 +1887,7 @@
 	node_info_from_raw_nat(ni, &raw_nat);
 }
 
-void build_sit_entries(struct f2fs_sb_info *sbi)
+static int build_sit_entries(struct f2fs_sb_info *sbi)
 {
 	struct sit_info *sit_i = SIT_I(sbi);
 	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
@@ -1847,7 +1898,11 @@
 	unsigned int i, segno;
 
 	sit_blk = calloc(BLOCK_SZ, 1);
-	ASSERT(sit_blk);
+	if (!sit_blk) {
+		MSG(1, "\tError: Calloc failed for build_sit_entries!\n");
+		return -ENOMEM;
+	}
+
 	for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) {
 		se = &sit_i->sentries[segno];
 
@@ -1867,18 +1922,20 @@
 		check_block_count(sbi, segno, &sit);
 		seg_info_from_raw_sit(se, &sit);
 	}
-
+	return 0;
 }
 
-int build_segment_manager(struct f2fs_sb_info *sbi)
+static int build_segment_manager(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
 	struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
 	struct f2fs_sm_info *sm_info;
 
 	sm_info = malloc(sizeof(struct f2fs_sm_info));
-	if (!sm_info)
+	if (!sm_info) {
+		MSG(1, "\tError: Malloc failed for build_segment_manager!\n");
 		return -ENOMEM;
+	}
 
 	/* init sm info */
 	sbi->sm_info = sm_info;
@@ -1890,11 +1947,10 @@
 	sm_info->main_segments = get_sb(segment_count_main);
 	sm_info->ssa_blkaddr = get_sb(ssa_blkaddr);
 
-	build_sit_info(sbi);
-
-	build_curseg(sbi);
-
-	build_sit_entries(sbi);
+	if (build_sit_info(sbi) || build_curseg(sbi) || build_sit_entries(sbi)) {
+		free(sm_info);
+		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -2305,6 +2361,8 @@
 		orphan_blks = __start_sum_addr(sbi) - 1;
 		flags |= CP_ORPHAN_PRESENT_FLAG;
 	}
+	if (is_set_ckpt_flags(cp, CP_TRIMMED_FLAG))
+		flags |= CP_TRIMMED_FLAG;
 	if (is_set_ckpt_flags(cp, CP_DISABLED_FLAG))
 		flags |= CP_DISABLED_FLAG;
 
diff --git a/fsck/xattr.h b/fsck/xattr.h
index e4a98e2..dc80faf 100644
--- a/fsck/xattr.h
+++ b/fsck/xattr.h
@@ -134,4 +134,9 @@
 		sizeof(struct f2fs_xattr_header) -		\
 		sizeof(struct f2fs_xattr_entry))
 
+#define MAX_INLINE_XATTR_SIZE						\
+			(DEF_ADDRS_PER_INODE -				\
+			F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) -	\
+			DEF_INLINE_RESERVED_SIZE -			\
+			MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
 #endif
diff --git a/include/android_config.h b/include/android_config.h
index 4582887..0613400 100644
--- a/include/android_config.h
+++ b/include/android_config.h
@@ -18,13 +18,11 @@
 #define HAVE_SYS_XATTR_H 1
 #define HAVE_UNISTD_H 1
 
-#define HAVE_ADD_KEY 1
 #define HAVE_FALLOCATE 1
 #define HAVE_FSETXATTR 1
 #define HAVE_FSTAT 1
 #define HAVE_FSTAT64 1
 #define HAVE_GETMNTENT 1
-#define HAVE_KEYCTL 1
 #define HAVE_LLSEEK 1
 #define HAVE_LSEEK64 1
 #define HAVE_MEMSET 1
@@ -48,13 +46,11 @@
 #define HAVE_SYS_XATTR_H 1
 #define HAVE_UNISTD_H 1
 
-#define HAVE_ADD_KEY 1
 #define HAVE_FALLOCATE 1
 #define HAVE_FSETXATTR 1
 #define HAVE_FSTAT 1
 #define HAVE_FSTAT64 1
 #define HAVE_GETMNTENT 1
-#define HAVE_KEYCTL 1
 #define HAVE_LLSEEK 1
 #define HAVE_MEMSET 1
 
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index a730688..e84cccc 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -52,6 +52,8 @@
 # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
 #elif defined(__LCLINT__)
 # define UNUSED(x) x
+#elif defined(__cplusplus)
+# define UNUSED(x)
 #else
 # define UNUSED(x) x
 #endif
@@ -1069,6 +1071,7 @@
 #define SIZE_OF_RESERVED	(PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
 				F2FS_SLOT_LEN) * \
 				NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
+#define MIN_INLINE_DENTRY_SIZE		40	/* just include '.' and '..' entries */
 
 /* One directory entry slot representing F2FS_SLOT_LEN-sized file name */
 struct f2fs_dir_entry {
@@ -1379,9 +1382,9 @@
 {
 	char *buf, *sub, *next;
 
-	buf = calloc(strlen(features) + 1, sizeof(char));
-	ASSERT(buf);
-	strncpy(buf, features, strlen(features) + 1);
+	buf = strdup(features);
+	if (!buf)
+		return -1;
 
 	for (sub = buf; sub && *sub; sub = next ? next + 1 : NULL) {
 		/* Skip the beginning blanks */
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index c692bf2..60b84e0 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -587,7 +587,7 @@
 		return NULL;
 	rootdev[ret] = '\0';
 
-	snprintf(rootdev, ret, "/dev/%s", buf);
+	snprintf(rootdev, ret + 1, "/dev/%s", buf);
 	return rootdev;
 #endif
 }
diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c
index b40c3d2..f848510 100644
--- a/lib/libf2fs_io.c
+++ b/lib/libf2fs_io.c
@@ -385,6 +385,7 @@
 			MSG(0, "\tError: Failed to close device file!!!\n");
 			break;
 		}
+		free(c.devices[i].path);
 	}
 	close(c.kd);
 
diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
index ee4f3e1..91f8cf2 100644
--- a/tools/f2fs_io/f2fs_io.c
+++ b/tools/f2fs_io/f2fs_io.c
@@ -374,19 +374,23 @@
 	if (argc == 3 && !strcmp(argv[2], "start")) {
 		printf("gc_urgent: start on %s\n", argv[1]);
 		sprintf(command, "echo %d > %s/%s/gc_urgent", 1, "/sys/fs/f2fs/", argv[1]);
-		system(command);
+		if (system(command))
+			exit(1);
 	} else if (argc == 3 && !strcmp(argv[2], "end")) {
 		printf("gc_urgent: end on %s\n", argv[1]);
 		sprintf(command, "echo %d > %s/%s/gc_urgent", 0, "/sys/fs/f2fs/", argv[1]);
-		system(command);
+		if (system(command))
+			exit(1);
 	} else if (argc == 4 && !strcmp(argv[2], "run")) {
 		printf("gc_urgent: start on %s for %d secs\n", argv[1], atoi(argv[3]));
 		sprintf(command, "echo %d > %s/%s/gc_urgent", 1, "/sys/fs/f2fs/", argv[1]);
-		system(command);
+		if (system(command))
+			exit(1);
 		sleep(atoi(argv[3]));
 		printf("gc_urgent: end on %s for %d secs\n", argv[1], atoi(argv[3]));
 		sprintf(command, "echo %d > %s/%s/gc_urgent", 0, "/sys/fs/f2fs/", argv[1]);
-		system(command);
+		if (system(command))
+			exit(1);
 	} else {
 		fputs("Excess arguments\n\n", stderr);
 		fputs(cmd->cmd_help, stderr);
diff --git a/tools/f2fs_io/f2fs_io.h b/tools/f2fs_io/f2fs_io.h
index 6b619bd..95fd5be 100644
--- a/tools/f2fs_io/f2fs_io.h
+++ b/tools/f2fs_io/f2fs_io.h
@@ -17,6 +17,8 @@
 # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
 #elif defined(__LCLINT__)
 # define UNUSED(x) x
+#elif defined(__cplusplus)
+# define UNUSED(x)
 #else
 # define UNUSED(x) x
 #endif
diff --git a/tools/f2fscrypt.c b/tools/f2fscrypt.c
index 81ef830..fe3e0ff 100644
--- a/tools/f2fscrypt.c
+++ b/tools/f2fscrypt.c
@@ -275,7 +275,8 @@
 	memset(in_passphrase, 0, sizeof(in_passphrase));
 }
 
-static void die_signal_handler(int signum, siginfo_t *siginfo, void *context)
+static void die_signal_handler(int UNUSED(signum),
+		siginfo_t *UNUSED(siginfo), void *UNUSED(context))
 {
 	clear_secrets();
 	exit(-1);
@@ -837,7 +838,8 @@
 "Give the invoking process (typically a shell) a new session keyring,\n" \
 "discarding its old session keyring.\n"
 
-static void do_new_session(int argc, char **argv, const struct cmd_desc *cmd)
+static void do_new_session(int argc, char **UNUSED(argv),
+					const struct cmd_desc *cmd)
 {
 	long keyid, ret;
 
@@ -872,7 +874,7 @@
 	{ NULL, NULL, NULL, NULL, 0 }
 };
 
-static void do_help(int argc, char **argv, const struct cmd_desc *cmd)
+static void do_help(int argc, char **argv, const struct cmd_desc *UNUSED(cmd))
 {
 	const struct cmd_desc *p;
 
diff --git a/tools/f2fstat.c b/tools/f2fstat.c
index 7f485b0..5b4d683 100644
--- a/tools/f2fstat.c
+++ b/tools/f2fstat.c
@@ -81,7 +81,7 @@
 	int ret;
 	char keyname[32];
 	char buf[4096];
-	struct mm_table key = { keyname, NULL };
+	struct mm_table key = { keyname, NULL, 0 };
 	struct mm_table *found;
 	int f2fstat_table_cnt;
 	char *head, *tail;
@@ -240,7 +240,7 @@
 
 	for (i = 0; i < 20; i++) {
 		ptr = (i == 0) ? strtok(res, " ") : strtok(NULL, " ");
-		strncpy(ptr_buf, name[i], strlen(name[i]));
+		strcpy(ptr_buf, name[i]);
 		if (i == 1) {
 			prev_index = ptr_buf - buf - 1;
 		} else if (i == 7) {