From 689372cd7f8ea88e38f64716d215cff512ba42a5 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Fri, 21 Apr 2023 15:39:25 +0800 Subject: erofs-utils: refine blobchunk implementation - record device_id in erofs_blobchunk for later tarerofs; - fix up endianness conversion; - blob (hash) entries should be released in the blobchunk submodule. Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20230421073926.85369-1-hsiangkao@linux.alibaba.com --- include/erofs/hashmap.h | 5 ++--- lib/blobchunk.c | 44 ++++++++++++++++++++++++++++---------------- lib/hashmap.c | 32 ++++++++++++++------------------ 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/include/erofs/hashmap.h b/include/erofs/hashmap.h index 3d38578..d25092d 100644 --- a/include/erofs/hashmap.h +++ b/include/erofs/hashmap.h @@ -61,7 +61,7 @@ struct hashmap_iter { /* hashmap functions */ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function, size_t initial_size); -void hashmap_free(struct hashmap *map, int free_entries); +int hashmap_free(struct hashmap *map); /* hashmap_entry functions */ static inline void hashmap_entry_init(void *entry, unsigned int hash) @@ -75,8 +75,7 @@ static inline void hashmap_entry_init(void *entry, unsigned int hash) void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata); void *hashmap_get_next(const struct hashmap *map, const void *entry); void hashmap_add(struct hashmap *map, void *entry); -void *hashmap_put(struct hashmap *map, void *entry); -void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata); +void *hashmap_remove(struct hashmap *map, const void *key); static inline void *hashmap_get_from_hash(const struct hashmap *map, unsigned int hash, diff --git a/lib/blobchunk.c b/lib/blobchunk.c index 8142cc3..6fbc15b 100644 --- a/lib/blobchunk.c +++ b/lib/blobchunk.c @@ -16,6 +16,7 @@ struct erofs_blobchunk { struct hashmap_entry ent; char sha256[32]; + unsigned int device_id; erofs_off_t chunksize; erofs_blk_t blkaddr; }; @@ -64,6 +65,7 @@ static struct erofs_blobchunk *erofs_blob_getchunk(int fd, chunk->chunksize = chunksize; blkpos = ftell(blobfile); DBG_BUGON(erofs_blkoff(blkpos)); + chunk->device_id = 0; chunk->blkaddr = erofs_blknr(blkpos); memcpy(chunk->sha256, sha256, sizeof(sha256)); hashmap_entry_init(&chunk->ent, hash); @@ -75,10 +77,7 @@ static struct erofs_blobchunk *erofs_blob_getchunk(int fd, ret = fwrite(zeroed, erofs_blksiz() - erofs_blkoff(chunksize), 1, blobfile); if (ret < 1) { - struct hashmap_entry key; - - hashmap_entry_init(&key, hash); - hashmap_remove(&blob_hashmap, &key, sha256); + hashmap_remove(&blob_hashmap, &chunk->ent); free(chunk); chunk = ERR_PTR(-ENOSPC); goto out; @@ -110,14 +109,6 @@ int erofs_blob_write_chunk_indexes(struct erofs_inode *inode, erofs_blk_t extent_end, extents_blks; unsigned int dst, src, unit; bool first_extent = true; - erofs_blk_t base_blkaddr = 0; - - if (multidev) { - idx.device_id = 1; - DBG_BUGON(!(inode->u.chunkformat & EROFS_CHUNK_FORMAT_INDEXES)); - } else { - base_blkaddr = remapped_base; - } if (inode->u.chunkformat & EROFS_CHUNK_FORMAT_INDEXES) unit = sizeof(struct erofs_inode_chunk_index); @@ -130,10 +121,15 @@ int erofs_blob_write_chunk_indexes(struct erofs_inode *inode, chunk = *(void **)(inode->chunkindexes + src); - if (chunk->blkaddr != EROFS_NULL_ADDR) - idx.blkaddr = base_blkaddr + chunk->blkaddr; - else + if (chunk->blkaddr == EROFS_NULL_ADDR) { idx.blkaddr = EROFS_NULL_ADDR; + } else if (chunk->device_id) { + DBG_BUGON(!(inode->u.chunkformat & EROFS_CHUNK_FORMAT_INDEXES)); + idx.blkaddr = chunk->blkaddr; + extent_start = EROFS_NULL_ADDR; + } else { + idx.blkaddr = remapped_base + chunk->blkaddr; + } if (extent_start != EROFS_NULL_ADDR && idx.blkaddr == extent_end + 1) { @@ -149,6 +145,9 @@ int erofs_blob_write_chunk_indexes(struct erofs_inode *inode, extent_start = idx.blkaddr; extent_end = idx.blkaddr; } + idx.device_id = cpu_to_le16(chunk->device_id); + idx.blkaddr = cpu_to_le32(idx.blkaddr); + if (unit == EROFS_BLOCK_MAP_ENTRY_SIZE) memcpy(inode->chunkindexes + dst, &idx.blkaddr, unit); else @@ -237,6 +236,8 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode) ret = PTR_ERR(chunk); goto err; } + if (multidev) + chunk->device_id = 1; *(void **)idx++ = chunk; } inode->datalayout = EROFS_INODE_CHUNK_BASED; @@ -293,10 +294,21 @@ int erofs_blob_remap(void) void erofs_blob_exit(void) { + struct hashmap_iter iter; + struct hashmap_entry *e; + if (blobfile) fclose(blobfile); - hashmap_free(&blob_hashmap, 1); + while ((e = hashmap_iter_first(&blob_hashmap, &iter))) { + struct erofs_blobchunk *bc = + container_of((struct hashmap_entry *)e, + struct erofs_blobchunk, ent); + + DBG_BUGON(hashmap_remove(&blob_hashmap, e) != e); + free(bc); + } + DBG_BUGON(hashmap_free(&blob_hashmap)); } int erofs_blob_init(const char *blobfile_path) diff --git a/lib/hashmap.c b/lib/hashmap.c index e11bd8d..45916ae 100644 --- a/lib/hashmap.c +++ b/lib/hashmap.c @@ -149,20 +149,21 @@ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function, alloc_table(map, size); } -void hashmap_free(struct hashmap *map, int free_entries) +int hashmap_free(struct hashmap *map) { - if (!map || !map->table) - return; - if (free_entries) { + if (map && map->table) { struct hashmap_iter iter; struct hashmap_entry *e; hashmap_iter_init(map, &iter); - while ((e = hashmap_iter_next(&iter))) - free(e); + e = hashmap_iter_next(&iter); + if (e) + return -EBUSY; + + free(map->table); + memset(map, 0, sizeof(*map)); } - free(map->table); - memset(map, 0, sizeof(*map)); + return 0; } void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata) @@ -194,10 +195,13 @@ void hashmap_add(struct hashmap *map, void *entry) rehash(map, map->tablesize << HASHMAP_RESIZE_BITS); } -void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata) +void *hashmap_remove(struct hashmap *map, const void *entry) { struct hashmap_entry *old; - struct hashmap_entry **e = find_entry_ptr(map, key, keydata); + struct hashmap_entry **e = &map->table[bucket(map, entry)]; + + while (*e && *e != entry) + e = &(*e)->next; if (!*e) return NULL; @@ -214,14 +218,6 @@ void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata) return old; } -void *hashmap_put(struct hashmap *map, void *entry) -{ - struct hashmap_entry *old = hashmap_remove(map, entry, NULL); - - hashmap_add(map, entry); - return old; -} - void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter) { iter->map = map; -- cgit v1.2.3