Skip to content

fix(storage): look at the device before erasing or unmounting it - #29

Merged
inkly merged 1 commit into
mainfrom
fix/format-guard
Nov 10, 2026
Merged

inkly merged 1 commit into
mainfrom
fix/format-guard

Conversation

@inkly

@inkly inkly commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

The dashboard offers only the disks that are free, but its list may be old. With this change the routes that erase or unmount look at the device themselves, just before they do anything to it.

  • Adding a storage with a format (POST /v1/storage) takes a whole disk that holds nothing in use: no mounted filesystem, no member of an array, a volume group, a pool or an encrypted volume. Without the format nothing is erased, and the disk's filesystem is mounted as before.
  • Formatting a storage (PUT /v1/storage) takes a storage: a device mounted where this box mounts one (/media, or /mnt for older installs). It may be a partition, an array or a logical volume. A storage the merged storage is made of must be taken out of it first.
  • Removing a storage (DELETE /v1/storage, DELETE /v1/disks/umount) unmounts only what is mounted under /media or /mnt, on the device or below it.
  • A path that is not a block device known to lsblk answers 400. A device in use answers 409, with the reason. In both cases nothing has been unmounted or erased.
  • Message bus. PublishEvent returns when the bus does not answer, in place of reading a response that is not there. The check at start-up uses it too.
  • Ejecting a USB drive. UmountUSB runs local-storage-helper.sh through bash, with the mount point as one argument; the helper quotes it. The error it returns carries what udevil said.

Tests. route/v1/storage_erase_test.go describes the disks of a box (system disk, array member, volume group, open encrypted volume, storages on a partition, an array and a logical volume, a blank disk) and checks, route by route, what is refused with nothing done and what goes on. service/publish_test.go covers a bus that does not answer, service/disk_umount_usb_test.go what the helper receives. go vet ./... and go test ./... pass in a golang:1.26 container. No real disk was formatted or ejected.

The dashboard offers only the disks that are free, but its list may be
old. The routes that erase or unmount now look at the device themselves,
before anything is done to it.

- EraseRefusal: a new storage is made of a whole disk that holds nothing
  in use; a storage formatted again is mounted where this box mounts one,
  and is not a part of the merged storage.
- UnmountRefusal: removing a storage unmounts only what is mounted under
  /media or /mnt.
- A path that is not a block device is a 400, a device in use a 409.
- PublishEvent: when the message bus does not answer there is no
  response to read; the event is logged as lost and the service goes on.
- UmountUSB runs the helper through bash with the mount point as one
  argument, and returns what udevil said.
@inkly
inkly marked this pull request as ready for review November 10, 2026 22:56
@inkly
inkly merged commit 1831432 into main Nov 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant