-
Notifications
You must be signed in to change notification settings - Fork 48
Integrate github.com/docker/docker/pkg/system Sequential utilities #121
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
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
f7411d2
Windows: mkdirall volume path aware
20a92d0
Windows: Fix use of IsAbs check
1798aa0
Windows: create daemon root with ACL
82d88ed
Windows: Use sequential file access
a419ce5
skip api/types/container/ (like golint) and fix one pkg
vieux aafb08f
Windows: Use sequential file access
b291614
LCOW: Create layer folders with correct ACL
b6bc917
[project] change syscall to /x/sys/unix|windows
tophj-ibm 28c30ad
Merge pull request #33399 from tophj-ibm/move-all-of-pkg-to-syscall
estesp c24df86
Remove redundant build-tags
thaJeztah b425d2a
Merge pull request #35823 from thaJeztah/remove-dead-code
yongtang 3511ac8
Add canonical import comment
dnephin 875002f
LCOW: Add SIDs to layer.vhd at creation
12d814f
Allow system.MkDirAll() to be used as drop-in for os.MkDirAll()
thaJeztah 64d5004
Use newer x/sys/windows SecurityAttributes struct
zx2c4 845ff9d
pkg/system: normalize comment formatting
thaJeztah 88b47d5
pkg/system: simplify IsAbs()
thaJeztah de65c12
Update to Go 1.17.0, and gofmt with Go 1.17
thaJeztah 8b36fc0
refactor: move from io/ioutil to io and os package
Juneezee 313aacd
Integrate github.com/docker/docker/pkg/system Sequential utilities
thaJeztah 172bbe5
sequential: initialize module, and remove unrelated functions
thaJeztah a88a500
sequential: rename funcs to match their "os" equivalent
thaJeztah File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // Package sequential provides a set of functions for managing sequential | ||
| // files on Windows. | ||
| // | ||
| // The origin of these functions are the golang OS and windows packages, | ||
| // slightly modified to only cope with files, not directories due to the | ||
| // specific use case. | ||
| // | ||
| // The alteration is to allow a file on Windows to be opened with | ||
| // FILE_FLAG_SEQUENTIAL_SCAN (particular for docker load), to avoid eating | ||
| // the standby list, particularly when accessing large files such as layer.tar. | ||
| // | ||
| // For non-Windows platforms, the package provides wrappers for the equivalents | ||
| // in the os packages. They are passthrough on Unix platforms, and only relevant | ||
| // on Windows. | ||
| package sequential | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| module github.com/moby/sys/sequential | ||
|
|
||
| go 1.17 | ||
|
|
||
| require golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= | ||
| golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| //go:build !windows | ||
| // +build !windows | ||
|
|
||
| package sequential | ||
|
|
||
| import "os" | ||
|
|
||
| // Create creates the named file with mode 0666 (before umask), truncating | ||
| // it if it already exists. If successful, methods on the returned | ||
| // File can be used for I/O; the associated file descriptor has mode | ||
| // O_RDWR. | ||
| // If there is an error, it will be of type *PathError. | ||
| func Create(name string) (*os.File, error) { | ||
| return os.Create(name) | ||
| } | ||
|
|
||
| // Open opens the named file for reading. If successful, methods on | ||
| // the returned file can be used for reading; the associated file | ||
| // descriptor has mode O_RDONLY. | ||
| // If there is an error, it will be of type *PathError. | ||
| func Open(name string) (*os.File, error) { | ||
| return os.Open(name) | ||
| } | ||
|
|
||
| // OpenFile is the generalized open call; most users will use Open | ||
| // or Create instead. It opens the named file with specified flag | ||
| // (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, | ||
| // methods on the returned File can be used for I/O. | ||
| // If there is an error, it will be of type *PathError. | ||
| func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { | ||
| return os.OpenFile(name, flag, perm) | ||
| } | ||
|
|
||
| // CreateTemp creates a new temporary file in the directory dir | ||
| // with a name beginning with prefix, opens the file for reading | ||
| // and writing, and returns the resulting *os.File. | ||
| // If dir is the empty string, TempFile uses the default directory | ||
| // for temporary files (see os.TempDir). | ||
| // Multiple programs calling TempFile simultaneously | ||
| // will not choose the same file. The caller can use f.Name() | ||
| // to find the pathname of the file. It is the caller's responsibility | ||
| // to remove the file when no longer needed. | ||
| func CreateTemp(dir, prefix string) (f *os.File, err error) { | ||
| return os.CreateTemp(dir, prefix) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| package sequential | ||
|
|
||
| import ( | ||
| "os" | ||
| "path/filepath" | ||
| "strconv" | ||
| "sync" | ||
| "syscall" | ||
| "time" | ||
| "unsafe" | ||
|
|
||
| "golang.org/x/sys/windows" | ||
| ) | ||
|
|
||
| // Create creates the named file with mode 0666 (before umask), truncating | ||
| // it if it already exists. If successful, methods on the returned | ||
| // File can be used for I/O; the associated file descriptor has mode | ||
| // O_RDWR. | ||
| // If there is an error, it will be of type *PathError. | ||
| func Create(name string) (*os.File, error) { | ||
| return OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0) | ||
| } | ||
|
|
||
| // Open opens the named file for reading. If successful, methods on | ||
| // the returned file can be used for reading; the associated file | ||
| // descriptor has mode O_RDONLY. | ||
| // If there is an error, it will be of type *PathError. | ||
| func Open(name string) (*os.File, error) { | ||
| return OpenFile(name, os.O_RDONLY, 0) | ||
| } | ||
|
|
||
| // OpenFile is the generalized open call; most users will use Open | ||
| // or Create instead. | ||
| // If there is an error, it will be of type *PathError. | ||
| func OpenFile(name string, flag int, _ os.FileMode) (*os.File, error) { | ||
| if name == "" { | ||
| return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT} | ||
| } | ||
| r, err := openFileSequential(name, flag, 0) | ||
| if err == nil { | ||
| return r, nil | ||
| } | ||
| return nil, &os.PathError{Op: "open", Path: name, Err: err} | ||
| } | ||
|
|
||
| func openFileSequential(name string, flag int, _ os.FileMode) (file *os.File, err error) { | ||
| r, e := openSequential(name, flag|windows.O_CLOEXEC, 0) | ||
| if e != nil { | ||
| return nil, e | ||
| } | ||
| return os.NewFile(uintptr(r), name), nil | ||
| } | ||
|
|
||
| func makeInheritSa() *windows.SecurityAttributes { | ||
| var sa windows.SecurityAttributes | ||
| sa.Length = uint32(unsafe.Sizeof(sa)) | ||
| sa.InheritHandle = 1 | ||
| return &sa | ||
| } | ||
|
|
||
| func openSequential(path string, mode int, _ uint32) (fd windows.Handle, err error) { | ||
| if len(path) == 0 { | ||
| return windows.InvalidHandle, windows.ERROR_FILE_NOT_FOUND | ||
| } | ||
| pathp, err := windows.UTF16PtrFromString(path) | ||
| if err != nil { | ||
| return windows.InvalidHandle, err | ||
| } | ||
| var access uint32 | ||
| switch mode & (windows.O_RDONLY | windows.O_WRONLY | windows.O_RDWR) { | ||
| case windows.O_RDONLY: | ||
| access = windows.GENERIC_READ | ||
| case windows.O_WRONLY: | ||
| access = windows.GENERIC_WRITE | ||
| case windows.O_RDWR: | ||
| access = windows.GENERIC_READ | windows.GENERIC_WRITE | ||
| } | ||
| if mode&windows.O_CREAT != 0 { | ||
| access |= windows.GENERIC_WRITE | ||
| } | ||
| if mode&windows.O_APPEND != 0 { | ||
| access &^= windows.GENERIC_WRITE | ||
| access |= windows.FILE_APPEND_DATA | ||
| } | ||
| sharemode := uint32(windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE) | ||
| var sa *windows.SecurityAttributes | ||
| if mode&windows.O_CLOEXEC == 0 { | ||
| sa = makeInheritSa() | ||
| } | ||
| var createmode uint32 | ||
| switch { | ||
| case mode&(windows.O_CREAT|windows.O_EXCL) == (windows.O_CREAT | windows.O_EXCL): | ||
| createmode = windows.CREATE_NEW | ||
| case mode&(windows.O_CREAT|windows.O_TRUNC) == (windows.O_CREAT | windows.O_TRUNC): | ||
| createmode = windows.CREATE_ALWAYS | ||
| case mode&windows.O_CREAT == windows.O_CREAT: | ||
| createmode = windows.OPEN_ALWAYS | ||
| case mode&windows.O_TRUNC == windows.O_TRUNC: | ||
| createmode = windows.TRUNCATE_EXISTING | ||
| default: | ||
| createmode = windows.OPEN_EXISTING | ||
| } | ||
| // Use FILE_FLAG_SEQUENTIAL_SCAN rather than FILE_ATTRIBUTE_NORMAL as implemented in golang. | ||
| // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx | ||
| const fileFlagSequentialScan = 0x08000000 // FILE_FLAG_SEQUENTIAL_SCAN | ||
| h, e := windows.CreateFile(pathp, access, sharemode, sa, createmode, fileFlagSequentialScan, 0) | ||
| return h, e | ||
| } | ||
|
|
||
| // Helpers for CreateTemp | ||
| var rand uint32 | ||
| var randmu sync.Mutex | ||
|
|
||
| func reseed() uint32 { | ||
| return uint32(time.Now().UnixNano() + int64(os.Getpid())) | ||
| } | ||
|
|
||
| func nextSuffix() string { | ||
| randmu.Lock() | ||
| r := rand | ||
| if r == 0 { | ||
| r = reseed() | ||
| } | ||
| r = r*1664525 + 1013904223 // constants from Numerical Recipes | ||
| rand = r | ||
| randmu.Unlock() | ||
| return strconv.Itoa(int(1e9 + r%1e9))[1:] | ||
| } | ||
|
|
||
| // CreateTemp is a copy of os.CreateTemp, modified to use sequential | ||
| // file access. Below is the original comment from golang: | ||
| // TempFile creates a new temporary file in the directory dir | ||
| // with a name beginning with prefix, opens the file for reading | ||
| // and writing, and returns the resulting *os.File. | ||
| // If dir is the empty string, TempFile uses the default directory | ||
| // for temporary files (see os.TempDir). | ||
| // Multiple programs calling TempFile simultaneously | ||
| // will not choose the same file. The caller can use f.Name() | ||
| // to find the pathname of the file. It is the caller's responsibility | ||
| // to remove the file when no longer needed. | ||
| func CreateTemp(dir, prefix string) (f *os.File, err error) { | ||
| if dir == "" { | ||
| dir = os.TempDir() | ||
| } | ||
|
|
||
| nconflict := 0 | ||
| for i := 0; i < 10000; i++ { | ||
| name := filepath.Join(dir, prefix+nextSuffix()) | ||
| f, err = OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600) | ||
| if os.IsExist(err) { | ||
| if nconflict++; nconflict > 10 { | ||
| randmu.Lock() | ||
| rand = reseed() | ||
| randmu.Unlock() | ||
| } | ||
| continue | ||
| } | ||
| break | ||
| } | ||
| return | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not new in this PR, but probably we have to replicate the original copyright header
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good point; perhaps extract the bits that were copied to a separate file (I'd have to check how much was copied; I think that's only in the
CreateTemp, which uses similar /same logic asos.CreateTemp)We can look at that in a follow up in deed 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW; was also discussing with @crazy-max to see to what extend we still need that function; it may be that some parts were needed for "pre go1.9" code, which didn't work well with Windows, but some of those reasons may no longer be there, so possibly we can start to remove some of this.
I think it's still useful to first do the migration, and go from there though (proposing to tag it as
v0.5, so that any deprecation that would happen could be done beforev1.0.0).