@cryptotaxi247 / netdata-1 / commits / 91f2ef1bd

Use one spinlock to access v2 and mmap related data (#20202)

Stelios Fragkakis committed Apr 29, 2025 at 23:45 UTC 91f2ef1bdb8bceec06565f5501719278cb48bdc0
2 files changed +21 -42
src/database/engine/journalfile.c
+20 -39
@@ -198,7 +198,7 @@ static void njfv2idx_remove(struct rrdengine_datafile *datafile) {
198 static struct journal_v2_header *journalfile_v2_mounted_data_get(struct rrdengine_journalfile *journalfile, size_t *data_size) {
199 struct journal_v2_header *j2_header = NULL;
200
201 - spinlock_lock(&journalfile->mmap.spinlock);
201 + spinlock_lock(&journalfile->data_spinlock);
202
203 if(!journalfile->mmap.data) {
204 journalfile->mmap.data = nd_mmap(NULL, journalfile->mmap.size, PROT_READ, MAP_SHARED, journalfile->mmap.fd, 0);
@@ -209,9 +209,7 @@ static struct journal_v2_header *journalfile_v2_mounted_data_get(struct rrdengin
209 journalfile->mmap.data = NULL;
210 journalfile->mmap.size = 0;
211
212 - spinlock_lock(&journalfile->v2.spinlock);
212 journalfile->v2.flags &= ~(JOURNALFILE_FLAG_IS_AVAILABLE | JOURNALFILE_FLAG_IS_MOUNTED);
214 - spinlock_unlock(&journalfile->v2.spinlock);
213
214 ctx_fs_error(datafile_ctx(journalfile->datafile));
215 }
@@ -223,10 +221,8 @@ static struct journal_v2_header *journalfile_v2_mounted_data_get(struct rrdengin
221 // madvise_dontneed(journalfile->mmap.data, journalfile->mmap.size);
222 madvise_random(journalfile->mmap.data, journalfile->mmap.size);
223
226 - spinlock_lock(&journalfile->v2.spinlock);
224 journalfile->v2.flags |= JOURNALFILE_FLAG_IS_AVAILABLE | JOURNALFILE_FLAG_IS_MOUNTED;
225 JOURNALFILE_FLAGS flags = journalfile->v2.flags;
229 - spinlock_unlock(&journalfile->v2.spinlock);
226
227 if(flags & JOURNALFILE_FLAG_MOUNTED_FOR_RETENTION) {
228 // we need the entire metrics directory into memory to process it
@@ -242,7 +238,7 @@ static struct journal_v2_header *journalfile_v2_mounted_data_get(struct rrdengin
238 *data_size = journalfile->mmap.size;
239 }
240
245 - spinlock_unlock(&journalfile->mmap.spinlock);
241 + spinlock_unlock(&journalfile->data_spinlock);
242
243 return j2_header;
244 }
@@ -252,20 +248,11 @@ static bool journalfile_v2_mounted_data_unmount(struct rrdengine_journalfile *jo
248
249 if(!have_locks) {
250 if(!wait) {
255 - if (!spinlock_trylock(&journalfile->mmap.spinlock))
251 + if (!spinlock_trylock(&journalfile->data_spinlock))
252 return false;
253 }
254 else
259 - spinlock_lock(&journalfile->mmap.spinlock);
260 -
261 - if(!wait) {
262 - if(!spinlock_trylock(&journalfile->v2.spinlock)) {
263 - spinlock_unlock(&journalfile->mmap.spinlock);
264 - return false;
265 - }
266 - }
267 - else
268 - spinlock_lock(&journalfile->v2.spinlock);
255 + spinlock_lock(&journalfile->data_spinlock);
256 }
257
258 if(!journalfile->v2.refcount) {
@@ -288,8 +275,7 @@ static bool journalfile_v2_mounted_data_unmount(struct rrdengine_journalfile *jo
275 }
276
277 if(!have_locks) {
291 - spinlock_unlock(&journalfile->v2.spinlock);
292 - spinlock_unlock(&journalfile->mmap.spinlock);
278 + spinlock_unlock(&journalfile->data_spinlock);
279 }
280
281 return unmounted;
@@ -309,7 +295,7 @@ void journalfile_v2_data_unmount_cleanup(time_t now_s) {
295 for (datafile = ctx->datafiles.first; datafile; datafile = datafile->next) {
296 struct rrdengine_journalfile *journalfile = datafile->journalfile;
297
312 - if(!spinlock_trylock(&journalfile->v2.spinlock))
298 + if(!spinlock_trylock(&journalfile->data_spinlock))
299 continue;
300
301 bool unmount = false;
@@ -324,7 +310,7 @@ void journalfile_v2_data_unmount_cleanup(time_t now_s) {
310 // enough time has passed since we last needed this journal
311 unmount = true;
312 }
327 - spinlock_unlock(&journalfile->v2.spinlock);
313 + spinlock_unlock(&journalfile->data_spinlock);
314
315 if (unmount)
316 journalfile_v2_mounted_data_unmount(journalfile, false, false);
@@ -334,7 +320,7 @@ void journalfile_v2_data_unmount_cleanup(time_t now_s) {
320 }
321
322 ALWAYS_INLINE struct journal_v2_header *journalfile_v2_data_acquire(struct rrdengine_journalfile *journalfile, size_t *data_size, time_t wanted_first_time_s, time_t wanted_last_time_s) {
337 - spinlock_lock(&journalfile->v2.spinlock);
323 + spinlock_lock(&journalfile->data_spinlock);
324
325 bool has_data = (journalfile->v2.flags & JOURNALFILE_FLAG_IS_AVAILABLE);
326 bool is_mounted = (journalfile->v2.flags & JOURNALFILE_FLAG_IS_MOUNTED);
@@ -356,7 +342,7 @@ ALWAYS_INLINE struct journal_v2_header *journalfile_v2_data_acquire(struct rrden
342
343 }
344 }
359 - spinlock_unlock(&journalfile->v2.spinlock);
345 + spinlock_unlock(&journalfile->data_spinlock);
346
347 if(do_we_need_it)
348 return journalfile_v2_mounted_data_get(journalfile, data_size);
@@ -365,7 +351,7 @@ ALWAYS_INLINE struct journal_v2_header *journalfile_v2_data_acquire(struct rrden
351 }
352
353 ALWAYS_INLINE void journalfile_v2_data_release(struct rrdengine_journalfile *journalfile) {
368 - spinlock_lock(&journalfile->v2.spinlock);
354 + spinlock_lock(&journalfile->data_spinlock);
355
356 internal_fatal(!journalfile->mmap.data, "trying to release a journalfile without data");
357 internal_fatal(journalfile->v2.refcount < 1, "trying to release a non-acquired journalfile");
@@ -380,7 +366,7 @@ ALWAYS_INLINE void journalfile_v2_data_release(struct rrdengine_journalfile *jou
366 if(journalfile->v2.flags & JOURNALFILE_FLAG_MOUNTED_FOR_RETENTION)
367 unmount = true;
368 }
383 - spinlock_unlock(&journalfile->v2.spinlock);
369 + spinlock_unlock(&journalfile->data_spinlock);
370
371 if(unmount)
372 journalfile_v2_mounted_data_unmount(journalfile, false, true);
@@ -388,18 +374,18 @@ ALWAYS_INLINE void journalfile_v2_data_release(struct rrdengine_journalfile *jou
374
375 bool journalfile_v2_data_available(struct rrdengine_journalfile *journalfile) {
376
391 - spinlock_lock(&journalfile->v2.spinlock);
377 + spinlock_lock(&journalfile->data_spinlock);
378 bool has_data = (journalfile->v2.flags & JOURNALFILE_FLAG_IS_AVAILABLE);
393 - spinlock_unlock(&journalfile->v2.spinlock);
379 + spinlock_unlock(&journalfile->data_spinlock);
380
381 return has_data;
382 }
383
384 size_t journalfile_v2_data_size_get(struct rrdengine_journalfile *journalfile) {
385
400 - spinlock_lock(&journalfile->mmap.spinlock);
386 + spinlock_lock(&journalfile->data_spinlock);
387 size_t data_size = journalfile->mmap.size;
402 - spinlock_unlock(&journalfile->mmap.spinlock);
388 + spinlock_unlock(&journalfile->data_spinlock);
389
390 return data_size;
391 }
@@ -411,8 +397,7 @@ void journalfile_v2_data_set(struct rrdengine_journalfile *journalfile, int fd,
397 if(unlikely(!journalfile->datafile))
398 fatal("DBENGINE: JOURNALFILE: trying to set journal data without a datafile");
399
414 - spinlock_lock(&journalfile->mmap.spinlock);
415 - spinlock_lock(&journalfile->v2.spinlock);
400 + spinlock_lock(&journalfile->data_spinlock);
401
402 internal_fatal(journalfile->mmap.fd != -1, "DBENGINE JOURNALFILE: trying to re-set journal fd");
403 internal_fatal(journalfile->mmap.data, "DBENGINE JOURNALFILE: trying to re-set journal_data");
@@ -431,8 +416,7 @@ void journalfile_v2_data_set(struct rrdengine_journalfile *journalfile, int fd,
416
417 journalfile_v2_mounted_data_unmount(journalfile, true, true);
418
434 - spinlock_unlock(&journalfile->v2.spinlock);
435 - spinlock_unlock(&journalfile->mmap.spinlock);
419 + spinlock_unlock(&journalfile->data_spinlock);
420
421 njfv2idx_add(journalfile->datafile);
422 }
@@ -446,8 +430,7 @@ static void journalfile_v2_data_unmap_permanently(struct rrdengine_journalfile *
430 if (has_references)
431 sleep_usec(10 * USEC_PER_MS);
432
449 - spinlock_lock(&journalfile->mmap.spinlock);
450 - spinlock_lock(&journalfile->v2.spinlock);
433 + spinlock_lock(&journalfile->data_spinlock);
434
435 if(journalfile_v2_mounted_data_unmount(journalfile, true, true)) {
436 if(journalfile->mmap.fd != -1)
@@ -465,8 +448,7 @@ static void journalfile_v2_data_unmap_permanently(struct rrdengine_journalfile *
448 internal_error(true, "DBENGINE JOURNALFILE: waiting for journalfile to be available to unmap...");
449 }
450
468 - spinlock_unlock(&journalfile->v2.spinlock);
469 - spinlock_unlock(&journalfile->mmap.spinlock);
451 + spinlock_unlock(&journalfile->data_spinlock);
452
453 } while(has_references);
454 }
@@ -475,8 +457,7 @@ struct rrdengine_journalfile *journalfile_alloc_and_init(struct rrdengine_datafi
457 {
458 struct rrdengine_journalfile *journalfile = callocz(1, sizeof(struct rrdengine_journalfile));
459 journalfile->datafile = datafile;
478 - spinlock_init(&journalfile->mmap.spinlock);
479 - spinlock_init(&journalfile->v2.spinlock);
460 + spinlock_init(&journalfile->data_spinlock);
461 spinlock_init(&journalfile->unsafe.spinlock);
462 journalfile->mmap.fd = -1;
463 datafile->journalfile = journalfile;
src/database/engine/journalfile.h
+1 -3
@@ -23,17 +23,15 @@ typedef enum __attribute__ ((__packed__)) {
23 JOURNALFILE_FLAG_METRIC_CRC_CHECK = (1 << 3),
24 } JOURNALFILE_FLAGS;
25
26 -/* only one event loop is supported for now */
26 struct rrdengine_journalfile {
27 + SPINLOCK data_spinlock;
28 struct {
29 - SPINLOCK spinlock;
29 void *data; // MMAPed file of journal v2
30 uint32_t size; // Total file size mapped
31 int fd;
32 } mmap;
33
34 struct {
36 - SPINLOCK spinlock;
35 JOURNALFILE_FLAGS flags;
36 int32_t refcount;
37 time_t first_time_s;