[PATCH 3/4] fs/erofs: allocate data buffers on heap with alignment (2/3)

Michael Walle mwalle at kernel.org
Tue Mar 24 00:42:19 AEDT 2026


The data buffers are used to transfer from or to hardware peripherals.
Often, there are restrictions on addresses, i.e. they have to be aligned
at a certain size. Thus, allocate the data on the heap instead of the
stack (at a random address alignment).

This will also have the benefit, that large data (4k) isn't eating up
the stack.

The actual change is split across multiple patches. This one allocates
the inode buffer on the heap. Before, if there was an extended inode,
the buffer was read incrementally. Now, as we need to have an aligned
buffer, the first part is just read again to keep the original buffer
address.

Signed-off-by: Michael Walle <mwalle at kernel.org>
---
 fs/erofs/namei.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c
index b493ef97a09..7ce62955540 100644
--- a/fs/erofs/namei.c
+++ b/fs/erofs/namei.c
@@ -13,14 +13,20 @@ static dev_t erofs_new_decode_dev(u32 dev)
 int erofs_read_inode_from_disk(struct erofs_inode *vi)
 {
 	int ret, ifmt;
-	char buf[sizeof(struct erofs_inode_extended)];
+	char *buf;
 	struct erofs_inode_compact *dic;
 	struct erofs_inode_extended *die;
 	const erofs_off_t inode_loc = iloc(vi->nid);
 
+	buf = malloc_cache_aligned(sizeof(struct erofs_inode_extended));
+	if (!buf)
+		return -ENOMEM;
+
 	ret = erofs_dev_read(0, buf, inode_loc, sizeof(*dic));
-	if (ret < 0)
+	if (ret < 0) {
+		free(buf);
 		return -EIO;
+	}
 
 	dic = (struct erofs_inode_compact *)buf;
 	ifmt = le16_to_cpu(dic->i_format);
@@ -29,17 +35,18 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi)
 	if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) {
 		erofs_err("unsupported datalayout %u of nid %llu",
 			  vi->datalayout, vi->nid | 0ULL);
+		free(buf);
 		return -EOPNOTSUPP;
 	}
 	switch (erofs_inode_version(ifmt)) {
 	case EROFS_INODE_LAYOUT_EXTENDED:
 		vi->inode_isize = sizeof(struct erofs_inode_extended);
 
-		ret = erofs_dev_read(0, buf + sizeof(*dic),
-				     inode_loc + sizeof(*dic),
-				     sizeof(*die) - sizeof(*dic));
-		if (ret < 0)
+		ret = erofs_dev_read(0, buf, inode_loc, sizeof(*die));
+		if (ret < 0) {
+			free(buf);
 			return -EIO;
+		}
 
 		die = (struct erofs_inode_extended *)buf;
 		vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount);
@@ -113,6 +120,7 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi)
 	default:
 		erofs_err("unsupported on-disk inode version %u of nid %llu",
 			  erofs_inode_version(ifmt), vi->nid | 0ULL);
+		free(buf);
 		return -EOPNOTSUPP;
 	}
 
@@ -121,6 +129,7 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi)
 		if (vi->u.chunkformat & ~EROFS_CHUNK_FORMAT_ALL) {
 			erofs_err("unsupported chunk format %x of nid %llu",
 				  vi->u.chunkformat, vi->nid | 0ULL);
+			free(buf);
 			return -EOPNOTSUPP;
 		}
 		vi->u.chunkbits = sbi.blkszbits +
-- 
2.47.3



More information about the Linux-erofs mailing list