Skip to content

Don't log EINVAL when unmount IPC#33329

Merged
vdemeester merged 1 commit intomoby:masterfrom
wenjianhn:EINVAL
May 31, 2017
Merged

Don't log EINVAL when unmount IPC#33329
vdemeester merged 1 commit intomoby:masterfrom
wenjianhn:EINVAL

Conversation

@wenjianhn
Copy link
Contributor

EINVAL means that the target exists but it is not (yet) a mount point.
See umount2(2).

On freebsd, following errors also lead to EINVAL.

  1. The file system ID specified using MNT_BYFSID could not be decoded.
  2. the specified file system is the root file system.
    We don't need to handle them in UnmountIpcMounts.

Fix #33328

Signed-off-by: Jacob Wen [email protected]

- What I did

- How I did it

- How to verify it

- Description for the changelog

- A picture of a cute animal (not mandatory but encouraged)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about something like:

if err := unmount(shmPath); err != nil && !os.IsNotExist(err) {
    mounted, _ := mount.Mounted(shmPath); mounted {
        // append warning
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Linux, EINVAL may mean that umount2() was called with an invalid flag value in flags.
We need to use Mounted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry we may want to go ahead and read this error like

if mounted, mErr := ...; mounted || mErr != nil {
    // append err
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wenjianhn can you address this comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpuguy83 @thaJeztah Done. Thanks.

} else if shmPath != "" {
if err := unmount(shmPath); err != nil && !os.IsNotExist(err) {
warnings = append(warnings, fmt.Sprintf("failed to umount %s: %v", shmPath, err))
if mounted, mErr := mount.Mounted(shmPath); mounted || mErr != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpuguy83 looks like this is now doing the same as mount.Unmount(), only in reverse order (first try syscall.Unmount(), then check if it was mounted - I assume that's a performance optimisation) - should we move that optimisation in mount.Unmount() and use it here?

It looks like the unmount argument for UnmountIpcMounts() is not really needed anymore (it looks like it was was added in 78bd17e to allow different unmount methods in different parts of the code)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really different since we're only checking if it's mounted if the unmount failed, vs only trying to unmount if it is mounted. Checking if it's mounted first is racey... and I wouldn't be surprised if it's technically slower to do it that way.

Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@thaJeztah
Copy link
Member

thaJeztah commented May 31, 2017

Flaky test on experimental? https://jenkins.dockerproject.org/job/Docker-PRs-experimental/34573/console

09:43:09 ----------------------------------------------------------------------
09:43:09 FAIL: docker_cli_stack_test.go:59: DockerSwarmSuite.TestStackDeployComposeFile
09:43:09 
09:43:09 [d35123665fb88] waiting for daemon to start
09:43:09 [d35123665fb88] daemon started
09:43:09 
09:43:09 docker_cli_stack_test.go:76:
09:43:09     c.Assert(err, checker.IsNil)
09:43:09 ... value *exec.ExitError = &exec.ExitError{ProcessState:(*os.ProcessState)(0xc420543b00), Stderr:[]uint8(nil)} ("exit status 1")
09:43:09 
09:43:09 [d35123665fb88] exiting daemon
09:43:11 

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - we can discuss / look into the optimisation separate from this PR

@kolyshkin
Copy link
Contributor

Instead of parsing the whole /proc/self/mountinfo we should just ignore EINVAL (same as pkg/mount's Unmount() does). Will send a PR soon.

@thaJeztah
Copy link
Member

@kolyshkin won't that ignore other reasons for EINVAL? (reading back above; #33329 (comment))

@kolyshkin
Copy link
Contributor

The other reasons for EINVAL (in Linux) are bad value for flags. Since flags are hardcoded to be MNT_DETACH (which is supported since Linux 2.4.11, i.e. forever), there is zero chance it will happen.

@thaJeztah
Copy link
Member

Gotcha, thanks!

@kolyshkin
Copy link
Contributor

There are many other places (in particular, Unmount() implementation in pkg/mount) which do the same. Parsing /proc/self/mountinfo is relatively expensive (more so when you have many containers), so if we are sure we are passing the right flags, it's much better to ignore EINVAL, assuming it only means "not mounted".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WARN[0001] failed to cleanup ipc mounts

6 participants