Skip to content

Commit 4d3ad56

Browse files
committed
lib: chunkio: upgrade to v1.5.4
Signed-off-by: Eduardo Silva <[email protected]>
1 parent 8b7cfba commit 4d3ad56

File tree

10 files changed

+1026
-27
lines changed

10 files changed

+1026
-27
lines changed

lib/chunkio/.github/workflows/ci.yaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@ jobs:
1515
max-parallel: 48
1616
fail-fast: false
1717
matrix:
18-
os: [windows-latest, windows-2019]
18+
os: [windows-2025, windows-2022]
1919
steps:
2020
- uses: actions/checkout@v2
21-
- name: Build on ${{ matrix.os }} with vs-2019
21+
- name: Set up with Developer Command Prompt for Microsoft Visual C++
22+
uses: ilammy/msvc-dev-cmd@v1
23+
with:
24+
arch: amd64
25+
- name: Build on ${{ matrix.os }} with MSVC
2226
run: |
23-
.\scripts\win_build.bat
27+
cmake -G "NMake Makefiles" -DCIO_TESTS=On .
28+
cmake --build .
2429
- name: Run unit tests.
2530
run: |
26-
ctest --rerun-failed --output-on-failure -C Debug --test-dir .
31+
ctest . --rerun-failed --output-on-failure --test-dir .
2732
build-unix:
2833
name: Build sources on amd64 for ${{ matrix.os }} - ${{ matrix.compiler }}
2934
runs-on: ${{ matrix.os }}

lib/chunkio/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ project(chunk-io C)
33

44
set(CIO_VERSION_MAJOR 1)
55
set(CIO_VERSION_MINOR 5)
6-
set(CIO_VERSION_PATCH 3)
6+
set(CIO_VERSION_PATCH 4)
77
set(CIO_VERSION_STR "${CIO_VERSION_MAJOR}.${CIO_VERSION_MINOR}.${CIO_VERSION_PATCH}")
88

99
# CFLAGS

lib/chunkio/include/chunkio/cio_file.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct cio_file {
4040
size_t realloc_size; /* chunk size to increase alloc */
4141
char *path; /* root path + stream */
4242
char *map; /* map of data */
43+
struct cio_ctx *ctx; /* owning context */
4344
#ifdef _WIN32
4445
HANDLE backing_file;
4546
HANDLE backing_mapping;
@@ -49,6 +50,8 @@ struct cio_file {
4950
char *st_content;
5051
crc_t crc_cur; /* crc: current value calculated */
5152
int crc_reset; /* crc: must recalculate from the beginning ? */
53+
int auto_remap_warned; /* has sync auto-remap warning been emitted? */
54+
int map_truncated_warned; /* has RO truncation warning been emitted? */
5255
};
5356

5457
size_t cio_file_real_size(struct cio_file *cf);

lib/chunkio/src/cio_file.c

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,10 @@ static int munmap_file(struct cio_ctx *ctx, struct cio_chunk *ch)
324324
}
325325

326326
/* Unmap file */
327-
cio_file_native_unmap(cf);
327+
ret = cio_file_native_unmap(cf);
328+
if (ret != CIO_OK) {
329+
return -1;
330+
}
328331

