aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/umount.go22
-rw-r--r--completions/bash/podman2
-rw-r--r--docs/podman-umount.1.md17
-rw-r--r--libpod/container_api.go4
-rw-r--r--libpod/container_internal.go6
-rw-r--r--libpod/storage.go14
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