Skip to content

Commit 0191fcf

Browse files
authored
DAOS-18860 control: calc engine mem_size only on tgt count (#18407) (#18443)
Pass memory size calculation to engine based on a 1gib/tgt quota despite control-plane hugepage allocations taking MD-on-SSD System-XStream into account when calculating. Reorganize test cases in server_utils_test.go by splitting error scenarios into a dedicated test function. Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
1 parent edb803e commit 0191fcf

4 files changed

Lines changed: 206 additions & 94 deletions

File tree

src/control/server/engine/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,13 +777,13 @@ func (c *Config) WithLogSubsystems(subsystems string) *Config {
777777
return c
778778
}
779779

780-
// WithMemSize sets the NVMe memory size for SPDK memory allocation on this instance.
780+
// WithMemSize sets the NVMe memory size in MiB for SPDK memory allocation on this instance.
781781
func (c *Config) WithMemSize(memsize int) *Config {
782782
c.MemSize = memsize
783783
return c
784784
}
785785

786-
// WithHugepageSize sets the configured hugepage size on this instance.
786+
// WithHugepageSize sets the configured hugepage size in MiB on this instance.
787787
func (c *Config) WithHugepageSize(hugepagesz int) *Config {
788788
c.HugepageSz = hugepagesz
789789
return c

src/control/server/server_utils.go

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -494,49 +494,52 @@ func setDaosHelperEnvs(cfg *config.Server, setenv func(k, v string) error) error
494494

495495
// Per-NUMA hugepage allocations have been calculated and requested from kernel in prepBdevStorage
496496
// so now set mem-size values for engines and verify there are enough free hugepages to satisfy
497-
// typical DMA buffer requirements.
498-
func setEngineMemSize(srv *server, ei *EngineInstance, smi *common.SysMemInfo) {
497+
// typical DMA buffer requirements. Note that mem_size generally follows the 1gib-per-tgt rule
498+
// whereas hugepage allocations made in prepBdevStorage may be slightly different.
499+
func setEngineMemSize(srv *server, ei *EngineInstance, smi *common.SysMemInfo) error {
499500
ei.RLock()
500501
ec := ei.runner.GetConfig()
501502
eIdx := ec.Index
502503

503504
if ec.Storage.Tiers.Bdevs().Len() == 0 {
504505
srv.log.Debugf("skipping mem check on engine %d, no bdevs", eIdx)
505506
ei.RUnlock()
506-
return
507+
return nil
507508
}
508509
ei.RUnlock()
509510

510-
// Mem-size for each engine to be calculated based on server config total hugepage
511-
// requirements. Mem-size should be the same for each engine to avoid performance imbalance
511+
// nrPagesRequired is per-engine and to be calculated based on engine config target counts.
512+
// Mem-size should be the same for each engine to avoid performance imbalance
512513
// and will act as memory cap to stop DMA buffer growing beyond mem-size.
513-
nrPagesRequired := srv.cfg.NrHugepages / len(srv.cfg.Engines)
514+
nrPagesRequired, err := storage.CalcMinHugepages(smi.HugepageSizeKiB, ec.TargetCount)
515+
if err != nil {
516+
return errors.Wrapf(err, "calculating hugepage mem_size for engine %d", eIdx)
517+
}
514518

515519
// Global (rather than per-NUMA) meminfo stats used to verify sufficient free hugepages as
516520
// engines should be started even if hugemem has to be used across NUMA boundaries.
517521
nrPagesFree := smi.HugepagesFree
518522

519-
// Calculate mem_size per I/O engine (in MB) based on number of pages required per engine.
523+
// Calculate mem_size per I/O engine (in MiB) based on number of pages required per engine.
520524
pageSizeMiB := smi.HugepageSizeKiB / humanize.KiByte // kib to mib
521525
memSizeReqMiB := nrPagesRequired * pageSizeMiB
522526
memSizeFreeMiB := nrPagesFree * pageSizeMiB
523527

524-
// If free hugepage mem is not enough to meet requested number of hugepages, log notice and
525-
// set mem_size engine parameter to free value. Otherwise set to requested value.
526-
memSizeMiB := memSizeReqMiB
528+
// If free hugepage mem is not enough to meet requested number of hugepages, log notice.
527529
if memSizeFreeMiB < memSizeReqMiB {
528530
srv.log.Noticef("The amount of hugepage memory available for engine %d (%s, %d "+
529-
"hugepages) does not meet what is required (%s, %d hugepages)", ei.Index(),
531+
"hugepages) does not meet what is required (%s, %d hugepages)", eIdx,
530532
humanize.IBytes(uint64(humanize.MiByte*memSizeFreeMiB)), nrPagesFree,
531533
humanize.IBytes(uint64(humanize.MiByte*memSizeReqMiB)), nrPagesRequired)
532-
memSizeMiB = memSizeFreeMiB
533534
}
534535

535536
// Set hugepage_size (MiB) values based on hugepage info.
536-
srv.log.Debugf("Per-engine MemSize:%dMB, HugepageSize:%dMB (meminfo: %s)", memSizeMiB,
537-
pageSizeMiB, smi.Summary())
538-
ei.setMemSize(memSizeMiB)
537+
srv.log.Debugf("Engine %d Per-engine MemSize:%dMiB, HugepageSize:%dMiB (meminfo: %s)",
538+
eIdx, memSizeReqMiB, pageSizeMiB, smi.Summary())
539+
ei.setMemSize(memSizeReqMiB)
539540
ei.setHugepageSz(pageSizeMiB)
541+
542+
return nil
540543
}
541544

542545
// Clean SPDK resources, both lockfiles and orphaned hugepages. Orphaned hugepages will be cleaned
@@ -697,7 +700,9 @@ func registerEngineEventCallbacks(srv *server, engine *EngineInstance, allStarte
697700
}
698701

699702
// Update engine memory related config parameters before starting.
700-
setEngineMemSize(srv, engine, smi)
703+
if err := setEngineMemSize(srv, engine, smi); err != nil {
704+
return errors.Wrap(err, "set engine mem_size value")
705+
}
701706

702707
// Check available RAM can satisfy tmpfs size before starting a new engine.
703708
if err := checkEngineTmpfsMem(srv, engine, smi); err != nil {

0 commit comments

Comments
 (0)