Re: Hardlink support feasible?
Greg Troxel <[email protected]> Sat, 17 Jan 2026 10:16:59 -0500
| Newsgroups | gmane.network.unison.general |
|---|---|
| Message-ID | <[email protected]> |
Alan Savage <[email protected]> writes: > Thanks for getting back to me quickly. > >> it may be instructive to understand rsync's edge cases. > > Agreed. `rsync -H` only preserves source hard links, not destination hard > links, so it is not symmetrical. If the destination does not support > hard-links the files are silently duplicated. If you then reverse source > and destination, the hard links are destroyed. > > The `rsync -H` implementation builds an in-memory hard-link table keyed by > (device, inode). I think we'd want something similar, but that's getting > into implementation. > > For a second pass, I'd try and preserve any asymmetry. E.g. if on Side A 2 > files are hardlinked and on Side B they are not, then we keep them that > way. If one of the files on Side B is touched then the question would be > whether to Beware that I am not thinking deeply, so take this with grain of salt design thought (not as well thought out unison doctrine): Probably we need to think about NFS and CIFS mounts. NFS supports hardlinks (I just made one, NetBSD 9 client, NetBSD 10 server). CIFS almost certainly does not (but I avoid it, so idk). First define hardlink-capable as 1) OS supports hardlinks 2) fs that contains the replica supports hardlinks and 2) version of unison running on both sides advertise hardlink support. There's also a crazy edge case of a replica with a mount inside it. If neither side is hardlink-capable, we are where we are now. Perhaps there is a user-facing pref to disable or enable hardlinks. Maybe we start off with it opt in and later flip to opt out. Perhaps we can avoid that. If both sides are hardlink-capable, then I would see AhB (hardlinked) and AcB (separate files) as a conflict. The point is to replicate the same state. I am leery of just changing AcB to AhB and vice versa because while the bits are the same on read, writing has different semantics. If one side is hardlink-capable and the other isn't, then I can see newly appearing AhB on the capable side leading to AcB on the non-capable side, with AcB on the non-capable side leading to AcB on the capable side. And, AhB(capable) and AcB(non-capable) counting as not a difference. Perhaps we have a mechanism to coalesce AcB into AhB, when requested, and perhaps this has nothing to do with unison and it's just a utility we point to (or is written for this), to help people get from here to unison-hardlinks. This is beyond user spec, but we have archive files that describe the local state to detect changes. Those will likely have to change. I have always wanted a tool to dump archive files to nerd-readable; it would be cool to have unison-archive2json and unison-json2archive and similarly for fingerprint (or the tool works on pairs). >> if hardlinks are specified by POSIX and if real implementations follow >> POSIX > POSIX specifies hardlink behavior for `linkat`, `unlinkat` and the > `fstatat` calls, so we can rely on the POSIX where it's available. I'm not > sure about Windows. > > Some of the relevant rsync code seems to rely on the POSIX API: sounds good. >> what happens on filesystems without this facility > > What happens right now? I would start with preserving that behavior or > leaving a big caveat that the behavior is undefined and logging a warning > with future updates having better conflict handling. What do you think? I would really like to avoid documenting UB. People sync from POSIX to windows all the time. (I don't have any experience doing that.) > In general, I would think we can treat POSIX errors the same way we > currently treat file creation/editing/deletion errors, but I'd have to dig > in to see if that's really sufficient. I think that's a good starting position. Unison generally takes the position that system calls are supposed to work reliably and that errors are errors. We don't have a "then back off and try plan B" mentality. >> The second hard part is extending the sync protocol to represent >> hardlinks and decomposing the rules for what happens into rules for the >> two sides. > > How can we proceed with this? Is there a good example to follow? Probably not but you can start reading the sources. I really have no idea how hard that part is. There is an extension mechanism for the two sides to know what the other is capable of. The idea would be that each side says "I support the hardlink feature" and then the describe-replica protocol is somehow changed/extended to say that the 2..N files that are links in the fs are links to the original file, instead of inlining the size/checksum. The other thing you could do, in parallel, is to prepare a (marked draft please) PR to update the documentation to describe your proposed hardlink syncing rules. We'd need that, but writing that first would let people think about whether the details are right, and if it's complete. This would take the place of a specification in software engineering terms (not that we have rules like that; it's just how I think). I'm pretty sure you're aware, but I want to caution you that this is a fairly big project, and I'd estimate closer to 100 hours than 10 or 1000 of work time. I dare not estimate to more than integer log10 values :-) To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].