329332
cf->data_size = 0;
330333
cf->alloc_size = 0;
@@ -343,6 +346,7 @@ static int mmap_file(struct cio_ctx *ctx, struct cio_chunk *ch, size_t size)
343346
{
344347
ssize_t content_size;
345348
size_t fs_size;
349+
size_t requested_map_size;
346350
int ret;
347351
struct cio_file *cf;
348352

@@ -413,6 +417,7 @@ static int mmap_file(struct cio_ctx *ctx, struct cio_chunk *ch, size_t size)
413417
cf->alloc_size = size;
414418

415419
/* Map the file */
420+
requested_map_size = cf->alloc_size;
416421
ret = cio_file_native_map(cf, cf->alloc_size);
417422

418423
if (ret != CIO_OK) {
@@ -421,6 +426,21 @@ static int mmap_file(struct cio_ctx *ctx, struct cio_chunk *ch, size_t size)
421426
return CIO_ERROR;
422427
}
423428

429+
if ((cf->flags & CIO_OPEN_RD) && requested_map_size != cf->alloc_size) {
430+
if (cf->map_truncated_warned == CIO_FALSE) {
431+
cio_log_warn(ctx,
432+
"[cio file] truncated read-only map from %zu to %zu bytes: %s/%s",
433+
requested_map_size,
434+
cf->alloc_size,
435+
ch->st->name,
436+
ch->name);
437+
cf->map_truncated_warned = CIO_TRUE;
438+
}
439+
}
440+
else {
441+
cf->map_truncated_warned = CIO_FALSE;
442+
}
443+
424444
/* check content data size */
425445
if (fs_size > 0) {
426446
content_size = cio_file_st_get_content_len(cf->map,
@@ -664,6 +684,9 @@ struct cio_file *cio_file_open(struct cio_ctx *ctx,
664684
cf->crc_cur = cio_crc32_init();
665685
cf->path = path;
666686
cf->map = NULL;
687+
cf->ctx = ctx;
688+
cf->auto_remap_warned = CIO_FALSE;
689+
cf->map_truncated_warned = CIO_FALSE;
667690
ch->backend = cf;
668691

669692
#ifdef _WIN32
@@ -801,9 +824,9 @@ static int _cio_file_up(struct cio_chunk *ch, int enforced)
801824
return CIO_ERROR;
802825
}
803826

804-
if (cf->fd > 0) {
827+
if (cio_file_native_is_open(cf)) {
805828
cio_log_error(ch->ctx, "[cio file] file descriptor already exists: "
806-
"[fd=%i] %s:%s", cf->fd, ch->st->name, ch->name);
829+
"%s:%s", ch->st->name, ch->name);
807830
return CIO_ERROR;
808831
}
809832

@@ -908,7 +931,11 @@ int cio_file_down(struct cio_chunk *ch)
908931
}
909932

910933
/* unmap memory */
911-
munmap_file(ch->ctx, ch);
934+
ret = munmap_file(ch->ctx, ch);
935+
936+
if (ret != 0) {
937+
return -1;
938+
}
912939

913940
/* Allocated map size is zero */
914941
cf->alloc_size = 0;
@@ -921,7 +948,12 @@ int cio_file_down(struct cio_chunk *ch)
921948
}
922949

923950
/* Close file descriptor */
924-
cio_file_native_close(cf);
951+
ret = cio_file_native_close(cf);
952+
953+
if (ret != CIO_OK) {
954+
cio_errno();
955+
return -1;
956+
}
925957

926958
return 0;
927959
}
@@ -1047,7 +1079,6 @@ int cio_file_write_metadata(struct cio_chunk *ch, char *buf, size_t size)
10471079
char *cur_content_data;
10481080
char *new_content_data;
10491081
size_t new_size;
1050-
size_t content_av;
10511082
size_t meta_av;
10521083
struct cio_file *cf;
10531084

