erofs-utils: lib: tidy up erofs_blob_getchunk()
authorGao Xiang <hsiangkao@linux.alibaba.com>
Mon, 24 Jul 2023 17:06:45 +0000 (01:06 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Thu, 27 Jul 2023 07:32:01 +0000 (15:32 +0800)
Mainly get rid of memory allocation on each chunk.

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20230724170646.22281-2-hsiangkao@linux.alibaba.com
lib/blobchunk.c

index c0df2f74837de64390e1345d7e5d6d59026c9dba..4619057e4b49f7906268504f995533b3def5f49b 100644 (file)
@@ -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;
 }