From: Michael Walle <mwalle@kernel.org>
To: Huang Jianan <jnhuang95@gmail.com>, Tom Rini <trini@konsulko.com>
Cc: linux-erofs@lists.ozlabs.org, u-boot@lists.denx.de,
Michael Walle <mwalle@kernel.org>
Subject: [PATCH 4/4] fs/erofs: allocate data buffers on heap with alignment (3/3)
Date: Mon, 23 Mar 2026 14:42:20 +0100 [thread overview]
Message-ID: <20260323134305.2675822-5-mwalle@kernel.org> (raw)
In-Reply-To: <20260323134305.2675822-1-mwalle@kernel.org>
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 handles the
"struct erofs_map_blocks" which itself contains a data buffer. Add some
helpers to alloc and free the struct because the data buffer will now be
malloc'ed separately.
Signed-off-by: Michael Walle <mwalle@kernel.org>
---
fs/erofs/data.c | 103 +++++++++++++++++++++++++++++---------------
fs/erofs/internal.h | 4 +-
fs/erofs/zmap.c | 29 ++++++++++---
3 files changed, 94 insertions(+), 42 deletions(-)
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 2fe345d80ee..d10c00fe9f3 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -174,32 +174,60 @@ int erofs_read_one_data(struct erofs_map_blocks *map, char *buffer, u64 offset,
return 0;
}
+struct erofs_map_blocks *erofs_alloc_map_blocks(void)
+{
+ struct erofs_map_blocks *map;
+
+ map = malloc(sizeof(struct erofs_map_blocks));
+ if (!map)
+ return NULL;
+
+ memset(map, 0, sizeof(struct erofs_map_blocks));
+ map->index = UINT_MAX;
+
+ map->mpage = malloc_cache_aligned(EROFS_MAX_BLOCK_SIZE);
+ if (!map->mpage) {
+ free(map);
+ return NULL;
+ }
+
+ return map;
+}
+
+void erofs_free_map_blocks(struct erofs_map_blocks *map)
+{
+ free(map->mpage);
+ free(map);
+}
+
static int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
erofs_off_t size, erofs_off_t offset)
{
- struct erofs_map_blocks map = {
- .index = UINT_MAX,
- };
+ struct erofs_map_blocks *map;
int ret;
erofs_off_t ptr = offset;
+ map = erofs_alloc_map_blocks();
+ if (!map)
+ return -ENOMEM;
+
while (ptr < offset + size) {
char *const estart = buffer + ptr - offset;
erofs_off_t eend, moff = 0;
- map.m_la = ptr;
- ret = erofs_map_blocks(inode, &map, 0);
+ map->m_la = ptr;
+ ret = erofs_map_blocks(inode, map, 0);
if (ret)
- return ret;
+ goto out;
- DBG_BUGON(map.m_plen != map.m_llen);
+ DBG_BUGON(map->m_plen != map->m_llen);
/* trim extent */
- eend = min(offset + size, map.m_la + map.m_llen);
- DBG_BUGON(ptr < map.m_la);
+ eend = min(offset + size, map->m_la + map->m_llen);
+ DBG_BUGON(ptr < map->m_la);
- if (!(map.m_flags & EROFS_MAP_MAPPED)) {
- if (!map.m_llen) {
+ if (!(map->m_flags & EROFS_MAP_MAPPED)) {
+ if (!map->m_llen) {
/* reached EOF */
memset(estart, 0, offset + size - ptr);
ptr = offset + size;
@@ -210,17 +238,21 @@ static int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
continue;
}
- if (ptr > map.m_la) {
- moff = ptr - map.m_la;
- map.m_la = ptr;
+ if (ptr > map->m_la) {
+ moff = ptr - map->m_la;
+ map->m_la = ptr;
}
- ret = erofs_read_one_data(&map, estart, moff, eend - map.m_la);
+ ret = erofs_read_one_data(map, estart, moff, eend - map->m_la);
if (ret)
- return ret;
+ goto out;
ptr = eend;
}
- return 0;
+
+ ret = 0;
+out:
+ erofs_free_map_blocks(map);
+ return ret;
}
int z_erofs_read_one_data(struct erofs_inode *inode,
@@ -282,19 +314,21 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
erofs_off_t size, erofs_off_t offset)
{
erofs_off_t end, length, skip;
- struct erofs_map_blocks map = {
- .index = UINT_MAX,
- };
+ struct erofs_map_blocks *map;
bool trimmed;
unsigned int bufsize = 0;
char *raw = NULL;
int ret = 0;
+ map = erofs_alloc_map_blocks();
+ if (!map)
+ return -ENOMEM;
+
end = offset + size;
while (end > offset) {
- map.m_la = end - 1;
+ map->m_la = end - 1;
- ret = z_erofs_map_blocks_iter(inode, &map, 0);
+ ret = z_erofs_map_blocks_iter(inode, map, 0);
if (ret)
break;
@@ -302,31 +336,31 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
* trim to the needed size if the returned extent is quite
* larger than requested, and set up partial flag as well.
*/
- if (end < map.m_la + map.m_llen) {
- length = end - map.m_la;
+ if (end < map->m_la + map->m_llen) {
+ length = end - map->m_la;
trimmed = true;
} else {
- DBG_BUGON(end != map.m_la + map.m_llen);
- length = map.m_llen;
+ DBG_BUGON(end != map->m_la + map->m_llen);
+ length = map->m_llen;
trimmed = false;
}
- if (map.m_la < offset) {
- skip = offset - map.m_la;
+ if (map->m_la < offset) {
+ skip = offset - map->m_la;
end = offset;
} else {
skip = 0;
- end = map.m_la;
+ end = map->m_la;
}
- if (!(map.m_flags & EROFS_MAP_MAPPED)) {
+ if (!(map->m_flags & EROFS_MAP_MAPPED)) {
memset(buffer + end - offset, 0, length - skip);
- end = map.m_la;
+ end = map->m_la;
continue;
}
- if (map.m_plen > bufsize) {
- bufsize = map.m_plen;
+ if (map->m_plen > bufsize) {
+ bufsize = map->m_plen;
free(raw);
raw = malloc_cache_aligned(bufsize);
if (!raw) {
@@ -335,13 +369,14 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
}
}
- ret = z_erofs_read_one_data(inode, &map, raw,
+ ret = z_erofs_read_one_data(inode, map, raw,
buffer + end - offset, skip, length,
trimmed);
if (ret < 0)
break;
}
free(raw);
+ erofs_free_map_blocks(map);
return ret < 0 ? ret : 0;
}
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 13c862325a6..2e471d66c7d 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -291,7 +291,7 @@ enum {
#define EROFS_MAP_PARTIAL_REF (1 << BH_Partialref)
struct erofs_map_blocks {
- char mpage[EROFS_MAX_BLOCK_SIZE];
+ char *mpage;
erofs_off_t m_pa, m_la;
u64 m_plen, m_llen;
@@ -367,6 +367,8 @@ static inline int erofs_get_occupied_size(const struct erofs_inode *inode,
}
/* data.c */
+struct erofs_map_blocks *erofs_alloc_map_blocks(void);
+void erofs_free_map_blocks(struct erofs_map_blocks *map);
int erofs_getxattr(struct erofs_inode *vi, const char *name, char *buffer,
size_t buffer_size);
int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c
index 1ded934a5d7..3060b2e9ec6 100644
--- a/fs/erofs/zmap.c
+++ b/fs/erofs/zmap.c
@@ -75,28 +75,43 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
}
if (vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER) {
- struct erofs_map_blocks map = { .index = UINT_MAX };
+ struct erofs_map_blocks *map;
+
+ map = erofs_alloc_map_blocks();
+ if (!map) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
vi->idata_size = le16_to_cpu(h->h_idata_size);
- ret = z_erofs_do_map_blocks(vi, &map,
+ ret = z_erofs_do_map_blocks(vi, map,
EROFS_GET_BLOCKS_FINDTAIL);
- if (!map.m_plen ||
- erofs_blkoff(map.m_pa) + map.m_plen > erofs_blksiz()) {
+ if (!map->m_plen ||
+ erofs_blkoff(map->m_pa) + map->m_plen > erofs_blksiz()) {
erofs_err("invalid tail-packing pclustersize %llu",
- map.m_plen | 0ULL);
+ map->m_plen | 0ULL);
ret = -EFSCORRUPTED;
+ erofs_free_map_blocks(map);
goto err_out;
}
+ erofs_free_map_blocks(map);
if (ret < 0)
goto err_out;
}
if (vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER &&
!(h->h_clusterbits >> Z_EROFS_FRAGMENT_INODE_BIT)) {
- struct erofs_map_blocks map = { .index = UINT_MAX };
+ struct erofs_map_blocks *map;
+
+ map = erofs_alloc_map_blocks();
+ if (!map) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
vi->fragmentoff = le32_to_cpu(h->h_fragmentoff);
- ret = z_erofs_do_map_blocks(vi, &map,
+ ret = z_erofs_do_map_blocks(vi, map,
EROFS_GET_BLOCKS_FINDTAIL);
+ erofs_free_map_blocks(map);
if (ret < 0)
goto err_out;
}
--
2.47.3
prev parent reply other threads:[~2026-03-23 13:43 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-23 13:42 [PATCH 0/4] fs/erofs: major alignment fixes Michael Walle
2026-03-23 13:42 ` [PATCH 1/4] fs/erofs: align the malloc'ed data Michael Walle
2026-03-23 14:41 ` Gao Xiang
2026-03-23 15:08 ` Michael Walle
2026-03-23 15:13 ` Gao Xiang
2026-03-23 13:42 ` [PATCH 2/4] fs/erofs: allocate data buffers on heap with alignment (1/3) Michael Walle
2026-03-23 13:42 ` [PATCH 3/4] fs/erofs: allocate data buffers on heap with alignment (2/3) Michael Walle
2026-03-23 13:42 ` Michael Walle [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260323134305.2675822-5-mwalle@kernel.org \
--to=mwalle@kernel.org \
--cc=jnhuang95@gmail.com \
--cc=linux-erofs@lists.ozlabs.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox