From 8882683acf59c1da33fb8ce2a25183018a76b8b8 Mon Sep 17 00:00:00 2001 From: Gancho Tenev <10522628+gtenev@users.noreply.github.com> Date: Thu, 23 Jul 2020 09:37:19 -0700 Subject: [PATCH] Fixed problem with all "forced" volumes cache (#7028) Fixed a problem with cache volume configurations where all volumes are forced to a span (disk) in storage.config and percentage size is used in volume.config. Since "forced" volumes are now excluded from "total cache space" used for volume size percentage calculations when all spans (disks) are "forced" to volumes the "total cache space" becomes 0 and then volume sizes calculated as percentage become 0. This patch fixes the issue and also handles the case when a single volume is forced to multiple spans. (cherry picked from commit 26ddf1ed4c3b68242830aa0470ff23ef3954bd9a) --- iocore/cache/Cache.cc | 61 ++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index d1f2a3eb7ae..387812dafa0 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -2719,21 +2719,26 @@ cplist_update() if (nullptr == config_vol->cachep) { // Find out if this is a forced volume assigned exclusively to a span which was cleared (hence not referenced in cp_list). // Note: non-exclusive cleared spans are not handled here, only the "exclusive" + bool forced_volume = false; for (int d_no = 0; d_no < gndisks; d_no++) { if (gdisks[d_no]->forced_volume_num == config_vol->number) { - CacheVol *new_cp = new CacheVol(); - if (nullptr != new_cp) { - new_cp->disk_vols = (DiskVol **)ats_malloc(gndisks * sizeof(DiskVol *)); - if (nullptr != new_cp->disk_vols) { - memset(new_cp->disk_vols, 0, gndisks * sizeof(DiskVol *)); - new_cp->vol_number = config_vol->number; - new_cp->scheme = config_vol->scheme; - config_vol->cachep = new_cp; - fillExclusiveDisks(config_vol->cachep); - cp_list.enqueue(new_cp); - } else { - delete new_cp; - } + forced_volume = true; + } + } + + if (forced_volume) { + CacheVol *new_cp = new CacheVol(); + if (nullptr != new_cp) { + new_cp->disk_vols = static_castdisk_vols)>(ats_malloc(gndisks * sizeof(DiskVol *))); + if (nullptr != new_cp->disk_vols) { + memset(new_cp->disk_vols, 0, gndisks * sizeof(DiskVol *)); + new_cp->vol_number = config_vol->number; + new_cp->scheme = config_vol->scheme; + config_vol->cachep = new_cp; + fillExclusiveDisks(config_vol->cachep); + cp_list.enqueue(new_cp); + } else { + delete new_cp; } } } @@ -2761,7 +2766,7 @@ fillExclusiveDisks(CacheVol *cp) /* There should be a single "forced" volume and no other volumes should exist on this "exclusive" disk (span) */ bool found_nonforced_volumes = false; - for (int j = 0; j < (int)gdisks[i]->header->num_volumes; j++) { + for (int j = 0; j < static_cast(gdisks[i]->header->num_volumes); j++) { if (volume_number != gdisks[i]->disk_vols[j]->vol_number) { found_nonforced_volumes = true; break; @@ -2777,7 +2782,7 @@ fillExclusiveDisks(CacheVol *cp) continue; } - /* Now, volumes have been either deleted or did not existing to begin with so we need to create them. */ + /* Now, volumes have been either deleted or did not exist to begin with so we need to create them. */ int64_t size_diff = gdisks[i]->num_usable_blocks; DiskVolBlock *dpb; do { @@ -2876,14 +2881,34 @@ cplist_reconfigure() Warning("no volumes created"); return -1; } - int64_t space_in_blks = (int64_t)(((double)(config_vol->percent / percent_remaining)) * tot_space_in_blks); + + // Find if the volume is forced and if it is then calculate the total forced volume size. + // Forced volumes take the whole span (disk) also sum all disk space this volume is forced to. + int64_t tot_forced_space_in_blks = 0; + for (int i = 0; i < gndisks; i++) { + if (config_vol->number == gdisks[i]->forced_volume_num) { + tot_forced_space_in_blks += (gdisks[i]->num_usable_blocks / blocks_per_vol) * blocks_per_vol; + } + } + + int64_t space_in_blks = 0; + if (0 == tot_forced_space_in_blks) { + // Calculate the space as percentage of total space in blocks. + space_in_blks = static_cast(((double)(config_vol->percent / percent_remaining)) * tot_space_in_blks); + } else { + // Forced volumes take all disk space, so no percentage calculations here. + space_in_blks = tot_forced_space_in_blks; + } space_in_blks = space_in_blks >> (20 - STORE_BLOCK_SHIFT); /* round down to 128 megabyte multiple */ space_in_blks = (space_in_blks >> 7) << 7; config_vol->size = space_in_blks; - tot_space_in_blks -= space_in_blks << (20 - STORE_BLOCK_SHIFT); - percent_remaining -= (config_vol->size < 128) ? 0 : config_vol->percent; + + if (0 == tot_forced_space_in_blks) { + tot_space_in_blks -= space_in_blks << (20 - STORE_BLOCK_SHIFT); + percent_remaining -= (config_vol->size < 128) ? 0 : config_vol->percent; + } } if (config_vol->size < 128) { Warning("the size of volume %d (%" PRId64 ") is less than the minimum required volume size %d", config_vol->number,