aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSandeep Dhavale <dhavale@google.com>2024-06-06 15:51:07 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2024-06-06 15:51:07 +0000
commit1db54f71926264db03369e9b54b5d774cefcd1fd (patch)
treed310aeb92dccbad056ea5c7748ff95d41f427513
parent41dee1871a6a3ecc1cd235b00acab2ea8ab74d26 (diff)
parent90c7f666d92ea1b8032a14de89decc661e4059f7 (diff)
downloaderofs-utils-master.tar.gz
UPSTREAM: erofs-utils: lib: treat data blocks filled with 0s as a hole am: 90c7f666d9HEADmastermain
Original change: https://android-review.googlesource.com/c/platform/external/erofs-utils/+/3117095 Change-Id: I8b947d4afa98ddf97d88334ea2917d45f0faa763 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--include/erofs/blobchunk.h2
-rw-r--r--lib/blobchunk.c75
-rw-r--r--mkfs/main.c2
3 files changed, 65 insertions, 14 deletions
diff --git a/include/erofs/blobchunk.h b/include/erofs/blobchunk.h
index 89c8048..a426111 100644
--- a/include/erofs/blobchunk.h
+++ b/include/erofs/blobchunk.h
@@ -22,7 +22,7 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd,
int tarerofs_write_chunkes(struct erofs_inode *inode, erofs_off_t data_offset);
int erofs_mkfs_dump_blobs(struct erofs_sb_info *sbi);
void erofs_blob_exit(void);
-int erofs_blob_init(const char *blobfile_path);
+int erofs_blob_init(const char *blobfile_path, erofs_off_t chunksize);
int erofs_mkfs_init_devices(struct erofs_sb_info *sbi, unsigned int devices);
#ifdef __cplusplus
diff --git a/lib/blobchunk.c b/lib/blobchunk.c
index 9ac9e5b..b74bb36 100644
--- a/lib/blobchunk.c
+++ b/lib/blobchunk.c
@@ -69,8 +69,15 @@ static struct erofs_blobchunk *erofs_blob_getchunk(struct erofs_sb_info *sbi,
chunk = hashmap_get_from_hash(&blob_hashmap, hash, sha256);
if (chunk) {
DBG_BUGON(chunksize != chunk->chunksize);
+
sbi->saved_by_deduplication += chunksize;
- erofs_dbg("Found duplicated chunk at %u", chunk->blkaddr);
+ if (chunk->blkaddr == erofs_holechunk.blkaddr) {
+ chunk = &erofs_holechunk;
+ erofs_dbg("Found duplicated hole chunk");
+ } else {
+ erofs_dbg("Found duplicated chunk at %u",
+ chunk->blkaddr);
+ }
return chunk;
}
@@ -231,7 +238,21 @@ static void erofs_update_minextblks(struct erofs_sb_info *sbi,
if (lb && lb < *minextblks)
*minextblks = lb;
}
-
+static bool erofs_blob_can_merge(struct erofs_sb_info *sbi,
+ struct erofs_blobchunk *lastch,
+ struct erofs_blobchunk *chunk)
+{
+ if (!lastch)
+ return true;
+ if (lastch == &erofs_holechunk && chunk == &erofs_holechunk)
+ return true;
+ if (lastch->device_id == chunk->device_id &&
+ erofs_pos(sbi, lastch->blkaddr) + lastch->chunksize ==
+ erofs_pos(sbi, chunk->blkaddr))
+ return true;
+
+ return false;
+}
int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd,
erofs_off_t startoff)
{
@@ -303,16 +324,19 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd,
}
if (offset > pos) {
- len = 0;
- erofs_update_minextblks(sbi, interval_start, pos,
- &minextblks);
+ if (!erofs_blob_can_merge(sbi, lastch,
+ &erofs_holechunk)) {
+ erofs_update_minextblks(sbi, interval_start,
+ pos, &minextblks);
+ interval_start = pos;
+ }
do {
*(void **)idx++ = &erofs_holechunk;
pos += chunksize;
} while (pos < offset);
DBG_BUGON(pos != offset);
- lastch = NULL;
- interval_start = pos;
+ lastch = &erofs_holechunk;
+ len = 0;
continue;
}
#endif
@@ -330,9 +354,7 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd,
goto err;
}
- if (lastch && (lastch->device_id != chunk->device_id ||
- erofs_pos(sbi, lastch->blkaddr) + lastch->chunksize !=
- erofs_pos(sbi, chunk->blkaddr))) {
+ if (!erofs_blob_can_merge(sbi, lastch, chunk)) {
erofs_update_minextblks(sbi, interval_start, pos,
&minextblks);
interval_start = pos;
@@ -498,7 +520,36 @@ void erofs_blob_exit(void)
}
}
-int erofs_blob_init(const char *blobfile_path)
+static int erofs_insert_zerochunk(erofs_off_t chunksize)
+{
+ u8 *zeros;
+ struct erofs_blobchunk *chunk;
+ u8 sha256[32];
+ unsigned int hash;
+ int ret = 0;
+
+ zeros = calloc(1, chunksize);
+ if (!zeros)
+ return -ENOMEM;
+
+ erofs_sha256(zeros, chunksize, sha256);
+ free(zeros);
+ hash = memhash(sha256, sizeof(sha256));
+ chunk = malloc(sizeof(struct erofs_blobchunk));
+ if (!chunk)
+ return -ENOMEM;
+
+ chunk->chunksize = chunksize;
+ /* treat chunk filled with zeros as hole */
+ chunk->blkaddr = erofs_holechunk.blkaddr;
+ memcpy(chunk->sha256, sha256, sizeof(sha256));
+
+ hashmap_entry_init(&chunk->ent, hash);
+ hashmap_add(&blob_hashmap, chunk);
+ return ret;
+}
+
+int erofs_blob_init(const char *blobfile_path, erofs_off_t chunksize)
{
if (!blobfile_path) {
#ifdef HAVE_TMPFILE64
@@ -515,7 +566,7 @@ int erofs_blob_init(const char *blobfile_path)
return -EACCES;
hashmap_init(&blob_hashmap, erofs_blob_hashmap_cmp, 0);
- return 0;
+ return erofs_insert_zerochunk(chunksize);
}
int erofs_mkfs_init_devices(struct erofs_sb_info *sbi, unsigned int devices)
diff --git a/mkfs/main.c b/mkfs/main.c
index 6d2b700..ccb64ae 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1084,7 +1084,7 @@ int main(int argc, char **argv)
}
if (cfg.c_chunkbits) {
- err = erofs_blob_init(cfg.c_blobdev_path);
+ err = erofs_blob_init(cfg.c_blobdev_path, 1 << cfg.c_chunkbits);
if (err)
return 1;
}