fs/erofs: Introduce new features including ztailpacking, fragments and dedupe

This patch updates erofs driver code to catch up with the latest code of
erofs_utils (commit e4939f9eaa177e05d697ace85d8dc283e25dc2ed).

LZMA will be supported in the separate patch later.

Signed-off-by: Yifan Zhao <zhaoyifan@sjtu.edu.cn>
Reviewed-by: Huang Jianan <jnhuang95@gmail.com>
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 8277d9b..d339262 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -9,7 +9,7 @@
 	sbi->feature_incompat = feature;
 
 	/* check if current kernel meets all mandatory requirements */
-	if (feature & (~EROFS_ALL_FEATURE_INCOMPAT)) {
+	if (feature & ~EROFS_ALL_FEATURE_INCOMPAT) {
 		erofs_err("unidentified incompatible feature %x, please upgrade kernel version",
 			  feature & ~EROFS_ALL_FEATURE_INCOMPAT);
 		return false;
@@ -40,14 +40,18 @@
 
 	sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1;
 	sbi->devs = calloc(ondisk_extradevs, sizeof(*sbi->devs));
+	if (!sbi->devs)
+		return -ENOMEM;
 	pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
 	for (i = 0; i < ondisk_extradevs; ++i) {
 		struct erofs_deviceslot dis;
 		int ret;
 
 		ret = erofs_dev_read(0, &dis, pos, sizeof(dis));
-		if (ret < 0)
+		if (ret < 0) {
+			free(sbi->devs);
 			return ret;
+		}
 
 		sbi->devs[i].mapped_blkaddr = dis.mapped_blkaddr;
 		sbi->total_blocks += dis.blocks;
@@ -58,42 +62,41 @@
 
 int erofs_read_superblock(void)
 {
-	char data[EROFS_BLKSIZ];
+	u8 data[EROFS_MAX_BLOCK_SIZE];
 	struct erofs_super_block *dsb;
-	unsigned int blkszbits;
 	int ret;
 
-	ret = erofs_blk_read(data, 0, 1);
+	ret = erofs_blk_read(data, 0, erofs_blknr(sizeof(data)));
 	if (ret < 0) {
-		erofs_dbg("cannot read erofs superblock: %d", ret);
+		erofs_err("cannot read erofs superblock: %d", ret);
 		return -EIO;
 	}
 	dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET);
 
 	ret = -EINVAL;
 	if (le32_to_cpu(dsb->magic) != EROFS_SUPER_MAGIC_V1) {
-		erofs_dbg("cannot find valid erofs superblock");
+		erofs_err("cannot find valid erofs superblock");
 		return ret;
 	}
 
 	sbi.feature_compat = le32_to_cpu(dsb->feature_compat);
 
-	blkszbits = dsb->blkszbits;
-	/* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
-	if (blkszbits != LOG_BLOCK_SIZE) {
-		erofs_err("blksize %u isn't supported on this platform",
-			  1 << blkszbits);
+	sbi.blkszbits = dsb->blkszbits;
+	if (sbi.blkszbits < 9 ||
+	    sbi.blkszbits > ilog2(EROFS_MAX_BLOCK_SIZE)) {
+		erofs_err("blksize %llu isn't supported on this platform",
+			  erofs_blksiz() | 0ULL);
 		return ret;
-	}
-
-	if (!check_layout_compatibility(&sbi, dsb))
+	} else if (!check_layout_compatibility(&sbi, dsb)) {
 		return ret;
+	}
 
 	sbi.primarydevice_blocks = le32_to_cpu(dsb->blocks);
 	sbi.meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
 	sbi.xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
 	sbi.islotbits = EROFS_ISLOTBITS;
 	sbi.root_nid = le16_to_cpu(dsb->root_nid);
+	sbi.packed_nid = le64_to_cpu(dsb->packed_nid);
 	sbi.inos = le64_to_cpu(dsb->inos);
 	sbi.checksum = le32_to_cpu(dsb->checksum);