Add --force to podman umount to force the unmounting of the rootfs

podman umount will currently only unmount file system if not other
process is using it, otherwise the umount decrements the container
storage to indicate that the caller is no longer using the mount
point, once the count gets to 0, the file system is actually unmounted.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1184
Approved by: TomSweeneyRedHat
This commit is contained in:
Daniel J Walsh
2018-07-30 09:04:18 -04:00
committed by Atomic Bot
parent a8ae7eae9c
commit 8e1ef558eb
6 changed files with 54 additions and 11 deletions

View File

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/storage"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/projectatomic/libpod/cmd/podman/libpodruntime" "github.com/projectatomic/libpod/cmd/podman/libpodruntime"
"github.com/projectatomic/libpod/libpod" "github.com/projectatomic/libpod/libpod"
@ -16,13 +17,24 @@ var (
Name: "all, a", Name: "all, a",
Usage: "umount all of the currently mounted containers", 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{ umountCommand = cli.Command{
Name: "umount", Name: "umount",
Aliases: []string{"unmount"}, Aliases: []string{"unmount"},
Usage: "Unmounts working container's root filesystem", Usage: "Unmounts working container's root filesystem",
Description: "Unmounts working container's root filesystem", Description: description,
Flags: umountFlags, Flags: umountFlags,
Action: umountCmd, Action: umountCmd,
ArgsUsage: "CONTAINER-NAME-OR-ID", ArgsUsage: "CONTAINER-NAME-OR-ID",
@ -36,6 +48,7 @@ func umountCmd(c *cli.Context) error {
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
force := c.Bool("force")
umountAll := c.Bool("all") umountAll := c.Bool("all")
args := c.Args() args := c.Args()
if len(args) == 0 && !umountAll { if len(args) == 0 && !umountAll {
@ -58,7 +71,7 @@ func umountCmd(c *cli.Context) error {
continue continue
} }
if err = ctr.Unmount(); err != nil { if err = ctr.Unmount(force); err != nil {
if lastError != nil { if lastError != nil {
logrus.Error(lastError) logrus.Error(lastError)
} }
@ -78,7 +91,10 @@ func umountCmd(c *cli.Context) error {
continue 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 { if lastError != nil {
logrus.Error(lastError) logrus.Error(lastError)
} }

View File

@ -1358,6 +1358,8 @@ _podman_umount() {
local boolean_options=" local boolean_options="
--all --all
-a -a
--force
-f
--help --help
-h -h
" "

View File

@ -7,13 +7,28 @@ podman\-umount - Unmount the specified working containers' root file system.
**podman umount** *container* ... **podman umount** *container* ...
## DESCRIPTION ## 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 ## OPTIONS
**--all, -a** **--all, -a**
All of the currently mounted containers will be unmounted. 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 ## EXAMPLE
podman umount containerID podman umount containerID

View File

@ -441,7 +441,7 @@ func (c *Container) Mount() (string, error) {
} }
// Unmount unmounts a container's filesystem on the host // Unmount unmounts a container's filesystem on the host
func (c *Container) Unmount() error { func (c *Container) Unmount(force bool) error {
if !c.batched { if !c.batched {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() 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 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 // Pause pauses a container

View File

@ -839,7 +839,7 @@ func (c *Container) cleanupStorage() error {
return nil 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 // If the container has already been removed, warn but don't
// error // error
// We still want to be able to kick the container out of the // 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 // unmount unmounts the container's root filesystem
func (c *Container) unmount() error { func (c *Container) unmount(force bool) error {
// Also unmount storage // 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()) return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID())
} }

View File

@ -231,7 +231,7 @@ func (r *storageService) MountContainerImage(idOrName string) (string, error) {
return mountPoint, nil return mountPoint, nil
} }
func (r *storageService) UnmountContainerImage(idOrName string) (bool, error) { func (r *storageService) UnmountContainerImage(idOrName string, force bool) (bool, error) {
if idOrName == "" { if idOrName == "" {
return false, ErrEmptyID return false, ErrEmptyID
} }
@ -239,7 +239,17 @@ func (r *storageService) UnmountContainerImage(idOrName string) (bool, error) {
if err != nil { if err != nil {
return false, err 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 { if err != nil {
logrus.Debugf("failed to unmount container %q: %v", container.ID, err) logrus.Debugf("failed to unmount container %q: %v", container.ID, err)
return false, err return false, err