Fix datafile creation race condition (#20662)
Fix datafile creation lock
Stelios Fragkakis committed
Jul 13, 2025 at 17:25 UTC
20bd48e4878832f35cb7b1a105af539d398adf8d
3 files changed
+11
-16
src/database/engine/datafile.c
+8
-13
@@ -1,20 +1,15 @@
1
// SPDX-License-Identifier: GPL-3.0-or-later
2
#include "rrdengine.h"
3
4
-void datafile_list_insert(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile, bool having_lock)
4
+void datafile_list_insert(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile)
5
{
6
- if(!having_lock)
7
- uv_rwlock_wrlock(&ctx->datafiles.rwlock);
8
-
6
+ uv_rwlock_wrlock(&ctx->datafiles.rwlock);
7
Pvoid_t *Pvalue = JudyLIns(&ctx->datafiles.JudyL, (Word_t ) datafile->fileno, PJE0);
8
if(!Pvalue || Pvalue == PJERR)
9
fatal("DBENGINE: cannot insert datafile %u of tier %d into the datafiles list",
10
datafile->fileno, ctx->config.tier);
13
-
11
*Pvalue = datafile;
15
-
16
- if(!having_lock)
17
- uv_rwlock_wrunlock(&ctx->datafiles.rwlock);
12
+ uv_rwlock_wrunlock(&ctx->datafiles.rwlock);
13
}
14
15
void datafile_list_delete_unsafe(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile)
@@ -515,7 +510,7 @@ static int scan_data_files(struct rrdengine_instance *ctx)
510
}
511
512
ctx_current_disk_space_increase(ctx, datafile->pos + journalfile->unsafe.pos);
518
- datafile_list_insert(ctx, datafile, false);
513
+ datafile_list_insert(ctx, datafile);
514
}
515
516
matched_files -= failed_to_load;
@@ -525,7 +520,7 @@ static int scan_data_files(struct rrdengine_instance *ctx)
520
}
521
522
/* Creates a datafile and a journalfile pair */
528
-int create_new_datafile_pair(struct rrdengine_instance *ctx, bool having_lock)
523
+int create_new_datafile_pair(struct rrdengine_instance *ctx)
524
{
525
__atomic_add_fetch(&rrdeng_cache_efficiency_stats.datafile_creation_started, 1, __ATOMIC_RELAXED);
526
@@ -556,7 +551,7 @@ int create_new_datafile_pair(struct rrdengine_instance *ctx, bool having_lock)
551
nd_log(NDLS_DAEMON, NDLP_INFO, "DBENGINE: created journal file \"%s\".", path);
552
553
ctx_current_disk_space_increase(ctx, datafile->pos + journalfile->unsafe.pos);
559
- datafile_list_insert(ctx, datafile, having_lock);
554
+ datafile_list_insert(ctx, datafile);
555
ctx_last_fileno_increment(ctx);
556
557
return 0;
@@ -584,7 +579,7 @@ int init_data_files(struct rrdengine_instance *ctx)
579
} else if (0 == ret) {
580
netdata_log_info("DBENGINE: data files not found, creating in path \"%s\".", ctx->config.dbfiles_path);
581
ctx->atomic.last_fileno = 0;
587
- ret = create_new_datafile_pair(ctx, false);
582
+ ret = create_new_datafile_pair(ctx);
583
if (ret) {
584
netdata_log_error("DBENGINE: failed to create data and journal files in path \"%s\".", ctx->config.dbfiles_path);
585
return ret;
@@ -592,7 +587,7 @@ int init_data_files(struct rrdengine_instance *ctx)
587
}
588
else {
589
if (ctx->loading.create_new_datafile_pair)
595
- create_new_datafile_pair(ctx, false);
590
+ create_new_datafile_pair(ctx);
591
592
while(rrdeng_ctx_tier_cap_exceeded(ctx)) {
593
Word_t Index = 0;
src/database/engine/datafile.h
+2
-2
@@ -92,14 +92,14 @@ void datafile_release_with_trace(struct rrdengine_datafile *df, DATAFILE_ACQUIRE
92
#define datafile_release(df, reason) datafile_release_with_trace(df, reason, __FUNCTION__)
93
bool datafile_acquire_for_deletion(struct rrdengine_datafile *df, bool is_shutdown);
94
95
-void datafile_list_insert(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile, bool having_lock);
95
+void datafile_list_insert(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile);
96
void datafile_list_delete_unsafe(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile);
97
void generate_datafilepath(struct rrdengine_datafile *datafile, char *str, size_t maxlen);
98
int close_data_file(struct rrdengine_datafile *datafile);
99
int unlink_data_file(struct rrdengine_datafile *datafile);
100
int destroy_data_file_unsafe(struct rrdengine_datafile *datafile);
101
int create_data_file(struct rrdengine_datafile *datafile);
102
-int create_new_datafile_pair(struct rrdengine_instance *ctx, bool having_lock);
102
+int create_new_datafile_pair(struct rrdengine_instance *ctx);
103
int init_data_files(struct rrdengine_instance *ctx);
104
void finalize_data_files(struct rrdengine_instance *ctx);
105
void cleanup_datafile_epdl_structures(struct rrdengine_datafile *datafile);
src/database/engine/rrdengine.c
+1
-1
@@ -798,7 +798,7 @@ static struct rrdengine_datafile *get_datafile_to_write_extent(struct rrdengine_
798
// take the latest datafile again - without this, multiple threads may create multiple files
799
datafile = get_last_ctx_datafile(ctx, false);
800
801
- if(datafile_is_full(ctx, datafile) && create_new_datafile_pair(ctx, true) == 0)
801
+ if(datafile_is_full(ctx, datafile) && create_new_datafile_pair(ctx) == 0)
802
__atomic_store_n(&ctx->atomic.needs_indexing, true, __ATOMIC_RELAXED);
803
804
netdata_mutex_unlock(&mutex);