impermanence icon indicating copy to clipboard operation
impermanence copied to clipboard

Strategies to deal with `renameat(3)` on persisted files

Open Ma27 opened this issue 1 year ago • 1 comments

Suppose you have a configuration like this:

{
  environment.persistence = {
    "/impermanence/safe" = {
      directories = [
        "/etc/wpa_supplicant.conf"
      ];
  };
}

Now, wpa_supplicant appears to do a rename when writing changes to the config which is state I'd like to keep. A similar issue also exists for ~/.local/share/recently-used.xbel or .gdbinit.

This doesn't work if only the file is persisted (i.e. bind-mounted) since a rename fails with EBUSY in that case.

There are two kinds of workarounds:

  • use symlinks (with #146): works for a few applications, e.g. gdb. But GTK (for recently-used.xbel) and wpa_supplicant replace the symlink with a file then.
  • patch around in the NixOS module to use another config file. For wpa_supplicant that was my fix (https://github.com/Ma27/nixpkgs/commit/d90b3eb6f49104b02b02c8296230f6f9d8c11761, note: I use allowAuxiliaryImperativeNetworks). Now I can persist /etc/wpa_supplicant[1] and the move inside works fine. This however is not feasible for recently-used.xbel which seems to be backed into GTK and would cause an excessive amount of rebuilds for me (and I don't really want to use libredirect for ~everything on my desktop).

What I'm wondering is, is there any feasible, generic way that doesn't require us to find solutions per-application? If so, we may want to consider adding those as another alternative into impermanence.

[1] https://docs.gtk.org/gtk4/property.Settings.gtk-recent-files-enabled.html

Ma27 avatar Mar 27 '24 17:03 Ma27

This isn't optimal, but I think it would work in this situation. If using btrfs subvolumes, on boot (or at least before a lot of services start), you could copy the file into your /persist location, and then copy that over to the actual location.

For example, if this is your persist:

/persist/recently-used.xbel (mtime 4/02)

Then on boot:

/last_boot/home/.../recently-used.xbel (mtime 4/03) -> /persist/recently-used.xbel
/persist/recently-used.xbel (mtime 4/03) -> /home/.../recently-used.xbel

This has the downside of not being persisted until after boot happens again, but on btrfs this copy could be essentially free with --reflink.

DarkKronicle avatar Apr 03 '24 23:04 DarkKronicle