}
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;
}
unsigned int count, unit;
struct erofs_inode_chunk_index *idx;
erofs_off_t pos, len, chunksize;
+ u8 *chunkdata;
int ret;
#ifdef SEEK_DATA
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;
#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;
}