4141
4242#include < stdlib.h>
4343
44+ #include < quill/Quill.h>
45+
4446#include < asm-generic/ioctl.h>
4547#include < fcntl.h>
4648#include < linux/falloc.h>
@@ -80,6 +82,12 @@ size_t storage_pool::device_t::chunks() const
8082 return metadata_->chunks (size_of_file_);
8183}
8284
85+ size_t storage_pool::device_t::cnv_chunks () const
86+ {
87+ MONAD_ASSERT (!is_zoned_device (), " zonefs support isn't implemented yet" );
88+ return metadata_->num_cnv_chunks ;
89+ }
90+
8391std::pair<file_offset_t , file_offset_t > storage_pool::device_t::capacity () const
8492{
8593 switch (type_) {
@@ -454,6 +462,7 @@ storage_pool::device_t storage_pool::make_device_(
454462 memcpy (metadata_footer->magic , " MND0" , 4 );
455463 metadata_footer->chunk_capacity =
456464 static_cast <uint32_t >(chunk_capacity);
465+ metadata_footer->num_cnv_chunks = flags.num_cnv_chunks ;
457466 MONAD_ASSERT_PRINTF (
458467 ::pwrite (
459468 readwritefd,
@@ -465,6 +474,15 @@ storage_pool::device_t storage_pool::make_device_(
465474 }
466475 total_size =
467476 metadata_footer->total_size (static_cast <size_t >(stat.st_size ));
477+ if (flags.num_cnv_chunks > metadata_footer->num_cnv_chunks ) {
478+ LOG_WARNING (
479+ " Flag-specified num_cnv_chunks ({}) exceeds the value in "
480+ " metadata ({}) on the existing database. "
481+ " Existing databases cannot be reconfigured to use more chunks. "
482+ " Please create a new database to increase num_cnv_chunks." ,
483+ flags.num_cnv_chunks ,
484+ metadata_footer->num_cnv_chunks );
485+ }
468486 }
469487 size_t const offset = round_down_align<CPU_PAGE_BITS>(
470488 static_cast <size_t >(stat.st_size ) - total_size);
@@ -504,21 +522,29 @@ void storage_pool::fill_chunks_(creation_flags const &flags)
504522 fnv1a_hash<uint32_t >::add (
505523 hashshouldbe, uint32_t (device.unique_hash_ >> 32 ));
506524 }
525+ // Backward compatibility: databases created before `num_cnv_chunks` was
526+ // added have this field set to 0. Treat 0 as the legacy default of 3
527+ // chunks.
528+ uint32_t const cnv_chunks_count =
529+ devices_[0 ].metadata_ ->num_cnv_chunks == 0
530+ ? 3
531+ : devices_[0 ].metadata_ ->num_cnv_chunks ;
507532 std::vector<size_t > chunks;
508533 size_t total = 0 ;
509534 chunks.reserve (devices_.size ());
510535 for (auto const &device : devices_) {
511536 if (device.is_file () || device.is_block_device ()) {
512537 auto const devicechunks = device.chunks ();
513538 MONAD_ASSERT_PRINTF (
514- devicechunks >= 4 ,
515- " Device %s has %zu chunks the minimum allowed is four ." ,
539+ devicechunks >= cnv_chunks_count + 1 ,
540+ " Device %s has %zu chunks the minimum allowed is %u ." ,
516541 device.current_path ().c_str (),
517- devicechunks);
542+ devicechunks,
543+ cnv_chunks_count + 1 );
518544 MONAD_ASSERT (devicechunks <= std::numeric_limits<uint32_t >::max ());
519- // Take off three for the cnv chunks
520- chunks.push_back (devicechunks - 3 );
521- total += devicechunks - 3 ;
545+ // Take off cnv_chunks_count for the cnv chunks
546+ chunks.push_back (devicechunks - cnv_chunks_count );
547+ total += devicechunks - cnv_chunks_count ;
522548 fnv1a_hash<uint32_t >::add (
523549 hashshouldbe, static_cast <uint32_t >(devicechunks));
524550 fnv1a_hash<uint32_t >::add (
@@ -560,22 +586,17 @@ void storage_pool::fill_chunks_(creation_flags const &flags)
560586 auto const zone_id = [this ](int const chunk_type) {
561587 return static_cast <uint32_t >(chunks_[chunk_type].size ());
562588 };
563- // First three blocks of each device goes to conventional, remainder go to
564- // sequential
565- chunks_[cnv].reserve (devices_.size () * 3 );
589+ // First cnv_chunks_count blocks of each device goes to conventional,
590+ // remainder go to sequential
591+ chunks_[cnv].reserve (devices_.size () * cnv_chunks_count );
566592 chunks_[seq].reserve (total);
567593 if (flags.interleave_chunks_evenly ) {
568- for (auto &device : devices_) {
569- chunks_[cnv].emplace_back (
570- activate_chunk (storage_pool::cnv, device, 0 , zone_id (cnv)));
571- }
572- for (auto &device : devices_) {
573- chunks_[cnv].emplace_back (
574- activate_chunk (storage_pool::cnv, device, 1 , zone_id (cnv)));
575- }
576- for (auto &device : devices_) {
577- chunks_[cnv].emplace_back (
578- activate_chunk (storage_pool::cnv, device, 2 , zone_id (cnv)));
594+ for (uint32_t chunk_idx = 0 ; chunk_idx < cnv_chunks_count;
595+ ++chunk_idx) {
596+ for (auto &device : devices_) {
597+ chunks_[cnv].emplace_back (activate_chunk (
598+ storage_pool::cnv, device, chunk_idx, zone_id (cnv)));
599+ }
579600 }
580601 // We now need to evenly spread the sequential chunks such that if
581602 // device A has 20, device B has 10 and device C has 5, the interleaving
@@ -585,7 +606,7 @@ void storage_pool::fill_chunks_(creation_flags const &flags)
585606 for (size_t n = 0 ; n < chunks.size (); n++) {
586607 chunkratios[n] = double (total) / static_cast <double >(chunks[n]);
587608 chunkcounts[n] = chunkratios[n];
588- chunks[n] = 3 ;
609+ chunks[n] = cnv_chunks_count ;
589610 }
590611 while (chunks_[seq].size () < chunks_[seq].capacity ()) {
591612 for (size_t n = 0 ; n < chunks.size (); n++) {
@@ -612,19 +633,18 @@ void storage_pool::fill_chunks_(creation_flags const &flags)
612633 }
613634 else {
614635 for (auto &device : devices_) {
615- chunks_[cnv].emplace_back (
616- activate_chunk (cnv, device, 0 , zone_id (cnv)));
617- chunks_[cnv].emplace_back (
618- activate_chunk (cnv, device, 1 , zone_id (cnv)));
619- chunks_[cnv].emplace_back (
620- activate_chunk (cnv, device, 2 , zone_id (cnv)));
636+ for (uint32_t chunk_idx = 0 ; chunk_idx < cnv_chunks_count;
637+ ++chunk_idx) {
638+ chunks_[cnv].emplace_back (
639+ activate_chunk (cnv, device, chunk_idx, zone_id (cnv)));
640+ }
621641 }
622642 for (size_t deviceidx = 0 ; deviceidx < chunks.size (); deviceidx++) {
623643 for (size_t n = 0 ; n < chunks[deviceidx]; n++) {
624644 chunks_[seq].emplace_back (activate_chunk (
625645 seq,
626646 devices_[deviceidx],
627- static_cast <uint32_t >(3 + n),
647+ static_cast <uint32_t >(cnv_chunks_count + n),
628648 zone_id (seq)));
629649 }
630650 }
0 commit comments