ZFS receive and attributes, proposing some changes. was Re: ZFS full system backup hoses the backup host.
borjam at sarenet.es
Fri Feb 26 11:16:22 UTC 2016
> On 26 Feb 2016, at 05:56, Karli Sjöberg <karli.sjoberg at slu.se> wrote:
> What have other people done to get around this and/or can we either put in
> an "ignore properties" on receive flag or a -R on send that doesn't send
(I removed freebsd-hackers as this discussion belongs in freebsd-fs)
The possibility of replacing options in the receive command would be most useful here. Ideally
it should be done atomically with the receive.
For example: Imagine a replication system. It would be something like this:
- Make the first snapshot
- Send it | receive it with -u (you don’t want it mounted)
- Set the destination dataset’s canmount property to “noauto"
- And, periodically
- Make new snapshot
- Send it incrementally
- etc etc
However, there is a race condition here. If your replication program/script crashes, or it stops for
whatever reason between the first send and the “set canmount” (or you reboot the destination server)
you end up with a time bomb. Despite being received with the -u flag, if you boot it will be mounted
automatically. If you are replicating the root filesystem (or anything mounted on an important system
directory) you are dead :)
To avoid this kind of problems, two options come to my mind, from least desirable/useful/consistent
to better (in my opinion)
1) Have some kind of force-inherit attribute on a dataset which forces children’s mountpoint to go below it.
Example: when replicating server1’s datasets, I send them below to pool/server1_copies. If I set
mountpoint=force_child (or something similar) for pool/server1_copies, anything received under it
would have the mountpoint changed, adding the mountpoint of pool/server1_copies to it.
Imagine I am replicating the /usr filesystem of server1, which is pool_server1/usr, with the
mountpoint /usr. The destination would have the mountpoint /pool/server1_copies/usr.
This at least avoids the unintended mountpoint overwrite problem, which is not bad. And this possibility
can be useful, but it’s not a very clean solution.
2) Adding an option to “zfs receive” so that properties can be changed for the received dataset *atomically*.
The race condition is avoided if I can specify an option to zfs recv, something like -O canmount=noauto.
Actually, there are some changes I would make, not just for this particular case, which will not break
functionality and will make ZFS safer to use and easier to handle, especially when replicating datasets.
1) Enhancing “zfs recv” with the possibility of changing options and holds atomically.
- Changing options: -O option=value -O option=value
- Adding holds: -h holdname
When using snapshots to replicate datasets you must be careful not to delete the last replicated snapshot
accidentally, or you can lose the ability to do an incremental send, forcing a full one. Holds help to prevent this.
And if using them it would be very useful to have the last snapshot properly protected in the destination dataset
as well. Again, it should be done ATOMICALLY.
Same applies to dataset properties, if only for the outright dangerous combination of the canmount/mountpoint
properties. Once more, we want this to be done ATOMICALLY with the zfs recv.
2) Adding the possibility of specifying “default” or “inherit” for the mountpoint property.
When a dataset is created, the default mountpoint is pool/dataset_name unless a different value is specified.
A value of “default” would set the dataset’s mountpoint back to pool/…/dataset_name, and “inherit” could
set the mountpoint to the "parent’s mountpoint”/dataset_name.
These two options can be very useful when using zfs send/zfs recv to keep replicas as a backup, but I think
they can be useful in other situations.
What do you think? In my opinion these additions won’t break functionality and they are worthwhile if only for making
replication safer/more useful.
More information about the freebsd-fs