@@ -1082,13 +1113,11 @@ int cio_file_write_metadata(struct cio_chunk *ch, char *buf, size_t size)
10821113
* where we need to increase the memory map size, move the content area
10831114
* bytes to a different position and write the metadata.
10841115
*
1085-
* Calculate the available space in the content area.
1116+
* Check if resize is needed before calculating content_av to avoid
1117+
* unsigned underflow. We need: header + new_metadata + content_data <= alloc_size
10861118
*/
1087-
content_av = cf->alloc_size - cf->data_size;
1088-
1089-
/* If there is no enough space, increase the file size and it memory map */
1090-
if (content_av < size) {
1091-
new_size = (size - meta_av) + cf->data_size + CIO_FILE_HEADER_MIN;
1119+
if (cf->alloc_size < CIO_FILE_HEADER_MIN + size + cf->data_size) {
1120+
new_size = CIO_FILE_HEADER_MIN + size + cf->data_size;
10921121

10931122
ret = cio_file_resize(cf, new_size);
10941123

@@ -1106,7 +1135,7 @@ int cio_file_write_metadata(struct cio_chunk *ch, char *buf, size_t size)
11061135
/* set new position for the content data */
11071136
cur_content_data = cio_file_st_get_content(cf->map);
11081137
new_content_data = meta + size;
1109-
memmove(new_content_data, cur_content_data, size);
1138+
memmove(new_content_data, cur_content_data, cf->data_size);
11101139

11111140
/* copy new metadata */
11121141
memcpy(meta, buf, size);
@@ -1138,6 +1167,12 @@ int cio_file_sync(struct cio_chunk *ch)
11381167
return 0;
11391168
}
11401169

1170+
/* If chunk is down (unmapped), there's nothing to sync */
1171+
/* You can only write to a chunk when it's up, so if it's down, no pending changes exist */
1172+
if (!cio_file_native_is_mapped(cf)) {
1173+
return 0;
1174+
}
1175+
11411176
if (cf->synced == CIO_TRUE) {
11421177
return 0;
11431178
}

lib/chunkio/src/cio_file_unix.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ int cio_file_native_unmap(struct cio_file *cf)
6666

6767
cf->alloc_size = 0;
6868
cf->map = NULL;
69+
cf->map_truncated_warned = CIO_FALSE;
6970

7071
return CIO_OK;
7172
}

lib/chunkio/src/cio_file_win32.c

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ int cio_file_native_unmap(struct cio_file *cf)
3838
return CIO_ERROR;
3939
}
4040

41-
if (!cio_file_native_is_open(cf)) {
42-
return CIO_OK;
43-
}
44-
41+
/* Check if already unmapped first */
4542
if (!cio_file_native_is_mapped(cf)) {
4643
return CIO_OK;
4744
}
4845

46+
/* On Windows, we can unmap even if file handle is closed */
47+
/* The mapping handle maintains the reference */
48+
4949
result = UnmapViewOfFile(cf->map);
5050

5151
if (result == 0) {
@@ -54,11 +54,18 @@ int cio_file_native_unmap(struct cio_file *cf)
5454
return CIO_ERROR;
5555
}
5656

57-
CloseHandle(cf->backing_mapping);
57+
result = CloseHandle(cf->backing_mapping);
58+
59+
if (result == 0) {
60+
cio_file_native_report_os_error();
61+
62+
return CIO_ERROR;
63+
}
5864

5965
cf->backing_mapping = INVALID_HANDLE_VALUE;
6066
cf->alloc_size = 0;
6167
cf->map = NULL;
68+
cf->map_truncated_warned = CIO_FALSE;
6269

6370
return CIO_OK;
6471
}
@@ -67,6 +74,9 @@ int cio_file_native_map(struct cio_file *cf, size_t map_size)
6774
{
6875
DWORD desired_protection;
6976
DWORD desired_access;
77+
size_t file_size;
78+
size_t actual_map_size;
79+
int ret;
7080

7181
if (cf == NULL) {
7282
return CIO_ERROR;
@@ -92,17 +102,48 @@ int cio_file_native_map(struct cio_file *cf, size_t map_size)
92102
return CIO_ERROR;
93103
}
94104

105+
/* Get current file size to ensure we don't map beyond it for read-only files */
106+
ret = cio_file_native_get_size(cf, &file_size);
107+
if (ret != CIO_OK) {
108+
return CIO_ERROR;
109+
}
110+
111+
/* For read-only files, we cannot map beyond the file size */
112+
/* For read-write files, if map_size > file_size, we should resize first */
113+
if (cf->flags & CIO_OPEN_RD) {
114+
if (map_size > file_size) {
115+
actual_map_size = file_size;
116+
}
117+
else {
118+
actual_map_size = map_size;
119+
}
120+
}
121+
else {
122+
/* For RW files, if map_size > file_size, resize the file first */
123+
if (map_size > file_size) {
124+
ret = cio_file_native_resize(cf, map_size);
125+
if (ret != CIO_OK) {
126+
return CIO_ERROR;
127+
}
128+
}
129+
actual_map_size = map_size;
130+
}
131+
132+
/* CreateFileMappingA requires size as two DWORDs (high and low) */
133+
/* Use actual_map_size to ensure consistency */
95134
cf->backing_mapping = CreateFileMappingA(cf->backing_file, NULL,
96135
desired_protection,
97-
0, 0, NULL);
136+
(DWORD)(actual_map_size >> 32),
137+
(DWORD)(actual_map_size & 0xFFFFFFFFUL),
138+
NULL);
98139

