@@ -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 +
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(-)