lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250422123612.261764-3-lihongbo22@huawei.com>
Date: Tue, 22 Apr 2025 12:36:10 +0000
From: Hongbo Li <lihongbo22@...wei.com>
To: <xiang@...nel.org>, <chao@...nel.org>, <huyue2@...lpad.com>,
	<jefflexu@...ux.alibaba.com>
CC: <linux-erofs@...ts.ozlabs.org>, <linux-kernel@...r.kernel.org>,
	<lihongbo22@...wei.com>
Subject: [PATCH RFC 2/4] erofs-utils: lib: Implement the main logic for --meta_fix option

The option --meta_fix will fix the metadata area, so for the data
area, we first dump them into a temporary file to avoid alloc buffer
from @g_sbi.bmgr. Then we remmap the blkaddr based on the offset in
@g_sbi.bmgr after metadata finishing, and dump it into @g_sbi.bmgr
directly.

Signed-off-by: Hongbo Li <lihongbo22@...wei.com>
---
 include/erofs/blobraw.h |  28 ++++++++++
 lib/Makefile.am         |   3 +-
 lib/blobraw.c           | 121 ++++++++++++++++++++++++++++++++++++++++
 lib/inode.c             |   6 ++
 mkfs/main.c             |  15 +++++
 5 files changed, 172 insertions(+), 1 deletion(-)
 create mode 100755 include/erofs/blobraw.h
 create mode 100755 lib/blobraw.c

diff --git a/include/erofs/blobraw.h b/include/erofs/blobraw.h
new file mode 100755
index 0000000..d56bb46
--- /dev/null
+++ b/include/erofs/blobraw.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */
+/*
+ * erofs-utils/lib/blobraw.h
+ *
+ * Copyright (C) 2025, HUAWEI, Inc.
+ */
+#ifndef __EROFS_BLOBRAW_H
+#define __EROFS_BLOBRAW_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "erofs/internal.h"
+
+void erofs_blobraw_remap_blkaddr(struct erofs_inode *inode);
+int erofs_blobraw_write_file(struct erofs_inode *inode, int fd);
+int erofs_blobraw_init();
+void erofs_blobraw_exit();
+int erofs_mkfs_dump_rawblob(struct erofs_sb_info *sbi, bool drop_blob);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/lib/Makefile.am b/lib/Makefile.am
index bdc74ad..c0804b3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -3,6 +3,7 @@
 noinst_LTLIBRARIES = liberofs.la
 noinst_HEADERS = $(top_srcdir)/include/erofs_fs.h \
       $(top_srcdir)/include/erofs/blobchunk.h \
+      $(top_srcdir)/include/erofs/blobraw.h \
       $(top_srcdir)/include/erofs/block_list.h \
       $(top_srcdir)/include/erofs/cache.h \
       $(top_srcdir)/include/erofs/compress.h \
@@ -33,7 +34,7 @@ noinst_HEADERS = $(top_srcdir)/include/erofs_fs.h \
 noinst_HEADERS += compressor.h
 liberofs_la_SOURCES = config.c io.c cache.c super.c inode.c xattr.c exclude.c \
 		      namei.c data.c compress.c compressor.c zmap.c decompress.c \
-		      compress_hints.c hashmap.c sha256.c blobchunk.c dir.c \
+		      compress_hints.c hashmap.c sha256.c blobchunk.c blobraw.c dir.c \
 		      fragments.c dedupe.c uuid_unparse.c uuid.c tar.c \
 		      block_list.c rebuild.c diskbuf.c bitops.c dedupe_ext.c
 
diff --git a/lib/blobraw.c b/lib/blobraw.c
new file mode 100755
index 0000000..248fc30
--- /dev/null
+++ b/lib/blobraw.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
+/*
+ * erofs-utils/lib/blobraw.c
+ *
+ * Copyright (C) 2025, HUAWEI, Inc.
+ */
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "erofs/blobraw.h"
+#include "erofs/print.h"
+#include "erofs/cache.h"
+#include "liberofs_private.h"
+
+static int blobfile = -1;		/* tmp fd for blob buffer */
+static erofs_blk_t remapped_base;	/* metadata block end address */
+static erofs_off_t bloboff;		/* current blob file offset */
+
+void erofs_blobraw_remap_blkaddr(struct erofs_inode *inode)
+{
+	if (inode->i_size > 0)
+		inode->u.i_blkaddr += remapped_base;
+}
+
+int erofs_blobraw_write_file(struct erofs_inode *inode, int fd)
+{
+	static u8 zeroed[EROFS_MAX_BLOCK_SIZE];
+	struct erofs_sb_info *sbi = inode->sbi;
+	unsigned int padding;
+	erofs_off_t foff;
+	ssize_t length, ret, isize = inode->i_size;
+	u64 pos_in, pos_out = bloboff;
+
+	pos_in = 0;
+	do {
+		length = min_t(erofs_off_t, isize,  SSIZE_MAX);
+		ret = erofs_copy_file_range(fd, &pos_in,
+				blobfile, &pos_out, length);
+	} while (ret > 0 && (isize -= ret));
+
+	foff = lseek(blobfile, inode->i_size, SEEK_CUR);
+	DBG_BUGON(foff != bloboff + inode->i_size);
+
+	padding = erofs_blkoff(sbi, inode->i_size);
+	if (padding) {
+		padding = erofs_blksiz(sbi) - padding;
+		ret = __erofs_io_write(blobfile, zeroed, padding);
+		if (ret > 0 && ret != padding)
+			return -EIO;
+	}
+
+	inode->datalayout = EROFS_INODE_FLAT_PLAIN;
+	inode->u.i_blkaddr = erofs_blknr(sbi, bloboff);
+	bloboff += round_up(inode->i_size, erofs_blksiz(sbi));
+
+	return 0;
+}
+
+int erofs_mkfs_dump_rawblob(struct erofs_sb_info *sbi, bool drop_blob)
+{
+	struct erofs_buffer_head *bh;
+	erofs_off_t blob_size;
+	ssize_t length, ret = 0;
+	u64 pos_in, pos_out;
+
+	if (blobfile < 0) {
+		erofs_err("dump rawblob failed");
+		return -1;
+	}
+
+	blob_size = bloboff;
+
+	bh = erofs_balloc(sbi->bmgr, DATA, blob_size, 0);
+	if (IS_ERR(bh))
+		return PTR_ERR(bh);
+
+	erofs_mapbh(NULL, bh->block);
+
+	pos_out = erofs_btell(bh, false);
+	remapped_base = erofs_blknr(sbi, pos_out);
+	pos_out += sbi->bdev.offset;
+
+	/* copy the raw blob data */
+	if (!drop_blob) {
+		pos_in = 0;
+		do {
+			length = min_t(erofs_off_t, blob_size,  SSIZE_MAX);
+			ret = erofs_copy_file_range(blobfile, &pos_in,
+					sbi->bdev.fd, &pos_out, length);
+		} while (ret > 0 && (blob_size -= ret));
+
+		if (ret >= 0) {
+			if (blob_size) {
+				erofs_err("failed to append the remaining %llu-byte blob data",
+					  blob_size);
+				ret = -EIO;
+			} else {
+				ret = 0;
+			}
+		}
+	}
+
+	erofs_bdrop(bh, false);
+	return ret;
+}
+
+int erofs_blobraw_init()
+{
+	blobfile = erofs_tmpfile();
+	if (blobfile < 0)
+		return -errno;
+
+	return 0;
+}
+
+void erofs_blobraw_exit()
+{
+	if (blobfile >= 0)
+		close(blobfile);
+}
diff --git a/lib/inode.c b/lib/inode.c
index 108aa9e..39257c7 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -28,6 +28,7 @@
 #include "erofs/block_list.h"
 #include "erofs/compress_hints.h"
 #include "erofs/blobchunk.h"
+#include "erofs/blobraw.h"
 #include "erofs/fragments.h"
 #include "liberofs_private.h"
 
@@ -579,6 +580,8 @@ int erofs_write_unencoded_file(struct erofs_inode *inode, int fd, u64 fpos)
 		return erofs_blob_write_chunked_file(inode, fd, fpos);
 	}
 
+	if (cfg.c_meta_fix)
+		return erofs_blobraw_write_file(inode, fd);
 	/* fallback to all data uncompressed */
 	return write_uncompressed_file_from_fd(inode, fd);
 }
@@ -600,6 +603,9 @@ int erofs_iflush(struct erofs_inode *inode)
 	else
 		off = erofs_iloc(inode);
 
+	if (S_ISREG(inode->i_mode) && cfg.c_meta_fix)
+		erofs_blobraw_remap_blkaddr(inode);
+
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
 	    S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode))
 		u1.rdev = cpu_to_le32(inode->u.i_rdev);
diff --git a/mkfs/main.c b/mkfs/main.c
index 42635c6..82db452 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -26,6 +26,7 @@
 #include "erofs/block_list.h"
 #include "erofs/compress_hints.h"
 #include "erofs/blobchunk.h"
+#include "erofs/blobraw.h"
 #include "erofs/fragments.h"
 #include "erofs/rebuild.h"
 #include "../lib/liberofs_private.h"
@@ -1422,6 +1423,12 @@ int main(int argc, char **argv)
 			return 1;
 	}
 
+	if (cfg.c_meta_fix) {
+		err = erofs_blobraw_init();
+		if (err)
+			return -1;
+	}
+
 	if (((erofstar.index_mode && !erofstar.headeronly_mode) &&
 	    !erofstar.mapfile) || cfg.c_blobdev_path) {
 		err = erofs_mkfs_init_devices(&g_sbi, 1);
@@ -1498,6 +1505,12 @@ int main(int argc, char **argv)
 			goto exit;
 	}
 
+	if (cfg.c_meta_fix) {
+		err = erofs_mkfs_dump_rawblob(&g_sbi, cfg.c_meta_fix);
+		if (err)
+			goto exit;
+	}
+
 	/* flush all buffers except for the superblock */
 	err = erofs_bflush(g_sbi.bmgr, NULL);
 	if (err)
@@ -1537,6 +1550,8 @@ exit:
 	erofs_cleanup_exclude_rules();
 	if (cfg.c_chunkbits)
 		erofs_blob_exit();
+	if (cfg.c_meta_fix)
+		erofs_blobraw_exit();
 	erofs_packedfile_exit(&g_sbi);
 	erofs_xattr_cleanup_name_prefixes();
 	erofs_rebuild_cleanup();
-- 
2.22.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