diff options
-rw-r--r-- | cmd/podman/umount.go | 22 | ||||
-rw-r--r-- | completions/bash/podman | 2 | ||||
-rw-r--r-- | docs/podman-umount.1.md | 17 | ||||
-rw-r--r-- | libpod/container_api.go | 4 | ||||
-rw-r--r-- | libpod/container_internal.go | 6 | ||||
-rw-r--r-- | libpod/storage.go | 14 |
6 files changed, 54 insertions, 11 deletions
diff --git a/cmd/podman/umount.go b/cmd/podman/umount.go index 1a2cf22c6..1e364b48f 100644 --- a/cmd/podman/umount.go +++ b/cmd/podman/umount.go @@ -3,6 +3,7 @@ package main import ( "fmt" + "github.com/containers/storage" "github.com/pkg/errors" "github.com/projectatomic/libpod/cmd/podman/libpodruntime" "github.com/projectatomic/libpod/libpod" @@ -16,13 +17,24 @@ var ( Name: "all, a", Usage: "umount all of the currently mounted containers", }, + cli.BoolFlag{ + Name: "force, f", + Usage: "force the complete umount all of the currently mounted containers", + }, } + description = ` +Container storage increments a mount counter each time a container is mounted. +When a container is unmounted, the mount counter is decremented and the +container's root filesystem is physically unmounted only when the mount +counter reaches zero indicating no other processes are using the mount. +An unmount can be forced with the --force flag. +` umountCommand = cli.Command{ Name: "umount", Aliases: []string{"unmount"}, Usage: "Unmounts working container's root filesystem", - Description: "Unmounts working container's root filesystem", + Description: description, Flags: umountFlags, Action: umountCmd, ArgsUsage: "CONTAINER-NAME-OR-ID", @@ -36,6 +48,7 @@ func umountCmd(c *cli.Context) error { } defer runtime.Shutdown(false) + force := c.Bool("force") umountAll := c.Bool("all") args := c.Args() if len(args) == 0 && !umountAll { @@ -58,7 +71,7 @@ func umountCmd(c *cli.Context) error { continue } - if err = ctr.Unmount(); err != nil { + if err = ctr.Unmount(force); err != nil { if lastError != nil { logrus.Error(lastError) } @@ -78,7 +91,10 @@ func umountCmd(c *cli.Context) error { continue } - if err = ctr.Unmount(); err != nil { + if err = ctr.Unmount(force); err != nil { + if umountAll && errors.Cause(err) == storage.ErrLayerNotMounted { + continue + } if lastError != nil { logrus.Error(lastError) } diff --git a/completions/bash/podman b/completions/bash/podman index 2c43a2d8f..563597f0b 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1358,6 +1358,8 @@ _podman_umount() { local boolean_options=" --all -a + --force + -f --help -h " diff --git a/docs/podman-umount.1.md b/docs/podman-umount.1.md index c13781dbf..70f30869a 100644 --- a/docs/podman-umount.1.md +++ b/docs/podman-umount.1.md @@ -7,13 +7,28 @@ podman\-umount - Unmount the specified working containers' root file system. **podman umount** *container* ... ## DESCRIPTION -Unmounts the specified containers' root file system. +Unmounts the specified containers' root file system, if no other processes +are using it. + +Container storage increments a mount counter each time a container is mounted. +When a container is unmounted, the mount counter is decremented and the +container's root filesystem is physically unmounted only when the mount +counter reaches zero indicating no other processes are using the mount. +An unmount can be forced with the --force flag. ## OPTIONS **--all, -a** All of the currently mounted containers will be unmounted. +**--force, -f** + +Force the unmounting of specified containers' root file system, even if other +processes have mounted it. + +Note: This could cause other processes that are using the file system to fail, +as the mount point could be removed without their knowledge. + ## EXAMPLE podman umount containerID diff --git a/libpod/container_api.go b/libpod/container_api.go index b5104048e..73fd96960 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -441,7 +441,7 @@ func (c *Container) Mount() (string, error) { } // Unmount unmounts a container's filesystem on the host -func (c *Container) Unmount() error { +func (c *Container) Unmount(force bool) error { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -469,7 +469,7 @@ func (c *Container) Unmount() error { return errors.Wrapf(err, "can't unmount %s last mount, it is still in use", c.ID()) } } - return c.unmount() + return c.unmount(force) } // Pause pauses a container diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 66d1e44ad..7b5932541 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -839,7 +839,7 @@ func (c *Container) cleanupStorage() error { return nil } - if err := c.unmount(); err != nil { + if err := c.unmount(false); err != nil { // If the container has already been removed, warn but don't // error // We still want to be able to kick the container out of the @@ -1338,9 +1338,9 @@ func (c *Container) mount() (string, error) { } // unmount unmounts the container's root filesystem -func (c *Container) unmount() error { +func (c *Container) unmount(force bool) error { // Also unmount storage - if _, err := c.runtime.storageService.UnmountContainerImage(c.ID()); err != nil { + if _, err := c.runtime.storageService.UnmountContainerImage(c.ID(), force); err != nil { return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID()) } diff --git a/libpod/storage.go b/libpod/storage.go index 9c5fc858e..10827f13e 100644 --- a/libpod/storage.go +++ b/libpod/storage.go @@ -231,7 +231,7 @@ func (r *storageService) MountContainerImage(idOrName string) (string, error) { return mountPoint, nil } -func (r *storageService) UnmountContainerImage(idOrName string) (bool, error) { +func (r *storageService) UnmountContainerImage(idOrName string, force bool) (bool, error) { if idOrName == "" { return false, ErrEmptyID } @@ -239,7 +239,17 @@ func (r *storageService) UnmountContainerImage(idOrName string) (bool, error) { if err != nil { return false, err } - mounted, err := r.store.Unmount(container.ID, false) + + if !force { + mounted, err := r.store.Mounted(container.ID) + if err != nil { + return false, err + } + if mounted == 0 { + return false, storage.ErrLayerNotMounted + } + } + mounted, err := r.store.Unmount(container.ID, force) if err != nil { logrus.Debugf("failed to unmount container %q: %v", container.ID, err) return false, err |