diff mbox series

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

Message ID 20260323134305.2675822-4-mwalle@kernel.org
State New
Delegated to: Tom Rini
Headers show
Series fs/erofs: major alignment fixes | expand

Commit Message

Michael Walle March 23, 2026, 1:42 p.m. UTC
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@kernel.org>
---
 fs/erofs/namei.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)
diff mbox series

Patch

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 +