Skip to content

Commit

Permalink
Handle non-inline files that need to be EROFS_INODE_CHUNK_BASED
Browse files Browse the repository at this point in the history
Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters committed Sep 10, 2024
1 parent 31c43f9 commit d00c962
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 10 deletions.
41 changes: 31 additions & 10 deletions libcomposefs/lcfs-writer-erofs.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ static uint64_t compute_erofs_inode_padding_for_tail(struct lcfs_node_s *node,
/* Didn't fit, don't inline the tail. */
node->erofs_n_blocks++;
node->erofs_tailsize = 0;
return round_up(pos, EROFS_BLKSIZ) - pos;
}

return 0;
Expand Down Expand Up @@ -817,6 +818,17 @@ static int write_erofs_dentries(struct lcfs_ctx_s *ctx, struct lcfs_node_s *node
return 0;
}

static int write_empty_chunks(struct lcfs_ctx_s *ctx, uint32_t chunk_count)
{
for (size_t i = 0; i < chunk_count; i++) {
uint32_t empty_chunk = 0xFFFFFFFF;
int ret = lcfs_write(ctx, &empty_chunk, sizeof(empty_chunk));
if (ret < 0)
return ret;
}
return 0;
}

static int write_erofs_inode_data(struct lcfs_ctx_s *ctx, struct lcfs_node_s *node)
{
struct lcfs_ctx_erofs_s *ctx_erofs = (struct lcfs_ctx_erofs_s *)ctx;
Expand Down Expand Up @@ -1012,28 +1024,23 @@ static int write_erofs_inode_data(struct lcfs_ctx_s *ctx, struct lcfs_node_s *no
if (ret < 0)
return ret;
}
} else if (type == S_IFREG) {
} else if (type == S_IFREG && node->erofs_tailsize > 0) {
if (node->content != NULL) {
if (node->erofs_tailsize) {
uint64_t file_size = node->inode.st_size;
ret = lcfs_write(ctx,
node->content + file_size -
node->erofs_tailsize,
node->erofs_tailsize);
if (ret < 0)
return ret;
}
} else {
// Currently we assume this fits within a single block
assert(chunk_count <= LCFS_MAX_NONINLINE_CHUNKS);
assert(node->erofs_n_blocks == 0 ||
node->erofs_n_blocks == 1);
for (size_t i = 0; i < chunk_count; i++) {
uint32_t empty_chunk = 0xFFFFFFFF;
ret = lcfs_write(ctx, &empty_chunk,
sizeof(empty_chunk));
if (ret < 0)
return ret;
ret = write_empty_chunks(ctx, chunk_count);
if (ret < 0) {
return ret;
}
}
}
Expand Down Expand Up @@ -1071,7 +1078,21 @@ static int write_erofs_file_content(struct lcfs_ctx_s *ctx, struct lcfs_node_s *
uint8_t *target;
bool has_blocks = node->erofs_n_blocks > 0;
if (type == S_IFREG && has_blocks) {
assert(node->content != NULL);
// If this is a non-inline file, then we need to write at most
// a single block-sized chunk.
if (node->content == NULL) {
assert(node->erofs_tailsize == 0);
uint32_t chunkbits;
uint32_t chunk_count;
erofs_compute_chunking(node->inode.st_size, &chunkbits,
&chunk_count);
// Currently we assume this fits within a single block
assert(chunk_count <= LCFS_MAX_NONINLINE_CHUNKS);
assert(node->erofs_n_blocks == 1);
// Note early return here
return write_empty_chunks(ctx, chunk_count);
}
// If it's an inline file, provide the content to write
target = node->content;
} else if (type == S_IFLNK && has_blocks) {
assert(node->payload != NULL);
Expand Down
2 changes: 2 additions & 0 deletions tests/assets/bigfile-xattr.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/ 4096 40755 2 0 0 0 0.0 - - -
/bigfile 9001899274941000 100777 1 0 0 0 0.0 - - - user.foo=
1 change: 1 addition & 0 deletions tests/assets/bigfile-xattr.dump.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
5bdb37d78dcf03b4ab1adc9a2d5212d3d95213b41628939f5fe3769f93d927cc
1 change: 1 addition & 0 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ test_assets_small = [
'special.dump',
'longlink.dump',
'bigfile.dump',
'bigfile-xattr.dump',
'special_v1.dump',
'honggfuzz-long-symlink.dump',
'no-newline.dump',
Expand Down

0 comments on commit d00c962

Please sign in to comment.