Expand description
Undoing a migration and deleting the old tree.
What:
Undo a migration (--rollback) and delete the old tree after a finished one (--remove-old), plus the removal of
a subvolume tree that both depend on.
Why:
Rollback carries back what was written to the new root since the exchange (files newer there win), swaps the trees
again, rewrites the restored indexes’ stat fields (the carried-back index describes the new tree’s inodes), and
deletes the new subvolume deepest nested subvolume first, because the kernel refuses to destroy a subvolume that
holds another (ENOTEMPTY). Where the mount does not allow an unprivileged destroy, an emptied subvolume is
removed with rmdir, which the kernel allows for an empty subvolume root. The old tree is an ordinary directory,
so deleting it is a file walk, never a subvolume destroy.
In TS you’d write (pseudocode):
await rollback(run); await removeOldTree(run, { discardUnreadable });Functions§
- remove_
old_ tree - What:
Delete the old tree of a finished migration.
Ok(None)means it ran;Ok(Some(refusals))means nothing was changed. Why: The files this user could not read exist only there, so a non-empty list refuses unless the person discards them explicitly. The deletion (remove_tree) unlinks entries, makes directories the user owns writable on the way, and never follows symbolic links. - remove_
subvolume_ tree - What: Remove a subvolume and every subvolume nested in it, deepest first. Why: See the module description.
- rollback
- What:
The rollback.
Ok(None)means it ran;Ok(Some(refusals))means nothing was changed. Why: Three states can be undone: before the exchange (delete the new subvolume and the lock), after it (carry back, swap again, delete the new subvolume), and in between (finish the bookkeeping, then the second case).