[PATCH 1/2] erofs-utils: refine blobchunk implementation

Gao Xiang hsiangkao at linux.alibaba.com
Fri Apr 21 17:39:25 AEST 2023


 - 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 <hsiangkao at 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;
-- 
2.24.4



More information about the Linux-erofs mailing list