diff options
author | Aditya R <arajan@redhat.com> | 2022-06-03 13:18:44 +0530 |
---|---|---|
committer | Aditya R <arajan@redhat.com> | 2022-06-06 18:58:42 +0530 |
commit | aadae49ad3b00e0545e525213bcb00edddfae4c1 (patch) | |
tree | a9aaface501bd8206db1622dc09252360655e37a /libpod | |
parent | 48a4e6d69019390cc40cbb13b0a83456159d10b6 (diff) | |
download | podman-aadae49ad3b00e0545e525213bcb00edddfae4c1.tar.gz podman-aadae49ad3b00e0545e525213bcb00edddfae4c1.tar.bz2 podman-aadae49ad3b00e0545e525213bcb00edddfae4c1.zip |
overlay-volumes: add support for non-volatile upperdir,workdir for anonymous volumes
Similar feature was added for named overlay volumes here: https://github.com/containers/podman/pull/12712
Following PR just mimics similar feature for anonymous volumes.
Often users want their anonymous overlayed volumes to be `non-volatile` in nature
that means that same `upper` dir can be re-used by one or more
containers but overall of nature of volumes still have to be overlay
so work done is still on a overlay not on the actual volume.
Following PR adds support for more advanced options i.e custom `workdir`
and `upperdir` for overlayed volumes. So that users can re-use `workdir`
and `upperdir` across new containers as well.
Usage
```console
podman run -it -v /some/path:/data:O,upperdir=/path/persistant/upper,workdir=/path/persistant/work alpine sh
```
Signed-off-by: Aditya R <arajan@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal_linux.go | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index e19d75deb..0056b8e86 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -388,6 +388,37 @@ func lookupHostUser(name string) (*runcuser.ExecUser, error) { return &execUser, nil } +// Internal only function which returns upper and work dir from +// overlay options. +func getOverlayUpperAndWorkDir(options []string) (string, string, error) { + upperDir := "" + workDir := "" + for _, o := range options { + if strings.HasPrefix(o, "upperdir") { + splitOpt := strings.SplitN(o, "=", 2) + if len(splitOpt) > 1 { + upperDir = splitOpt[1] + if upperDir == "" { + return "", "", errors.New("cannot accept empty value for upperdir") + } + } + } + if strings.HasPrefix(o, "workdir") { + splitOpt := strings.SplitN(o, "=", 2) + if len(splitOpt) > 1 { + workDir = splitOpt[1] + if workDir == "" { + return "", "", errors.New("cannot accept empty value for workdir") + } + } + } + } + if (upperDir != "" && workDir == "") || (upperDir == "" && workDir != "") { + return "", "", errors.New("must specify both upperdir and workdir") + } + return upperDir, workDir, nil +} + // Generate spec for a container // Accepts a map of the container's dependencies func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { @@ -460,23 +491,9 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { for _, o := range namedVol.Options { if o == "O" { overlayFlag = true - } - if overlayFlag && strings.Contains(o, "upperdir") { - splitOpt := strings.SplitN(o, "=", 2) - if len(splitOpt) > 1 { - upperDir = splitOpt[1] - if upperDir == "" { - return nil, errors.New("cannot accept empty value for upperdir") - } - } - } - if overlayFlag && strings.Contains(o, "workdir") { - splitOpt := strings.SplitN(o, "=", 2) - if len(splitOpt) > 1 { - workDir = splitOpt[1] - if workDir == "" { - return nil, errors.New("cannot accept empty value for workdir") - } + upperDir, workDir, err = getOverlayUpperAndWorkDir(namedVol.Options) + if err != nil { + return nil, err } } } @@ -489,10 +506,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { return nil, err } - if (upperDir != "" && workDir == "") || (upperDir == "" && workDir != "") { - return nil, errors.Wrapf(err, "must specify both upperdir and workdir") - } - overlayOpts = &overlay.Options{RootUID: c.RootUID(), RootGID: c.RootGID(), UpperDirOptionFragment: upperDir, @@ -585,11 +598,22 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // Add overlay volumes for _, overlayVol := range c.config.OverlayVolumes { + upperDir, workDir, err := getOverlayUpperAndWorkDir(overlayVol.Options) + if err != nil { + return nil, err + } contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID()) if err != nil { return nil, err } - overlayMount, err := overlay.Mount(contentDir, overlayVol.Source, overlayVol.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions()) + overlayOpts := &overlay.Options{RootUID: c.RootUID(), + RootGID: c.RootGID(), + UpperDirOptionFragment: upperDir, + WorkDirOptionFragment: workDir, + GraphOpts: c.runtime.store.GraphOptions(), + } + + overlayMount, err := overlay.MountWithOptions(contentDir, overlayVol.Source, overlayVol.Dest, overlayOpts) if err != nil { return nil, errors.Wrapf(err, "mounting overlay failed %q", overlayVol.Source) } |