summaryrefslogtreecommitdiffstats
path: root/shell
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-01 15:00:47 +0200
committersalmonik <salmonik@tuta.io>2026-08-01 15:00:47 +0200
commitd562e9df2bc5e69bba7298a9439e2adca5c18faf (patch)
tree8d763e60d512e7a4230413f13caaf9153cb2ec54 /shell
parentklog: [ssss.mmm] millisecond timestamps from the PIT (diff)
downloadrs-dos-d562e9df2bc5e69bba7298a9439e2adca5c18faf.tar.gz
rs-dos-d562e9df2bc5e69bba7298a9439e2adca5c18faf.zip
rsnix: runtime device detection — rescan for hotplugged/removed disks
Phase 1: make the boot discovery pipeline re-runnable and diff it against live hardware state. - ahci: store ABAR/NP/port bitmap; poll_dirty() (cheap PxSSTS.DET check per port) and rescan() which starts newly-present ports and tombstones the slots of removed ones. Slots never shift, so disk indices stay valid. select() now rejects tombstoned slots. - fat: Volume gets a mounted flag; rescan() unmounts volumes whose disk left and mounts every disk without a mounted volume (re-trying failed boot mounts). UID dedup ignores tombstones so a re-plugged disk keeps its /disk/<UID> name. - fs: init's mount loop factored into rescan_disks(), which lazily creates /disk, ensures a mount node per mounted volume and tombstones nodes of unmounted ones. - shell: 'rescan' command + automatic deep rescan before each prompt when ahci::poll_dirty() sees a port-presence change. Rescan events flow through serial_println so they land in klog too. Removal (PxSSTS) is a real-hardware path: QEMU q35 rejects disk hotplug on the ich9-ahci IDE buses, and PCIe device_del is a guest-cooperative protocol this kernel does not implement.
Diffstat (limited to 'shell')
-rw-r--r--shell/src/lib.rs35
1 files changed, 35 insertions, 0 deletions
diff --git a/shell/src/lib.rs b/shell/src/lib.rs
index ddd8688..28eb737 100644
--- a/shell/src/lib.rs
+++ b/shell/src/lib.rs
@@ -45,6 +45,12 @@ pub fn run() -> ! {
45 // Push any deferred scrolls so the prompt renders on a current 45 // Push any deferred scrolls so the prompt renders on a current
46 // framebuffer (e.g. after a streaming command's batch of output). 46 // framebuffer (e.g. after a streaming command's batch of output).
47 rsnix::vt::sync_scroll(); 47 rsnix::vt::sync_scroll();
48 // Cheap hotplug probe: if any AHCI port's device presence changed
49 // since the last scan, re-run discovery (mounts new volumes,
50 // unmounts gone ones) before showing the prompt.
51 if rsnix::ahci::poll_dirty() {
52 report_rescan(rescan_all());
53 }
48 // Print prompt 54 // Print prompt
49 term_print("> "); 55 term_print("> ");
50 56
@@ -681,6 +687,7 @@ write `{} <path> TIL <marker>`",
681 "stress" => cmd_stress(&parsed), 687 "stress" => cmd_stress(&parsed),
682 "date" => cmd_date(&parsed), 688 "date" => cmd_date(&parsed),
683 "pci" => cmd_pci(&parsed), 689 "pci" => cmd_pci(&parsed),
690 "rescan" => cmd_rescan(&parsed),
684 "ls" => cmd_ls(&parsed), 691 "ls" => cmd_ls(&parsed),
685 "cat" => cmd_cat(&parsed), 692 "cat" => cmd_cat(&parsed),
686 "klog" => cmd_klog(&parsed), 693 "klog" => cmd_klog(&parsed),
@@ -710,6 +717,7 @@ fn cmd_help(_p: &Parsed) {
710 stress — stress-test heap/page allocators 717 stress — stress-test heap/page allocators
711 date — show current date/time (RTC) 718 date — show current date/time (RTC)
712 pci — list PCI devices 719 pci — list PCI devices
720 rescan — re-scan for hotplugged/removed disks (also runs automatically)
713 ls — list a directory 721 ls — list a directory
714 cat — print files (cat USE a TO b copies a→b; cat TIL END is a heredoc) 722 cat — print files (cat USE a TO b copies a→b; cat TIL END is a heredoc)
715 klog — kernel boot log (cat /dev/klog; WRITING <dst> persists it) 723 klog — kernel boot log (cat /dev/klog; WRITING <dst> persists it)
@@ -1527,6 +1535,33 @@ fn cmd_date(p: &Parsed) {
1527 pipe.end(); 1535 pipe.end();
1528} 1536}
1529 1537
1538/// Deep device re-scan: AHCI ports → FAT volumes → VFS mount table.
1539/// Returns (disks added, disks removed, vols mounted, vols unmounted,
1540/// nodes added, nodes removed) so callers can report the result.
1541fn rescan_all() -> (usize, usize, usize, usize, usize, usize) {
1542 let (da, dr) = rsnix::ahci::rescan();
1543 let (ma, mu) = rsnix::fat::rescan();
1544 let (na, nr) = rsnix::fs::rescan_disks();
1545 (da, dr, ma, mu, na, nr)
1546}
1547
1548/// Print the one-line change summary; returns true if anything changed.
1549fn report_rescan((da, dr, ma, mu, na, nr): (usize, usize, usize, usize, usize, usize)) -> bool {
1550 term_println(&alloc::format!(
1551 "rescan: {} disk(s) added, {} removed · {} volume(s) mounted, {} unmounted · {} node(s) added, {} removed",
1552 da, dr, ma, mu, na, nr
1553 ));
1554 da + dr + ma + mu + na + nr > 0
1555}
1556
1557fn cmd_rescan(_p: &Parsed) {
1558 if report_rescan(rescan_all()) {
1559 term_println("rescan done — /disk updated");
1560 } else {
1561 term_println("rescan done — nothing changed");
1562 }
1563}
1564
1530fn cmd_pci(p: &Parsed) { 1565fn cmd_pci(p: &Parsed) {
1531 let devices = rsnix::pci::probe(); 1566 let devices = rsnix::pci::probe();
1532 let mut pipe = Pipeline::new(&p.filters, &p.output); 1567 let mut pipe = Pipeline::new(&p.filters, &p.output);