Skip empty directories on prior graphdriver detection - #35528
Conversation
When starting the daemon, the `/var/lib/docker` directory
is scanned for existing directories, so that the previously
selected graphdriver will automatically be used.
In some situations, empty directories are present (those
directories can be created during feature detection of
graph-drivers), in which case the daemon refuses to start.
This patch improves detection, and skips empty directories,
so that leftover directories don't cause the daemon to
fail.
Before this change:
$ mkdir /var/lib/docker /var/lib/docker/aufs /var/lib/docker/overlay2
$ dockerd
...
Error starting daemon: error initializing graphdriver: /var/lib/docker contains several valid graphdrivers: overlay2, aufs; Please cleanup or explicitly choose storage driver (-s <DRIVER>)
With this patch applied:
$ mkdir /var/lib/docker /var/lib/docker/aufs /var/lib/docker/overlay2
$ dockerd
...
INFO[2017-11-16T17:26:43.207739140Z] Docker daemon commit=ab90bc296 graphdriver(s)=overlay2 version=dev
INFO[2017-11-16T17:26:43.208033095Z] Daemon has completed initialization
And on restart (prior graphdriver is still picked up):
$ dockerd
...
INFO[2017-11-16T17:27:52.260361465Z] [graphdriver] using prior storage driver: overlay2
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
3246064 to
1262c57
Compare
|
ping @kolyshkin @dnephin PTAL |
| return true | ||
| } | ||
| return false | ||
| } |
There was a problem hiding this comment.
info, err := ioutil.ReadDir(name)
return err == nil && len(info) == 0?
There was a problem hiding this comment.
ioutil.ReadDir(name) would do a stat on all files/directories inside name? While this is only on daemon start, I can imagine it could be an issue if a lot of directories are present inside (having #31462 in mind)
| if _, err = f.Readdirnames(1); err == io.EOF { | ||
| return true | ||
| } | ||
| return false |
There was a problem hiding this comment.
nit: could be
_, err = f.Readdirnames(1)
return err == io.EOFThere was a problem hiding this comment.
Thanks for reviewing: I had this initially, but thought it would be more difficult to "grasp", so changed to a simple if
|
While reviewing this, I have an alternative idea, let me tell it, maybe it makes sense. Something like this: for driver := range drivers {
 p := filepath.Join(root, driver)
+ unix.Rmdir(p) // remove if directory is empty. ignore any errors
 if _, err := os.Stat(p); err == nil && driver != "vfs" {This way has two benefits:
We can actually make it even simple by removing the |
|
Here are the possible errors from
v2: updated with EBUSY So, ultimately, we should use |
|
Heh, I like the creative approach. The rm proposal would make sense in a "hot" path perhaps, but I'm not sure we should delete directories in a detection loop 😅 |
Why not? Those are empty directories that were (most probably) created by dockerd itself are within a directory tree that is owned and controlled by dockerd. The only case I see we should not remove a directory like this is when such a directory is to be used as a mount point, but for some reason it is not mounted. If we remove it, the subsequent mount will fail. From the other case, if dockerd is started but such directory is not mounted it is an error.
|
vieux
left a comment
There was a problem hiding this comment.
not a big fan of (most probably) I prefer @thaJeztah approach
LGTM
When starting the daemon, the
/var/lib/dockerdirectory is scanned for existing directories, so that the previously selected graphdriver will automatically be used.In some situations, empty directories are present (those directories can be created during feature detection of graph-drivers), in which case the daemon refuses to start.
This patch improves detection, and skips empty directories, so that leftover directories don't cause the daemon to fail.
Before this change:
With this patch applied:
And on restart (prior graphdriver is still picked up):