Compare commits

...

6 Commits

Author SHA1 Message Date
Daniel Barlow adf62d4483 arhcive: make it work when disk is attached before boot
This is a bit of a kludge (a lot of a kludge) but it will
get it running whilt I work on something better
2024-04-17 18:49:30 +01:00
Daniel Barlow 68eb1360f6 use appended dtb in gl-mt300n-v2 tftpboot
probably the A variant needs this as well
2024-04-17 18:48:19 +01:00
Daniel Barlow 19ad6cd278 watchdog: put s6 pkg on $PATH for s6-svstat 2024-04-17 13:01:10 +01:00
Daniel Barlow 00076c7b81 mount service: use uevent-watch 2024-04-17 12:59:13 +01:00
Daniel Barlow 721e7499f3 arhcive: use usb module instead of harcoded kconfig 2024-04-17 12:53:43 +01:00
Daniel Barlow fc723b9a35 think 2024-04-16 18:59:01 +01:00
7 changed files with 204 additions and 71 deletions

View File

@ -4412,3 +4412,154 @@ it can know what to update
Maybe config.filesystem should specify /etc/s6-rc/compiled.new
and something in early boot could symlink /etc/s6-rc/compiled to it
Sat Mar 30 18:41:14 GMT 2024
soft restart doesn't restart services that are invoked by trigger,
because it has to do -p -u default so that it prunes services that
were in the old config but not the new one. Ideally we need somehow
to notify the trigger that it should respawn its service. Maybe
we could add triggers to the force restart list, if there's a way
to detect which they are? don't want to do it by adding files in
the service state directory if there may be oneshot triggers. Can
there be oneshot triggers?
The hashes file is built when we build the service database, so we
could easily(?) add something in there to mark services that
need poking whenever there's a restart. It's not perfect because the
triggered services will be bounced unnecessarily, but remember that
the alternative is a reboot ...
Mon Apr 1 00:18:50 BST 2024
i) I don't know if digressing into remote log shipping is a tangent or
an important part of making services work well.
ii) Should there be a single "machine state" value for all of the
trigger services to reference, or is it better that each trigger
service has its own private state, or (third option) one state
per "state source"? We previously handwaved that a state source
is a service
services.addmember = services.udev.watch {
match = {
SUBSYSTEM = "net";
ID_PATH = "pci-0000:04:00.0";
ATTR.operstate = "up";
};
service = oneshot {
up = "ip link set dev $dev master $(output ${primary} ifname)";
down = "ip link set dev $(output ${member} ifname) nomaster";
};
}
Tue Apr 2 19:55:25 BST 2024
We could do a test script for udev usb disk mounting, which uses the
qemu monitor to add/remove a disk.
./result/run.sh --flag -device --flag usb-ehci,id=xhci --flag -drive --flag if=none,id=usbstick,format=raw,file=./stick.img
(qemu) device_add usb-storage,bus=xhci.0,drive=usbstick
Fri Apr 5 17:11:46 BST 2024
1) write a fennel thing that reads from the udev rebroadcast socket
2) and can check sysfs for state
3) set up mdevd in liminix
Sat Apr 6 13:23:02 BST 2024
I wonder if we could replace preinit with an execline script? One for
the TODO stack
Sun Apr 7 14:03:29 BST 2024
1) we want to know what messages are sent from mdevd under various circumstances
- actually, right now the only relevant circumstances are updown and inout
2) we might get a wider variety of messages from real hardware?
3) if we log the raw messages, pref. with timestamps, then we can
write tests for the parsing
therefore: write a program that opens the netlink socket and logs
all data received
----
what's the minimum we need here? we need the inout test to open a
uevent socket and use uevents to update some state that says whether the
backup drive is plugged in
rather awkwardly, uevents don't have filesystem labels. so we also need
to run blkid to find the label of each partition, and ideally we do this
while the partition is present, not each time we get an event for it.
We have DEVNAME, DEVTYPE, SUBSYSTEM to indicate that a filesystem of interest
may be present, we should use that as a trigger to scan any known
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1
SUBSYSTEM=block
MAJOR=8
MINOR=1
DEVNAME=sda1
DEVTYPE=partition
DISKSEQ=2
PARTN=1
SEQNUM=1528
Some disks on loaclhost and noetbook have PARTNAME field - I assume
this is because they're GPT disks. Would it actually be better to use this
field than grovelling for filesystem label?
Tue Apr 9 21:07:50 BST 2024
Having waited for the appropriately labelled disk to appear, we then
also have to communicate its path to the service that mounts it
- create a symlink
- or use an instanced service
Creating a symlink will be fine if we can pass the symlink name as
a param to fswait
Wed Apr 10 20:53:48 BST 2024
We think that fswait will evolve into a more general
waiting-for-uevents tool. Maybe we could provide the matchers on the
command line:
waituevent -l /dev/volumes/backup-disk -s mount-srv devtype=partition partname=backup-disk
Thu Apr 11 23:09:43 BST 2024
lcommit d3a2e3a4cb80b631df2ab79d463c2c4d1adef37b
commit 4a58cf9335116ce673fcf08f70f3bca921a4c9ad
commit afca6d4b63dd39062f02827b3c29e16904770216
Sun Apr 14 19:50:27 BST 2024
how to get this on to main:
- make uevent-watcher package (it's fswait renamed)
- make mount service use it
- module for mdevd
- add nellie (generalise for other netlink uses w/params pid/family/groups)
Mon Apr 15 19:59:43 BST 2024
plan:
introduce uevent-watcher command, update test to use it
make mount service use it

View File

@ -122,6 +122,7 @@
# 20MB seems to give enough room to uncompress the kernel
# without anything getting trodden on. 10MB was too small
loadAddress = lim.parseInt "0x1400000";
appendDTB = true;
};
kernel = {

View File

@ -28,34 +28,12 @@ in rec {
../modules/network
../modules/vlan
../modules/ssh
../modules/usb.nix
../modules/watchdog
../modules/mount
];
hostname = "arhcive";
kernel = {
config = {
USB = "y";
USB_EHCI_HCD = "y";
USB_EHCI_HCD_PLATFORM = "y";
USB_OHCI_HCD = "y";
USB_OHCI_HCD_PLATFORM = "y";
USB_SUPPORT = "y";
USB_COMMON = "y";
USB_STORAGE = "y";
USB_STORAGE_DEBUG = "n";
USB_UAS = "y";
USB_ANNOUNCE_NEW_DEVICES = "y";
SCSI = "y";
BLK_DEV_SD = "y";
USB_PRINTER = "y";
MSDOS_PARTITION = "y";
EFI_PARTITION = "y";
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
services.dhcpc =
let iface = config.hardware.networkInterfaces.lan;
@ -105,11 +83,21 @@ in rec {
};
services.mount_external_disk = svc.mount.build {
device = "LABEL=backup-disk";
partlabel = "backup-disk";
mountpoint = "/srv";
fstype = "ext4";
};
# until we support retained uevent state, we need to push coldplug
# events to mount_external_disk to account for the case that the
# disk is already plugged at boot time
services.fudge_coldplug = oneshot {
name = "fudge_coldplug";
up = "sleep 5; for i in /sys/class/block/*/uevent; do echo 'change' > $i ;done";
dependencies = [ services.mount_external_disk ];
};
services.rsync =
let
secrets_file = oneshot rec {

View File

@ -19,28 +19,36 @@ in {
type = liminix.lib.types.serviceDefn;
};
};
config.system.service = {
mount = liminix.callService ./service.nix {
device = mkOption {
type = types.str;
example = "/dev/sda1";
};
mountpoint = mkOption {
type = types.str;
example = "/mnt/media";
};
options = mkOption {
type = types.listOf types.str;
default = [];
example = ["noatime" "ro" "sync"];
};
fstype = mkOption {
type = types.str;
default = "auto";
example = "vfat";
};
imports = [ ../mdevd.nix ];
config.system.service.mount =
let svc = liminix.callService ./service.nix {
partlabel = mkOption {
type = types.str;
example = "my-usb-stick";
};
mountpoint = mkOption {
type = types.str;
example = "/mnt/media";
};
options = mkOption {
type = types.listOf types.str;
default = [];
example = ["noatime" "ro" "sync"];
};
fstype = mkOption {
type = types.str;
default = "auto";
example = "vfat";
};
};
in svc // {
build = args:
let args' = args // {
dependencies = (args.dependencies or []) ++ [config.services.mdevd];
};
in svc.build args' ;
};
};
config.programs.busybox = {
applets = ["blkid" "findfs"];
options = {

View File

@ -1,10 +1,12 @@
{
liminix
, uevent-watch
, lib
}:
{ device, mountpoint, options, fstype }:
{ partlabel, mountpoint, options, fstype }:
let
inherit (liminix.services) longrun oneshot;
device = "/dev/disk/by-partlabel/${partlabel}";
options_string =
if options == [] then "" else "-o ${lib.concatStringsSep "," options}";
mount_service = oneshot {
@ -18,14 +20,7 @@ in longrun {
isTrigger = true;
buildInputs = [ mount_service ];
# This accommodates bringing the service up when the device appears.
# It doesn't bring it down on unplug because unmount will probably
# fail anyway (so don't do that)
run = ''
while ! findfs ${device}; do
echo waiting for device ${device}
sleep 1
done
s6-rc -b -u change ${mount_service.name}
${uevent-watch}/bin/uevent-watch -s ${mount_service.name} -n ${device} partname=${partlabel} devtype=partition
'';
}

View File

@ -1,6 +1,7 @@
{
liminix
, lib
, s6
}:
{ watched, headStart } :
let
@ -8,5 +9,5 @@ let
in longrun {
name = "watchdog";
run =
"HEADSTART=${toString headStart} ${./gaspode.sh} ${lib.concatStringsSep " " (builtins.map (s: s.name) watched)}";
"PATH=${s6}/bin:$PATH HEADSTART=${toString headStart} ${./gaspode.sh} ${lib.concatStringsSep " " (builtins.map (s: s.name) watched)}";
}

View File

@ -47,20 +47,9 @@ in rec {
rootfsType = "jffs2";
hostname = "inout";
services.watch_mount_srv =
let
node = "/dev/disk/by-partlabel/backup-disk";
mount = oneshot {
name = "mount-srv";
up = "mount -t ext2 ${node} /srv";
down = "umount /srv";
};
in longrun {
name = "mount_srv";
run = ''
${pkgs.uevent-watch}/bin/uevent-watch -s ${mount.name} -n ${node} partname=backup-disk devtype=partition
'';
dependencies = [ config.services.mdevd ];
buildInputs = [ mount ];
};
services.mount_backup_disk = svc.mount.build {
partlabel = "backup-disk";
mountpoint = "/srv";
fstype = "ext4";
};
}