99140
if (cf->backing_mapping == NULL) {
100141
cio_file_native_report_os_error();
101142

102143
return CIO_ERROR;
103144
}
104145

105-
cf->map = MapViewOfFile(cf->backing_mapping, desired_access, 0, 0, map_size);
146+
cf->map = MapViewOfFile(cf->backing_mapping, desired_access, 0, 0, actual_map_size);
106147

107148
if (cf->map == NULL) {
108149
cio_file_native_report_os_error();
@@ -114,7 +155,7 @@ int cio_file_native_map(struct cio_file *cf, size_t map_size)
114155
return CIO_ERROR;
115156
}
116157

117-
cf->alloc_size = map_size;
158+
cf->alloc_size = actual_map_size;
118159

119160
return CIO_OK;
120161
}
@@ -474,6 +515,38 @@ int cio_file_native_delete(struct cio_file *cf)
474515
{
475516
int result;
476517

518+
if (cf == NULL) {
519+
return CIO_ERROR;
520+
}
521+
522+
if (cio_file_native_is_mapped(cf)) {
523+
if (cf->ctx != NULL) {
524+
cio_log_warn(cf->ctx,
525+
"[cio file] auto-unmapping chunk prior to delete: %s",
526+
cf->path);
527+
}
528+
529+
result = cio_file_native_unmap(cf);
530+
531+
if (result != CIO_OK) {
532+
return result;
533+
}
534+
}
535+
536+
if (cio_file_native_is_open(cf)) {
537+
if (cf->ctx != NULL) {
538+
cio_log_warn(cf->ctx,
539+
"[cio file] closing handle prior to delete: %s",
540+
cf->path);
541+
}
542+
543+
result = cio_file_native_close(cf);
544+
545+
if (result != CIO_OK) {
546+
return result;
547+
}
548+
}
549+
477550
result = DeleteFileA(cf->path);
478551

479552
if (result == 0) {
@@ -489,6 +562,10 @@ int cio_file_native_sync(struct cio_file *cf, int sync_mode)
489562
{
490563
int result;
491564

565+
if (!cio_file_native_is_mapped(cf)) {
566+
return CIO_ERROR;
567+
}
568+
492569
result = FlushViewOfFile(cf->map, cf->alloc_size);
493570

494571
if (result == 0) {

lib/chunkio/tests/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ if(CIO_BACKEND_FILESYSTEM)
99
set(UNIT_TESTS_FILES
1010
${UNIT_TESTS_FILES}
1111
fs.c
12+
metadata_update.c
13+
)
14+
endif()
15+
16+
# Windows-specific inconsistency tests
17+
if(WIN32 AND CIO_BACKEND_FILESYSTEM)
18+
set(UNIT_TESTS_FILES
19+
${UNIT_TESTS_FILES}
20+
fs_windows.c
1221
)
1322
endif()
1423

@@ -35,7 +44,7 @@ foreach(source_file ${UNIT_TESTS_FILES})
3544
add_test(${source_file_we} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_file_we})
3645
endforeach()
3746

38-
# Perf tests for dev purposes: note these tests are not registered, they need to
47+
# Perf tests for dev purposes: note these tests are not registered, they need to
3948
# be executed manually
4049
set(UNIT_PERF_TESTS
4150
fs_perf.c

0 commit comments

Comments
 (0)