I was struck by the same issue. Splitting /home into parts for easier snapshot management turned into a weeks long nightmare. cp --reflinkreflink=always did not work for some reason (threw way too many errors at me I got lost in them).
The answer I've found at last was simple and so obvious, I'm ashamed I did not think of it before.
- Snapshot the original subvolume.
- Inside a snapshot, delete everything you don't need, and move the data you need to the root of the snapshot. Mostly it will be directories. It's fast and cheap.
- Make sure ACL on the snapshot root is what you expect.
- Mount your new subvolume where you want it.
If you've attempted to move across volumes before, but being a good system administrator, made a snapshot before that "just in case", there's a simple script to cleanup erroneous subvolume:
# cd /your/erroneous/subvolume
# find . -type f -exec cmp --silent '{}' '/your/good/snapshot/{}' \; -delete
This will remove from your erred subvolume any files that are same as those on your reserve snapshot. Do not attempt to rsync "the rest" back into snapshot. There could be partially copied files and you will lose data. Manually inspect the residue and only copy what you actually need.
And here's the answer to cp --reflink=always and "Invalid cross-device link" errors: this doesn't mean FS is at fault, it's just how the kernel map from extent to filename work, if you specify mounted subvolumes as targets. Mount your root FS, go into that directory and work from there with relative paths. All will be good.