-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should the default pathDriver walk though volume mount points on Windows? #174
Comments
Per the comment on
I guess the fourth and fifth options are considered the consuming project's problem, so when I get around to looking into this, I'll probably go with the third option, and implement a custom Walk for Windows that is identical to |
I think 4. is a sensible approach. An implementation of Do we care about regular symlinks, or are volumes enough to consider? Do you by any chance have time to rebase the two PRs? I would like to have a stab at this and it would be great if I could easily try out our branches with the changes. |
Something like this maybe? https://go.dev/play/p/R-OKyD5IGBR The result of which: PS C:\Users\Administrator\work\walk> go run .\main.go
visiting C:\var
visiting C:\var\a-link
visiting C:\var\a-mnt
2022/09/21 10:45:50 Skipping hidden system file/folder: C:\var\a-mnt\$RECYCLE.BIN
2022/09/21 10:45:50 Skipping hidden system file/folder: C:\var\a-mnt\System Volume Information
visiting C:\var\a-mnt\sasa.txt
visiting C:\var\a-mnt\test2
2022/09/21 10:45:50 Skipping hidden system file/folder: C:\var\a-mnt\test2\$RECYCLE.BIN
2022/09/21 10:45:50 Skipping hidden system file/folder: C:\var\a-mnt\test2\System Volume Information
visiting C:\var\a-mnt\test2\gdfg.rtf
2022/09/21 10:45:50 >> C:\var\a-mnt\test2\test-recurse points to a volume we've already visited: \??\Volume{bae7ecae-0000-0000-0000-100000000000}\
visiting C:\var\a-mnt\test2\test-recurse
visiting C:\var\a.txt
visiting C:\var\aa
visiting C:\var\aa\bb
visiting C:\var\lib
visiting C:\var\lib\cni
visiting C:\var\lib\cni\results
visiting C:\var\source
visiting C:\var\target
visiting C:\var\test.txt
PS C:\Users\Administrator\work\walk> |
Sorry, I won't have time to do the rebasing for at least the next week, I believe. The output and a skim of the playground link looks like it's doing pretty-much what I was thinking, a copy of I wouldn't skip system/hidden folders though, that seems surprising in this use-case. The thing I wonder about is if the second sight of the same volume should call I also wonder if it's possible for Linux to produce a recursive directory tree with bind-mounts? There's no protection against that if it's possible. Would it be better (for this use-case) if instead of rejecting volume mounts we've seen before, to reject volume mounts which lead back to volumes in the current path, so that we walk, e.g.,
such that we see the same thing under both b and c, i.e. the contents of That'd be more work though, as we'd have to know the volume of the starting point and track potentially a stack of volumes for the current path. Off-hand, the current use-cases we have for this aren't going to see volume mount points except for the initial directory anyway, so it may not be worth putting too much effort into. Oh, and I say we shouldn't see through regular symlinks. Then the behaviour is consistent on Linux and Windows, and the |
This was just a quick scratchpad implementation. I skipped system files because even as administrator, doing a Lstat on I'll write up a propper PR for this and we can move the discussion there. I can test it with your current branch. Shouldn't matter much. I don't think there have been any changes that would change the outcome/expectations in any way. |
Seems on linux bind mount don't recurse. Same with Also, the |
Makes sense. I like |
Created a PR here: #208 |
This change adds a fork of the filepath.Walk function from the standard library, with changes that allows it to visit reparse points that are in fact volume mounts. Currently go makes no distinction between a symlink, directory junction, volume mount or Unix domain socket. All reparse points are regarded as symlinks. This means that FileMode does not have ModeDir set for any path that also has ModeSymlink. This includes volume mounts. See: https://go-review.googlesource.com/c/go/+/41830/ This implementation also attempts to avoid recursions. Fixes: containerd#174 Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This change adds a fork of the filepath.Walk function from the standard library, with changes that allows it to visit reparse points that are in fact volume mounts. Currently go makes no distinction between a symlink, directory junction, volume mount or Unix domain socket. All reparse points are regarded as symlinks. This means that FileMode does not have ModeDir set for any path that also has ModeSymlink. This includes volume mounts. See: https://go-review.googlesource.com/c/go/+/41830/ This implementation also attempts to avoid recursions. Fixes: containerd#174 Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This change adds a fork of the filepath.Walk function from the standard library, with changes that allows it to visit reparse points that are in fact volume mounts. Currently go makes no distinction between a symlink, directory junction, volume mount or Unix domain socket. All reparse points are regarded as symlinks. This means that FileMode does not have ModeDir set for any path that also has ModeSymlink. This includes volume mounts. See: https://go-review.googlesource.com/c/go/+/41830/ This implementation also attempts to avoid recursions. Fixes: containerd#174 Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This change adds a fork of the filepath.Walk function from the standard library, with changes that allows it to visit reparse points that are in fact volume mounts. Currently go makes no distinction between a symlink, directory junction, volume mount or Unix domain socket. All reparse points are regarded as symlinks. This means that FileMode does not have ModeDir set for any path that also has ModeSymlink. This includes volume mounts. See: https://go-review.googlesource.com/c/go/+/41830/ This implementation also attempts to avoid recursions. Fixes: containerd#174 Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This change adds a fork of the filepath.Walk function from the standard library, with changes that allows it to visit reparse points that are in fact volume mounts. Currently go makes no distinction between a symlink, directory junction, volume mount or Unix domain socket. All reparse points are regarded as symlinks. This means that FileMode does not have ModeDir set for any path that also has ModeSymlink. This includes volume mounts. See: https://go-review.googlesource.com/c/go/+/41830/ This implementation also attempts to avoid recursions. Fixes: containerd#174 Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This change adds a fork of the filepath.Walk function from the standard library, with changes that allows it to visit reparse points that are in fact volume mounts. Currently go makes no distinction between a symlink, directory junction, volume mount or Unix domain socket. All reparse points are regarded as symlinks. This means that FileMode does not have ModeDir set for any path that also has ModeSymlink. This includes volume mounts. See: https://go-review.googlesource.com/c/go/+/41830/ This implementation also attempts to avoid recursions. Fixes: containerd#174 Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Per golang/go#26033 (comment) it seems that as-of Go 1.21, on Windows if a path ends in a path-seperator, Walk (and LStat) will now follow the symlink first. This was already the Go behaviour on POSIX systems (as specified by the POSIX spec). So I'll close this since both the original use-case has been removed, and because if any callers are in this situation, they are probably already passing in paths ending in a path separator to avoid being bitting by this problem on POSIX. Also reference to #232 which may ensure that such paths always end in path separators, removing the need for callers to be aware of this. |
For the record as of Go 1.23, mount points will be identified as ModeIrregular, not ModeSymlink. I don't think we'll be affected as we aren't using mount-points any more in the code that prompted this ticket, but if anyone hits the same issue in similar circumstances, then the end of golang/go#63703 will be relevant reading. |
While implementing WCOW for the containerd snapshotter (containerd/containerd#4419), I bounced off golang/go#26033 in calls to
fstest.CheckDirectoryEqualWithApplier
and had to work around it rather nastily.The summary of the issue is that
filepath.Walk
does not walk through Volume Mount Points (i.e. how a WCOW Layer is mounted to the local filesystem), because Go see it as a symlink, rather than a mount-point (bind, overlay, etc) as you would see on Unix systems for the same behaviour.There are four approaches I can see to fixing this:
PathDriver
in containerd's test helpers, which overridesWalk
, and either directly recognises volume mounts, or points to a newly-overriddenStat
in aDriver
, with the latter reporting a volume mount point as a directory, not a symlink.pathDriver
in continuity hasWalk
changed to always callDriver.Lstat
, and containerd's test framework can provide a modifiedDriver.Lstat
.This ticket is to ask whether that fourth or fifth options seems reasonable, before I come to creating PRs towards improving this situation; or take option 2 and just work around it.
The text was updated successfully, but these errors were encountered: