[PATCH 2/3] erofs-utils: lib: tidy up erofs_blob_getchunk()
Gao Xiang
hsiangkao at linux.alibaba.com
Tue Jul 25 03:06:45 AEST 2023
Mainly get rid of memory allocation on each chunk.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
lib/blobchunk.c | 92 +++++++++++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 41 deletions(-)
diff --git a/lib/blobchunk.c b/lib/blobchunk.c
index c0df2f7..4619057 100644
--- a/lib/blobchunk.c
+++ b/lib/blobchunk.c
@@ -51,60 +51,57 @@ struct erofs_blobchunk *erofs_get_unhashed_chunk(erofs_off_t chunksize,
}
static struct erofs_blobchunk *erofs_blob_getchunk(struct erofs_sb_info *sbi,
- int fd, erofs_off_t chunksize)
+ u8 *buf, erofs_off_t chunksize)
{
static u8 zeroed[EROFS_MAX_BLOCK_SIZE];
- u8 *chunkdata, sha256[32];
- int ret;
- unsigned int hash;
- erofs_off_t blkpos;
struct erofs_blobchunk *chunk;
+ unsigned int hash, padding;
+ u8 sha256[32];
+ erofs_off_t blkpos;
+ int ret;
- chunkdata = malloc(chunksize);
- if (!chunkdata)
- return ERR_PTR(-ENOMEM);
-
- ret = read(fd, chunkdata, chunksize);
- if (ret < chunksize) {
- chunk = ERR_PTR(-EIO);
- goto out;
- }
- erofs_sha256(chunkdata, chunksize, sha256);
+ erofs_sha256(buf, chunksize, sha256);
hash = memhash(sha256, sizeof(sha256));
chunk = hashmap_get_from_hash(&blob_hashmap, hash, sha256);
if (chunk) {
DBG_BUGON(chunksize != chunk->chunksize);
- goto out;
+ erofs_dbg("Found duplicated chunk at %u", chunk->blkaddr);
+ return chunk;
}
+
chunk = malloc(sizeof(struct erofs_blobchunk));
- if (!chunk) {
- chunk = ERR_PTR(-ENOMEM);
- goto out;
- }
+ if (!chunk)
+ return ERR_PTR(-ENOMEM);
chunk->chunksize = chunksize;
+ memcpy(chunk->sha256, sha256, sizeof(sha256));
blkpos = ftell(blobfile);
DBG_BUGON(erofs_blkoff(sbi, blkpos));
- chunk->device_id = 0;
+
+ if (multidev)
+ chunk->device_id = 1;
+ else
+ chunk->device_id = 0;
chunk->blkaddr = erofs_blknr(sbi, blkpos);
- memcpy(chunk->sha256, sha256, sizeof(sha256));
- hashmap_entry_init(&chunk->ent, hash);
- hashmap_add(&blob_hashmap, chunk);
erofs_dbg("Writing chunk (%u bytes) to %u", chunksize, chunk->blkaddr);
- ret = fwrite(chunkdata, chunksize, 1, blobfile);
- if (ret == 1 && erofs_blkoff(sbi, chunksize))
- ret = fwrite(zeroed,
- erofs_blksiz(sbi) - erofs_blkoff(sbi, chunksize),
- 1, blobfile);
+ ret = fwrite(buf, chunksize, 1, blobfile);
+ padding = erofs_blkoff(sbi, chunksize);
+ if (ret == 1) {
+ padding = erofs_blkoff(sbi, chunksize);
+ if (padding) {
+ padding = erofs_blksiz(sbi) - padding;
+ ret = fwrite(zeroed, padding, 1, blobfile);
+ }
+ }
+
if (ret < 1) {
- hashmap_remove(&blob_hashmap, &chunk->ent);
free(chunk);
- chunk = ERR_PTR(-ENOSPC);
- goto out;
+ return ERR_PTR(-ENOSPC);
}
-out:
- free(chunkdata);
+
+ hashmap_entry_init(&chunk->ent, hash);
+ hashmap_add(&blob_hashmap, chunk);
return chunk;
}
@@ -189,6 +186,7 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd)
unsigned int count, unit;
struct erofs_inode_chunk_index *idx;
erofs_off_t pos, len, chunksize;
+ u8 *chunkdata;
int ret;
#ifdef SEEK_DATA
@@ -212,11 +210,17 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd)
else
unit = EROFS_BLOCK_MAP_ENTRY_SIZE;
- inode->extent_isize = count * unit;
- idx = malloc(count * max(sizeof(*idx), sizeof(void *)));
- if (!idx)
+ chunkdata = malloc(chunksize);
+ if (!chunkdata)
return -ENOMEM;
- inode->chunkindexes = idx;
+
+ inode->extent_isize = count * unit;
+ inode->chunkindexes = malloc(count * max(sizeof(*idx), sizeof(void *)));
+ if (!inode->chunkindexes) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ idx = inode->chunkindexes;
for (pos = 0; pos < inode->i_size; pos += len) {
struct erofs_blobchunk *chunk;
@@ -248,20 +252,26 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd)
#endif
len = min_t(u64, inode->i_size - pos, chunksize);
- chunk = erofs_blob_getchunk(sbi, fd, len);
+ ret = read(fd, chunkdata, len);
+ if (ret < len) {
+ ret = -EIO;
+ goto err;
+ }
+
+ chunk = erofs_blob_getchunk(sbi, chunkdata, len);
if (IS_ERR(chunk)) {
ret = PTR_ERR(chunk);
goto err;
}
- if (multidev)
- chunk->device_id = 1;
*(void **)idx++ = chunk;
}
inode->datalayout = EROFS_INODE_CHUNK_BASED;
+ free(chunkdata);
return 0;
err:
free(inode->chunkindexes);
inode->chunkindexes = NULL;
+ free(chunkdata);
return ret;
}
--
2.24.4
More information about the Linux-erofs
mailing list