LCOV - code coverage report
Current view: top level - discof/vinyl - fd_vinyl_tile.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 192 0.0 %
Date: 2025-12-07 04:58:33 Functions: 0 10 0.0 %

          Line data    Source code
       1             : /* The 'vinyl' tile is a thin wrapper over 'fd_vinyl_exec'.
       2             : 
       3             :    This tile sleeps (using stem) until the system boots initial chain
       4             :    state (from snapshot or genesis).  Then, fd_vinyl_exec hijacks the
       5             :    stem run loop and takes over. */
       6             : 
       7             : #include "../../disco/topo/fd_topo.h"
       8             : #include "../../discof/restore/utils/fd_ssmsg.h"
       9             : #include "../../vinyl/fd_vinyl.h"
      10             : #include "../../vinyl/io/fd_vinyl_io_ur.h"
      11             : 
      12             : #include <errno.h>
      13             : #include <fcntl.h>
      14             : #if FD_HAS_LIBURING
      15             : #include <liburing.h>
      16             : #endif
      17             : 
      18             : #define NAME "vinyl"
      19             : #define MAX_INS 8
      20             : 
      21           0 : #define IN_KIND_GENESIS 1
      22           0 : #define IN_KIND_SNAP    2
      23             : 
      24           0 : #define IO_SPAD_MAX (32UL<<20)
      25             : 
      26             : struct fd_vinyl_tile_ctx {
      27             :   fd_vinyl_t * vinyl;
      28             :   uint         in_kind[ MAX_INS ];
      29             :   int          bstream_fd;
      30             : 
      31             :   void * io_mem;
      32             :   void * vinyl_mem;
      33             :   void * line_mem;     ulong line_footprint;
      34             :   void * cnc_mem;      ulong cnc_footprint;
      35             :   void * meta_mem;     ulong meta_footprint;
      36             :   void * ele_mem;      ulong ele_footprint;
      37             :   void * obj_mem;      ulong obj_footprint;
      38             : 
      39             :   ulong * snapin_manif_fseq;
      40             : 
      41             :   struct io_uring * ring;
      42             : # if FD_HAS_LIBURING
      43             :   struct io_uring _ring[1];
      44             : # endif
      45             : };
      46             : 
      47             : typedef struct fd_vinyl_tile_ctx fd_vinyl_tile_ctx_t;
      48             : 
      49             : #if FD_HAS_LIBURING
      50             : 
      51             : static struct io_uring_params *
      52             : vinyl_io_uring_params( struct io_uring_params * params,
      53             :                        uint                     uring_depth ) {
      54             :   memset( params, 0, sizeof(struct io_uring_params) );
      55             :   params->flags      |= IORING_SETUP_CQSIZE;
      56             :   params->cq_entries  = uring_depth;
      57             :   params->flags      |= IORING_SETUP_COOP_TASKRUN;
      58             :   params->flags      |= IORING_SETUP_SINGLE_ISSUER;
      59             :   params->flags      |= IORING_SETUP_R_DISABLED;
      60             :   params->features   |= IORING_SETUP_DEFER_TASKRUN;
      61             :   return params;
      62             : }
      63             : 
      64             : #endif
      65             : 
      66             : 
      67             : static ulong
      68           0 : scratch_align( void ) {
      69           0 :   return FD_SHMEM_HUGE_PAGE_SZ;
      70           0 : }
      71             : 
      72             : static ulong
      73           0 : scratch_footprint( fd_topo_tile_t const * tile ) {
      74           0 :   (void)tile;
      75           0 :   ulong l = FD_LAYOUT_INIT;
      76           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_vinyl_tile_ctx_t), sizeof(fd_vinyl_tile_ctx_t) );
      77           0 :   if( tile->vinyl.io_type==FD_VINYL_IO_TYPE_UR ) {
      78             : #   if FD_HAS_LIBURING
      79             :     l = FD_LAYOUT_APPEND( l, fd_vinyl_io_ur_align(), fd_vinyl_io_ur_footprint( IO_SPAD_MAX ) );
      80             : #   endif
      81           0 :   } else {
      82           0 :     l = FD_LAYOUT_APPEND( l, fd_vinyl_io_bd_align(), fd_vinyl_io_bd_footprint( IO_SPAD_MAX ) );
      83           0 :   }
      84           0 :   l = FD_LAYOUT_APPEND( l, fd_vinyl_align(),         fd_vinyl_footprint() );
      85           0 :   l = FD_LAYOUT_APPEND( l, fd_cnc_align(),           fd_cnc_footprint( FD_VINYL_CNC_APP_SZ ) );
      86           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_vinyl_line_t), sizeof(fd_vinyl_line_t)*tile->vinyl.vinyl_line_max );
      87           0 :   return FD_LAYOUT_FINI( l, scratch_align() );
      88           0 : }
      89             : 
      90             : /* vinyl_init_fast is a variation of fd_vinyl_init.  Creates tile
      91             :    private data structures and formats shared cache objects.  Reuses
      92             :    existing io/bstream/meta. */
      93             : 
      94             : static void
      95             : vinyl_init_fast( fd_vinyl_tile_ctx_t * ctx,
      96             :                  void * _vinyl,
      97             :                  void * _cnc,  ulong cnc_footprint,
      98             :                  void * _meta, ulong meta_footprint,
      99             :                  void * _line, ulong line_footprint,
     100             :                  void * _ele,  ulong ele_footprint,
     101             :                  void * _obj,  ulong obj_footprint,
     102             :                  fd_vinyl_io_t * io,
     103             :                  void *          obj_laddr0,
     104             :                  ulong           async_min,
     105             :                  ulong           async_max,
     106             :                  ulong           part_thresh,
     107             :                  ulong           gc_thresh,
     108           0 :                  int             gc_eager ) {
     109           0 :   ulong ele_max  = fd_ulong_pow2_dn( ele_footprint / sizeof( fd_vinyl_meta_ele_t ) );
     110           0 :   ulong pair_max = ele_max - 1UL;
     111           0 :   ulong line_cnt = fd_ulong_min( line_footprint / sizeof( fd_vinyl_line_t ), pair_max );
     112             : 
     113           0 :   FD_TEST( (3UL<=line_cnt) & (line_cnt<=FD_VINYL_LINE_MAX) );
     114           0 :   FD_TEST( io );
     115           0 :   FD_TEST( (0UL<async_min) & (async_min<=async_max) );
     116           0 :   FD_TEST( (-1<=gc_eager) & (gc_eager<=63) );
     117             : 
     118           0 :   fd_vinyl_t * vinyl = (fd_vinyl_t *)_vinyl;
     119           0 :   memset( vinyl, 0, fd_vinyl_footprint() );
     120             : 
     121           0 :   vinyl->cnc = fd_cnc_join( fd_cnc_new( _cnc, FD_VINYL_CNC_APP_SZ, FD_VINYL_CNC_TYPE, fd_log_wallclock() ) );
     122           0 :   FD_TEST( vinyl->cnc );
     123           0 :   vinyl->line = (fd_vinyl_line_t *)_line;
     124           0 :   vinyl->io   = io;
     125             : 
     126           0 :   vinyl->line_cnt  = line_cnt;
     127           0 :   vinyl->pair_max  = pair_max;
     128           0 :   vinyl->async_min = async_min;
     129           0 :   vinyl->async_max = async_max;
     130             : 
     131           0 :   vinyl->part_thresh  = part_thresh;
     132           0 :   vinyl->gc_thresh    = gc_thresh;
     133           0 :   vinyl->gc_eager     = gc_eager;
     134           0 :   vinyl->style        = FD_VINYL_BSTREAM_CTL_STYLE_RAW;
     135           0 :   vinyl->line_idx_lru = 0U;
     136           0 :   vinyl->pair_cnt     = 0UL;
     137           0 :   vinyl->garbage_sz   = 0UL;
     138             : 
     139           0 :   FD_TEST( fd_vinyl_meta_join( vinyl->meta, _meta, _ele ) );
     140             : 
     141           0 :   FD_TEST( fd_vinyl_data_init( vinyl->data, _obj, obj_footprint, obj_laddr0 ) );
     142           0 :   fd_vinyl_data_reset( NULL, 0UL, 0UL, 0, vinyl->data );
     143             : 
     144           0 :   vinyl->cnc_footprint  = cnc_footprint;
     145           0 :   vinyl->meta_footprint = meta_footprint;
     146           0 :   vinyl->line_footprint = line_footprint;
     147           0 :   vinyl->ele_footprint  = ele_footprint;
     148           0 :   vinyl->obj_footprint  = obj_footprint;
     149             : 
     150           0 :   ctx->vinyl = vinyl;
     151             : 
     152           0 :   FD_LOG_NOTICE(( "Vinyl config"
     153           0 :                   "\n\tline_cnt    %lu pairs"
     154           0 :                   "\n\tpair_max    %lu pairs"
     155           0 :                   "\n\tasync_min   %lu min iterations per async"
     156           0 :                   "\n\tasync_max   %lu max iterations per async"
     157           0 :                   "\n\tpart_thresh %lu bytes"
     158           0 :                   "\n\tgc_thresh   %lu bytes"
     159           0 :                   "\n\tgc_eager    %i",
     160           0 :                   line_cnt, pair_max, async_min, async_max, part_thresh, gc_thresh, gc_eager ));
     161           0 : }
     162             : 
     163             : #if FD_HAS_LIBURING
     164             : 
     165             : static void
     166             : vinyl_io_uring_init( fd_vinyl_tile_ctx_t * ctx,
     167             :                      uint                  uring_depth,
     168             :                      int                   dev_fd ) {
     169             :   ctx->ring = ctx->_ring;
     170             : 
     171             :   /* Setup io_uring instance */
     172             :   struct io_uring_params params[1];
     173             :   vinyl_io_uring_params( params, uring_depth );
     174             :   int init_err = io_uring_queue_init_params( uring_depth, ctx->ring, params );
     175             :   if( FD_UNLIKELY( init_err<0 ) ) FD_LOG_ERR(( "io_uring_queue_init_params failed (%i-%s)", init_err, fd_io_strerror( -init_err ) ));
     176             : 
     177             :   /* Setup io_uring file access */
     178             :   FD_TEST( 0==io_uring_register_files( ctx->ring, &dev_fd, 1 ) );
     179             : 
     180             :   /* Register restrictions */
     181             :   struct io_uring_restriction res[3] = {
     182             :     { .opcode    = IORING_RESTRICTION_SQE_OP,
     183             :       .sqe_op    = IORING_OP_READ },
     184             :     { .opcode    = IORING_RESTRICTION_SQE_FLAGS_REQUIRED,
     185             :       .sqe_flags = IOSQE_FIXED_FILE },
     186             :     { .opcode    = IORING_RESTRICTION_SQE_FLAGS_ALLOWED,
     187             :       .sqe_flags = IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS }
     188             :   };
     189             :   int res_err = io_uring_register_restrictions( ctx->ring, res, 3U );
     190             :   if( FD_UNLIKELY( res_err<0 ) ) FD_LOG_ERR(( "io_uring_register_restrictions failed (%i-%s)", res_err, fd_io_strerror( -res_err ) ));
     191             : 
     192             :   /* Enable rings */
     193             :   int enable_err = io_uring_enable_rings( ctx->ring );
     194             :   if( FD_UNLIKELY( enable_err<0 ) ) FD_LOG_ERR(( "io_uring_enable_rings failed (%i-%s)", enable_err, fd_io_strerror( -enable_err ) ));
     195             : }
     196             : 
     197             : #else /* no io_uring */
     198             : 
     199             : static void
     200             : vinyl_io_uring_init( fd_vinyl_tile_ctx_t * ctx,
     201             :                      uint                  uring_depth,
     202           0 :                      int                   dev_fd ) {
     203           0 :   (void)ctx; (void)uring_depth; (void)dev_fd;
     204           0 :   FD_LOG_ERR(( "Sorry, this build does not support io_uring" ));
     205           0 : }
     206             : 
     207             : #endif
     208             : 
     209             : static void
     210             : privileged_init( fd_topo_t *      topo,
     211           0 :                  fd_topo_tile_t * tile ) {
     212           0 :   ulong cnc_footprint = fd_cnc_footprint( FD_VINYL_CNC_APP_SZ );
     213           0 :   ulong line_footprint;
     214           0 :   if( FD_UNLIKELY( !tile->vinyl.vinyl_line_max || __builtin_umull_overflow( tile->vinyl.vinyl_line_max, sizeof(fd_vinyl_line_t), &line_footprint ) ) ) {
     215           0 :     FD_LOG_ERR(( "invalid vinyl_line_max %lu", tile->vinyl.vinyl_line_max ));
     216           0 :   }
     217             : 
     218           0 :   void * tile_mem = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     219           0 :   FD_SCRATCH_ALLOC_INIT( l, tile_mem );
     220           0 :   fd_vinyl_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_vinyl_tile_ctx_t), sizeof(fd_vinyl_tile_ctx_t) );
     221           0 :   void * _io = NULL;
     222           0 :   if( tile->vinyl.io_type==FD_VINYL_IO_TYPE_UR ) {
     223             : #   if FD_HAS_LIBURING
     224             :     _io = FD_SCRATCH_ALLOC_APPEND( l, fd_vinyl_io_ur_align(), fd_vinyl_io_ur_footprint( IO_SPAD_MAX ) );
     225             : #   endif
     226           0 :   } else {
     227           0 :     _io = FD_SCRATCH_ALLOC_APPEND( l, fd_vinyl_io_bd_align(), fd_vinyl_io_bd_footprint( IO_SPAD_MAX ) );
     228           0 :   }
     229           0 :   void *            vinyl_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_vinyl_align(), fd_vinyl_footprint()   );
     230           0 :   void *            _cnc      = FD_SCRATCH_ALLOC_APPEND( l, fd_cnc_align(),   cnc_footprint          );
     231           0 :   fd_vinyl_line_t * _line     = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_vinyl_line_t), line_footprint );
     232           0 :   ulong             _end      = FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
     233           0 :   FD_TEST( (ulong)tile_mem==(ulong)ctx );
     234           0 :   FD_TEST( (ulong)_end-(ulong)tile_mem==scratch_footprint( tile ) );
     235             : 
     236           0 :   memset( ctx, 0, sizeof(fd_vinyl_tile_ctx_t) );
     237             : 
     238           0 :   void * _meta = fd_topo_obj_laddr( topo, tile->vinyl.vinyl_meta_map_obj_id  );
     239           0 :   void * _ele  = fd_topo_obj_laddr( topo, tile->vinyl.vinyl_meta_pool_obj_id );
     240           0 :   void * _obj  = fd_topo_obj_laddr( topo, tile->vinyl.vinyl_data_obj_id      );
     241             : 
     242           0 :   ctx->io_mem    = _io;
     243           0 :   ctx->vinyl_mem = vinyl_mem;
     244           0 :   ctx->cnc_mem   = _cnc;   ctx->cnc_footprint  = cnc_footprint;
     245           0 :   ctx->meta_mem  = _meta;  ctx->meta_footprint = topo->objs[ tile->vinyl.vinyl_meta_map_obj_id  ].footprint;
     246           0 :   ctx->line_mem  = _line;  ctx->line_footprint = line_footprint;
     247           0 :   ctx->ele_mem   = _ele;   ctx->ele_footprint  = topo->objs[ tile->vinyl.vinyl_meta_pool_obj_id ].footprint;
     248           0 :   ctx->obj_mem   = _obj;   ctx->obj_footprint  = topo->objs[ tile->vinyl.vinyl_data_obj_id      ].footprint;
     249             : 
     250             :   /* FIXME use O_DIRECT? */
     251           0 :   int dev_fd = open( tile->vinyl.vinyl_bstream_path, O_RDWR|O_CLOEXEC );
     252           0 :   if( FD_UNLIKELY( dev_fd<0 ) ) FD_LOG_ERR(( "open(%s,O_RDWR|O_CLOEXEC) failed (%i-%s)", tile->vinyl.vinyl_bstream_path, errno, fd_io_strerror( errno ) ));
     253             : 
     254           0 :   ctx->bstream_fd = dev_fd;
     255             : 
     256           0 :   int io_type = tile->vinyl.io_type;
     257           0 :   if( io_type==FD_VINYL_IO_TYPE_UR ) {
     258           0 :     vinyl_io_uring_init( ctx, tile->vinyl.uring_depth, dev_fd );
     259           0 :   } else if( io_type!=FD_VINYL_IO_TYPE_BD ) {
     260           0 :     FD_LOG_ERR(( "Unsupported vinyl io_type %d", io_type ));
     261           0 :   }
     262           0 : }
     263             : 
     264             : static void
     265             : unprivileged_init( fd_topo_t *      topo,
     266           0 :                    fd_topo_tile_t * tile ) {
     267             : 
     268           0 :   fd_vinyl_tile_ctx_t * ctx = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     269             : 
     270           0 :   ulong manif_in_idx = fd_topo_find_tile_in_link( topo, tile, "snapin_manif", 0UL );
     271           0 :   FD_TEST( manif_in_idx!=ULONG_MAX );
     272           0 :   FD_TEST( manif_in_idx<MAX_INS );
     273           0 :   ctx->in_kind[ manif_in_idx ] = IN_KIND_SNAP;
     274             : 
     275             :   /* Join a public CNC if provided (development only) */
     276           0 :   if( tile->vinyl.vinyl_cnc_obj_id!=ULONG_MAX ) {
     277           0 :     ctx->cnc_mem       = fd_topo_obj_laddr( topo, tile->vinyl.vinyl_cnc_obj_id );
     278           0 :     ctx->cnc_footprint = topo->objs[ tile->vinyl.vinyl_cnc_obj_id ].footprint;
     279           0 :   }
     280             : 
     281           0 :   fd_topo_link_t const * in_link = &topo->links[ tile->in_link_id[ 0 ] ];
     282           0 :   FD_TEST( in_link && 0==strcmp( in_link->name, "snapin_manif" ) );
     283           0 :   if( FD_UNLIKELY( !tile->in_link_reliable[ 0 ] ) ) FD_LOG_ERR(( "tile `" NAME "` in link 0 must be reliable" ));
     284           0 :   ctx->snapin_manif_fseq = tile->in_link_fseq[ 0 ];
     285           0 : }
     286             : 
     287             : __attribute__((noreturn)) static void
     288           0 : enter_vinyl_exec( fd_vinyl_tile_ctx_t * ctx ) {
     289             : 
     290           0 :   fd_vinyl_io_t * io = NULL;
     291           0 :   if( ctx->ring ) {
     292           0 :     io = fd_vinyl_io_ur_init( ctx->io_mem, IO_SPAD_MAX, ctx->bstream_fd, ctx->ring );
     293           0 :     if( FD_UNLIKELY( !io ) ) FD_LOG_ERR(( "Failed to initialize io_uring I/O backend for account database" ));
     294           0 :   } else {
     295           0 :     io = fd_vinyl_io_bd_init( ctx->io_mem, IO_SPAD_MAX, ctx->bstream_fd, 0, NULL, 0UL, 0UL );
     296           0 :     if( FD_UNLIKELY( !io ) ) FD_LOG_ERR(( "Failed to initialize blocking I/O backend for account database" ));
     297           0 :   }
     298             : 
     299           0 :   ulong async_min   =         5UL;
     300           0 :   ulong async_max   = 2*async_min;
     301           0 :   ulong part_thresh =    64UL<<20;
     302           0 :   ulong gc_thresh   =   128UL<<20;
     303           0 :   int   gc_eager    =           2;
     304             : 
     305           0 :   vinyl_init_fast(
     306           0 :       ctx,
     307           0 :       ctx->vinyl_mem,
     308           0 :       ctx->cnc_mem,  ctx->cnc_footprint,
     309           0 :       ctx->meta_mem, ctx->meta_footprint,
     310           0 :       ctx->line_mem, ctx->line_footprint,
     311           0 :       ctx->ele_mem,  ctx->ele_footprint,
     312           0 :       ctx->obj_mem,  ctx->obj_footprint,
     313           0 :       io,
     314           0 :       fd_wksp_containing( ctx->obj_mem ),
     315           0 :       async_min, async_max,
     316           0 :       part_thresh,
     317           0 :       gc_thresh,
     318           0 :       gc_eager );
     319             : 
     320           0 :   fd_vinyl_line_t * line     = ctx->vinyl->line;
     321           0 :   ulong const       line_cnt = ctx->vinyl->line_cnt;
     322           0 :   for( ulong line_idx=0UL; line_idx<line_cnt; line_idx++ ) {
     323           0 :     line[ line_idx ].obj            = NULL;
     324           0 :     line[ line_idx ].ele_idx        = ULONG_MAX;
     325           0 :     line[ line_idx ].ctl            = fd_vinyl_line_ctl( 0UL, 0L);
     326           0 :     line[ line_idx ].line_idx_older = (uint)fd_ulong_if( line_idx!=0UL,          line_idx-1UL, line_cnt-1UL );
     327           0 :     line[ line_idx ].line_idx_newer = (uint)fd_ulong_if( line_idx!=line_cnt-1UL, line_idx+1UL, 0UL          );
     328           0 :   }
     329             : 
     330           0 :   fd_vinyl_exec( ctx->vinyl );
     331           0 :   FD_LOG_CRIT(( "Vinyl tile stopped unexpectedly" ));
     332           0 : }
     333             : 
     334             : static void
     335             : on_genesis_ctrl( fd_vinyl_tile_ctx_t * ctx,
     336           0 :                  ulong                 sig ) {
     337           0 :   (void)ctx; (void)sig;
     338           0 :   FD_LOG_ERR(( "Sorry, booting off vinyl is not yet supported" ));
     339           0 : }
     340             : 
     341             : static void
     342             : on_snap_ctrl( fd_vinyl_tile_ctx_t * ctx,
     343           0 :               ulong                 sig ) {
     344           0 :   ulong msg_type = fd_ssmsg_sig_message( sig );
     345           0 :   if( msg_type==FD_SSMSG_DONE ) {
     346           0 :     FD_LOG_INFO(( "Vinyl tile booting" ));
     347           0 :     fd_fseq_update( ctx->snapin_manif_fseq, ULONG_MAX-1UL ); /* mark consumer as shut down */
     348           0 :     enter_vinyl_exec( ctx );
     349           0 :   }
     350           0 : }
     351             : 
     352             : static inline void
     353             : during_frag( fd_vinyl_tile_ctx_t * ctx,
     354             :              ulong                 in_idx,
     355             :              ulong                 seq,
     356             :              ulong                 sig,
     357             :              ulong                 chunk,
     358             :              ulong                 sz     FD_PARAM_UNUSED,
     359           0 :              ulong                 ctl    FD_PARAM_UNUSED ) {
     360           0 :   (void)seq; (void)chunk;
     361           0 :   switch( ctx->in_kind[ in_idx ] ) {
     362           0 :   case IN_KIND_GENESIS:
     363           0 :     on_genesis_ctrl( ctx, sig );
     364           0 :     break;
     365           0 :   case IN_KIND_SNAP:
     366           0 :     on_snap_ctrl( ctx, sig );
     367           0 :     break;
     368           0 :   default:
     369           0 :     FD_LOG_CRIT(( "Frag from unexpected in_idx %lu", in_idx ));
     370           0 :   }
     371           0 : }
     372             : 
     373           0 : #define STEM_BURST (1UL)
     374           0 : #define STEM_CALLBACK_CONTEXT_TYPE  fd_vinyl_tile_ctx_t
     375           0 : #define STEM_CALLBACK_CONTEXT_ALIGN fd_vinyl_align()
     376           0 : #define STEM_CALLBACK_DURING_FRAG   during_frag
     377             : 
     378             : #include "../../disco/stem/fd_stem.c"
     379             : 
     380             : fd_topo_run_tile_t fd_tile_vinyl = {
     381             :   .name              = NAME,
     382             :   .scratch_align     = scratch_align,
     383             :   .scratch_footprint = scratch_footprint,
     384             :   .privileged_init   = privileged_init,
     385             :   .unprivileged_init = unprivileged_init,
     386             :   .run               = stem_run
     387             : };
     388             : 
     389             : #undef NAME

Generated by: LCOV version 1.14