Compare commits
6 Commits
a5f16dfa81
...
adf62d4483
Author | SHA1 | Date |
---|---|---|
Daniel Barlow | adf62d4483 | |
Daniel Barlow | 68eb1360f6 | |
Daniel Barlow | 19ad6cd278 | |
Daniel Barlow | 00076c7b81 | |
Daniel Barlow | 721e7499f3 | |
Daniel Barlow | fc723b9a35 |
151
THOUGHTS.txt
151
THOUGHTS.txt
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -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)}";
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue