acpid: allow PCI fd replacement; eagerly init AML symbols on sendfd
Closes the v4.0 plan P3 'acpid pci_fd is not registered' item.
Two related defects:
1. scheme.rs::on_sendfd had a one-shot EINVAL when self.pci_fd was
already Some. Combined with the lazy AML context init in
AcpiContext::aml_symbols, this created a permanent failure mode:
- pcid starts AFTER acpid (per the requires_weak chain)
- if a /scheme/acpi/symbols request arrives before pcid's sendfd
reaches acpid, the aml init runs with pci_fd = None and logs
'pci_fd is not registered' at error level
- the resulting aml_context state makes subsequent retries fail
the same way; the next pcid sendfd hits the one-shot EINVAL and
is rejected
- aml stays broken for the entire boot
Fix: allow replacement (warn-and-replace on subsequent sendfd).
Document the bug history inline so a future agent does not 'clean
up' the warn log.
2. aml_physmem.rs::AmlPhysMemHandler::new logged the missing fd at
log::error. Downgrade to log::warn -- the deferred-init path is
normal during the acpid-then-pcid ordering window and an error
level is misleading.
3. scheme.rs::on_sendfd now eagerly calls self.ctx.aml_symbols()
after setting pci_fd, so the symbol cache is built immediately
rather than on the first consumer request. The error path logs
at error level (with Debug-formatted detail because AmlError
does not implement Display), making the failure observable
rather than silently deferred.
Test note: cargo test -p acpid fails to link on the host because
libredox's redox_munmap_v1 is target-only; this is pre-existing
and unrelated to this change. cargo check -p acpid is clean.
This commit is contained in:
@@ -178,7 +178,9 @@ impl AmlPhysMemHandler {
|
||||
let pci_fd = if let Some(pci_fd) = pci_fd_opt {
|
||||
Some(libredox::Fd::new(pci_fd.raw()))
|
||||
} else {
|
||||
log::error!("pci_fd is not registered");
|
||||
log::warn!(
|
||||
"acpid: AmlPhysMemHandler created without PCI fd; AML init will retry once pcid sends it via scheme:acpid sendfd"
|
||||
);
|
||||
None
|
||||
};
|
||||
Self {
|
||||
|
||||
@@ -1070,10 +1070,27 @@ impl SchemeSync for AcpiScheme<'_, '_> {
|
||||
}
|
||||
let new_fd = libredox::Fd::new(new_fd);
|
||||
|
||||
// Allow replacement: pcid may resend the fd after a restart,
|
||||
// and the previous one-shot EINVAL left aml init permanently
|
||||
// broken if the first sendfd raced with an early aml request.
|
||||
if self.pci_fd.is_some() {
|
||||
return Err(Error::new(EINVAL));
|
||||
} else {
|
||||
self.pci_fd = Some(new_fd);
|
||||
log::warn!(
|
||||
"acpid: replacing previously-registered PCI fd; AML symbol cache will rebuild on next request"
|
||||
);
|
||||
}
|
||||
self.pci_fd = Some(new_fd);
|
||||
|
||||
// Kick aml symbol init now that pci_fd is registered. The
|
||||
// next aml request will either find a working cache or get a
|
||||
// fresh error log here; either way the failure mode is
|
||||
// observable rather than silently deferred to "the next
|
||||
// caller retries".
|
||||
match self.ctx.aml_symbols(self.pci_fd.as_ref()) {
|
||||
Ok(_) => log::info!("acpid: AML symbols initialized on PCI fd registration"),
|
||||
Err(err) => {
|
||||
log::error!("acpid: AML symbol init failed after PCI fd registration");
|
||||
log::error!("acpid: AML error detail: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(num_fds)
|
||||
|
||||
Reference in New Issue
Block a user