Repository navigation
Conversation
|
Ticket title is 'Hot-plugged drive claimed by the wrong engine' |
|
Test stage Functional Hardware Medium MD on SSD completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-19259/1/testReport/ |
c81a73a to
2dec464
Compare
|
Test stage Unit Test completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-19259/5/testReport/ |
2dec464 to
d225cee
Compare
|
Test stage Functional Hardware Medium MD on SSD completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-19259/6/testReport/ |
|
CI build 6 known failures with
Fix validated on Trout, Hotplug polling and replacement works as expected, manual verification process documented in ticket DAOS-19772. |
d225cee to
17d0124
Compare
kjacque
left a comment
There was a problem hiding this comment.
Only looked at the applicable commit... LGTM. My one comment is very minor. I guess this will need to be rebased before merging to remove the system erase commit?
|
Test stage Functional Hardware Medium MD on SSD completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-19259/7/testReport/ |
Features: control Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
17d0124 to
c7fa0ff
Compare
Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
Features: control Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
…in' into tanabarr/control-hotplug-pcidomain Features: control Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
|
Test stage Unit Test completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-19259/19/testReport/ |
knard38
left a comment
There was a problem hiding this comment.
If my concerns are valid they should be fixed before landing
| @@ -633,9 +621,9 @@ func BdevWriteConfigRequestFromConfig(ctx context.Context, log logging.Logger, c | |||
There was a problem hiding this comment.
From my understanding, the previous hwloc-based derivation returned the bus range of the PCI host bridges of the whole NUMA node, so the filter did not depend on the bdev tiers. Now it is derived from bdev_list, which only lists the devices of one tier, and setHotplugRanges() is only called for the first bdev tier (idx != 0 is skipped).
For example, with the configuration below the filter written to daos_nvme.conf is only 0000:e3, so the SSDs of the second tier (0000:e4, 0000:e5 and 0000:e6) would be refused by their own engine.
storage:
- class: ram
scm_mount: /mnt/dram1
- class: nvme # first bdev tier (idx 0)
bdev_roles: [wal]
bdev_list: ["0000:e3:00.0"]
- class: nvme # second bdev tier (idx 1)
bdev_roles: [meta, data]
bdev_list: ["0000:e4:00.0", "0000:e5:00.0", "0000:e6:00.0"]| // TestStorage_BdevHotplugRange_JSON is a regression test for JSON marshal/unmarshal of | ||
| // BdevHotplugRange. | ||
| func TestStorage_BdevHotplugRange_JSON(t *testing.T) { | ||
| hr, err := NewBdevHotplugRange("0x01:0x00-0xFF") |
There was a problem hiding this comment.
From my investigation with copilot, this test fails on the current head: the grammar of this PR no longer accepts the 0x prefix, so NewBdevHotplugRange("0x01:0x00-0xFF") returns parse identifier "0x01", expected plain hex notation and the test stops at its first t.Fatal. The Jenkins Unit Test stage of the head fails on exactly this test.
| hr, err := NewBdevHotplugRange("0x01:0x00-0xFF") | |
| hr, err := NewBdevHotplugRange("01:00-FF") |
There was a problem hiding this comment.
Minor, non-blocking: from copilot, a few statements of the design document and of the admin guide do not seem to match the branch (each checked by copilot against the current head):
- Section 5 and the PR description say the manual syntax is documented in
src/control/server/storage/README.md, but that file is not part of the PR and does not exist in the repository, so this document is currently the only place describingbdev_hotplug_range. Should the README be added, or the references removed? - Section 7 says
daos_server.ymlgains abdev_hotplug_rangeparameter, which contradicts section 5 and the diff (the diff only removes thebdev_busid_rangelines fromdaos_server.yml). - Smaller inaccuracies: section 4.1 names
setHotplugRange()(the function issetHotplugRanges); section 4.4 callsspdk_json_decode_arrayan existing pattern ofbio_config.c(this PR adds its only use, indecode_daos_array); section 8 lists overlapping-range validation and C-side tests that I could not find in the PR; section 6 says the file is regenerated "on every engine start" (it is regenerated when the old file cannot be parsed, or at format). - The admin guide (
docs/admin/administration.md) says the filter is "precise to exactly the devices the engine was formatted with" and "always succeeds"; this does not hold for engines with several bdev tiers (see my comment onprovider.go) nor beyond 64 entries (HOTPLUG_FILTER_MAX_ENTRIESinbio_config.c). - The legacy
bdev_busid_rangestill works as an alias of domain0000but is no longer documented indaos_server.ymlor the admin guide, and its use is only logged at DEBUG. Would a one-line "deprecated, applies to domain 0000 only" note indaos_server.yml(and perhaps a NOTICE in the log) help people who still have it in their configuration?
kjacque
left a comment
There was a problem hiding this comment.
Thanks for the format updates. I think the issues Cedric found are valid and should be addressed.
| if strings.Contains(parts[0], "-") { | ||
| return nil, errors.Errorf( | ||
| "invalid hotplug range domain %q in %q, only a single domain is supported "+ | ||
| "per entry", parts[0], entryStr) | ||
| } |
There was a problem hiding this comment.
This would be detected as simply a bad string format when the domain value is parsed, right? I don't think it needs to be called out specifically.
| ranges, err := deriveHotplugRangesFromBdevList(tier.Bdev.DeviceList) | ||
| if err != nil { | ||
| return errors.Wrapf(err, "get busid range limits") | ||
| return errors.Wrap(err, "derive hotplug filter ranges from bdev_list") | ||
| } | ||
| req.HotplugRanges = ranges |
There was a problem hiding this comment.
I think Cedric's comment is right, this is only getting the hotplug range for a single tier and overriding the range list. I think it would be fine to append them instead, since the caller is looping over the tiers.
Features: control Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
| log.Debug("auto-deriving hotplug filter ranges from bdev_list of all bdev tiers") | ||
| ranges, err := deriveHotplugRangesFromBdevList(bdevCfgs.NVMeBdevs()) | ||
| if err != nil { |
There was a problem hiding this comment.
From my investigation with copilot, your fix introduced a regression with emulated dev tiers and copilot proposed the following fix which makes sense to me:
| log.Debug("auto-deriving hotplug filter ranges from bdev_list of all bdev tiers") | |
| ranges, err := deriveHotplugRangesFromBdevList(bdevCfgs.NVMeBdevs()) | |
| if err != nil { | |
| if !bdevCfgs.HaveRealNVMe() && bdevCfgs.HaveEmulatedNVMe() { | |
| // Only emulated bdevs (class file or kdev): there is no PCI address to derive a filter from. | |
| log.Debug("emulated bdevs only: no hotplug filter ranges configured") | |
| req.HotplugRanges = nil | |
| return nil | |
| } | |
| log.Debug("auto-deriving hotplug filter ranges from bdev_list of all bdev tiers") | |
| ranges, err := deriveHotplugRangesFromBdevList(bdevCfgs.NVMeBdevs()) | |
| if err != nil { |
There was a problem hiding this comment.
thank you, resolved
| tier.Bdev.BusidRange.IsZero()) { | ||
| continue | ||
| } | ||
| if manualTier != nil { |
There was a problem hiding this comment.
NIT, it could be more user friendly to have this check in TierConfigs.Validate() to inform the user as soon as possible that a manual bdev_hotplug_range (or the legacy bdev_busid_range) is tolerated on one bdev tier only per engine.
Features: control Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
|
Test stage Functional on EL 9 completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19259/20/execution/node/1463/log |
|
@tanabarr Requested to land and will fix clang-format in a separate PR. |
why? can we please just fix it here |
mjmac
left a comment
There was a problem hiding this comment.
Approving because I think this is a much better approach now and I have limited review bandwidth for the next week or two. It does seem like the BdevHotplugRange implementation could be cleaned up to match the C struct, though, unless I'm missing something.
Also, it seems like parts of the design document were written from the perspective of how the design was changed from the first approach instead of what it changes from master. That's not really useful context to include in the final result, IMO.
| type BdevHotplugRange struct { | ||
| LowAddress hardware.PCIAddress | ||
| HighAddress hardware.PCIAddress | ||
| } |
There was a problem hiding this comment.
Out of curiosity, why use two PCIAddress members instead of something like this, which also matches the C struct:
type BdevHotplugRange struct {
Domain uint16
BusBegin uint8
BusEnd uint8
}I'm all for type reuse when it makes sense, but the current type has unused fields and the possibility of accidentally setting different domains on the low/high addresses.
There was a problem hiding this comment.
thank you . I will follow up on your review comments after landing
Sure I will push formatting fix, hopefully we can land on Monday without having to get reviews again given it's just clang formatting that will be fixed and we already have three reviews? @daltonbohning does that sound okay? |
Signed-off-by: Tom Nabarro <thomas.nabarro@hpe.com>
bdev_busid_range assumed PCI domain 0x0000 and only encoded an 8-bit
bus-ID range. On multi-PCI-segment platforms with non-zero domains,
this silently filtered the wrong bus-IDs (DAOS-19772: a hot-plugged
drive was claimed by the wrong engine).
Add bdev_hotplug_range, a config array of PCI domain + bus-ID-range
entries (one domain per entry; plain hex, no "0x" prefix, matching
ordinary PCI address formatting), replacing the legacy domain-0x00-
only bdev_busid_range (kept for backward compatibility). When unset,
ranges are now auto-derived directly from bdev_list's actual PCI
addresses instead of NUMA-node topology, collapsing only truly-
contiguous bus-IDs so the filter never admits an address absent from
bdev_list; VMD still allows all. Thread the resulting ranges through
to the SPDK JSON config and bio_config.c's hotplug_filter_fn, which
now matches domain+bus-ID per entry instead of a single bus-ID range.
Update daos_server.yml/admin guide to describe only the automatic
behavior; manual syntax is retained only in the design doc and
src/control/server/storage/README.md as an undocumented, experimental
escape hatch. Decimal notation is no longer accepted, hex only.
Add design/control/hotplug-pci-domain-design.md.
Features: control
Steps for the author:
After all prior steps are complete: