mountpoint_cmp: flatten mountpoint= parameter before sorting#18207
mountpoint_cmp: flatten mountpoint= parameter before sorting#18207robn wants to merge 2 commits intoopenzfs:masterfrom
mountpoint_cmp: flatten mountpoint= parameter before sorting#18207Conversation
This test constructs a mount tree that deliberately cannot be mounted correctly if the mountpoints are sorted "naturally", requiring the sorter to understand the effect of "runs" of slashes in path names. Sponsored-by: TrueNAS Signed-off-by: Rob Norris <rob.norris@truenas.com>
mountpoint_cmp: flatten mountpoint= parameter before sorting
Datasets with nested mountpoints must be mounted in order from shallowest to deepest, otherwise the deeper ones will be obscured by the shallow ones. mountpoint_cmp() has only traditionally been a character-based sort, with no awareness of "legal" patterns in pathnames, in particular, runs of '/' characters. These are (for better or worse) legal paths, but confuse a character-based comparison, causing mounts to be attempted in an incorrect order, with mixed results. This commit adds a path "flattening" function, and applies it to the string returned from the mountpoint= paramater before using it as a path. This corrects the sort order and allows mounting to proceed correctly. Reported-by: James McKay <portablejim@jamesmckay.id.au> Sponsored-by: TrueNAS Signed-off-by: Rob Norris <rob.norris@truenas.com>
64e4635 to
5ed72a7
Compare
amotin
left a comment
There was a problem hiding this comment.
To me the main questions here are whether we should be more strict on allowed mountpoint values, and whether we should clean the value before storing it. mountpoint_namecheck() is really relaxed on it.
| gota = (zfs_get_type(za) == ZFS_TYPE_FILESYSTEM); | ||
| if (gota) { | ||
| verify(zfs_prop_get(za, ZFS_PROP_MOUNTPOINT, mounta, | ||
| sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); | ||
| VERIFY0(zfs_flatten_path(mounta, sizeof (mounta), NULL)); | ||
| } | ||
| gotb = (zfs_get_type(zb) == ZFS_TYPE_FILESYSTEM); | ||
| if (gotb) { | ||
| verify(zfs_prop_get(zb, ZFS_PROP_MOUNTPOINT, mountb, | ||
| sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); | ||
| VERIFY0(zfs_flatten_path(mountb, sizeof (mountb), NULL)); | ||
| } |
There was a problem hiding this comment.
That's quite a comparison function for sorting.
There was a problem hiding this comment.
Yeah, fortunately its not particularly time-sensitive. I could maybe do something to cache the flattened form though, if you think its worth it?
Yeah, I don't know either. If we define (and enforce) On the other other hand, after #18205 I'm already thinking about what it would mean for I don't think there's any hurry in deciding this though, certainly not if we have to commit to an on-disk meaning change. |
[Sponsors: TrueNAS]
Motivation and Context
A user showed me a curious situation where after a reboot his datasets did not mount correctly, so some of his applications would start with apparently-empty data directories. He'd worked around it by stopping services, unmount everything, mounting datasets in two distinct sets, then starting up. "That's awful and I am so sorry" I said, and we stared for a long time into the screen before finally noticing that the root dataset of the affected tree had a trailing slash on the
mountpoint=parameter. With the little bit of soul that didn't leave my body, I promised I would fix it because that behaviour is miserably unfair.@portablejim thank you for your patience :)
Description
Datasets with nested mountpoints must be mounted in order from shallowest to deepest, otherwise the deeper ones will be obscured by the shallow ones.
mountpoint_cmp()has only traditionally been a character-based sort, with no awareness of "legal" patterns in pathnames, in particular, runs of '/' characters. These are (for better or worse) legal paths, but confuse a character-based comparison, causing mounts to be attempted in an incorrect order, with mixed results.This commit adds a path "flattening" function, and applies it to the string returned from the
mountpoint=paramater before using it as a path. This corrects the sort order and allows mounting to proceed correctly.I did originally think about requiring
mountpoint=to be stored in some sort of "flattened" or (lets say) "canonical" form, so it would have been down a layer in the property getter/setter (the getter would be necessary for existing pools). I eventually decided against this for a few reasons:mountpoint=, and I don't want to mess with them/cc @lundman on that last one. I don't know what you currently do on
mountpoint=for Windows but I tried to structure this so it could be moved out of your way without too much fuss. It seems to me thatzfs_flatten_path()could easily a platform-specific function, and be renamed aszfs_convert_mountpoint_os()or something like that. I'm not looking to do that here (yet), I'm mostly just curious to make sure I'm not getting in your way, and/or if you have a better approach to this kind of thing already.How Has This Been Tested?
New test added, that fails on both Linux and FreeBSD before the change, and succeeds afterwards. The test method is finicky, but the test has a lot of commentary.
I've not had chance to do a full ZTS run, so I'll will let CI take a look at it. I would be surprised if it broke an existing test other than an outright bug.
Types of changes
Checklist:
Signed-off-by.