Skip to content

Commit

Permalink
overlay: support additional image store on vfs
Browse files Browse the repository at this point in the history
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Apr 22, 2024
1 parent d2c5e2a commit ad0dd59
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 25 deletions.
82 changes: 65 additions & 17 deletions drivers/overlay/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/drivers/overlayutils"
"github.com/containers/storage/drivers/quota"
"github.com/containers/storage/drivers/vfs"
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/chrootarchive"
"github.com/containers/storage/pkg/directory"
Expand Down Expand Up @@ -977,7 +978,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
}

func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, readOnly bool) (retErr error) {
dir, homedir, _ := d.dir2(id, readOnly)
dir, homedir, _, _ := d.dir2(id, false)

disableQuota := readOnly

Expand Down Expand Up @@ -1008,8 +1009,14 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, readOnl
return err
}
if parent != "" {
parentBase := d.dir(parent)
st, err := system.Stat(filepath.Join(parentBase, "diff"))
parentBase, _, singleLayer, _ := d.dir2(parent, false)
var d string
if singleLayer {
d = parentBase
} else {
d = filepath.Join(parentBase, "diff")
}
st, err := system.Stat(d)
if err != nil {
return err
}
Expand Down Expand Up @@ -1066,8 +1073,14 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, readOnl
}

if parent != "" {
parentBase := d.dir(parent)
st, err := system.Stat(filepath.Join(parentBase, "diff"))
parentBase, _, singleLayer, _ := d.dir2(parent, false)
var d string
if singleLayer {
d = parentBase
} else {
d = filepath.Join(parentBase, "diff")
}
st, err := system.Stat(d)
if err != nil {
return err
}
Expand Down Expand Up @@ -1142,13 +1155,17 @@ func (d *Driver) parseStorageOpt(storageOpt map[string]string, driver *Driver) e
}

func (d *Driver) getLower(parent string) (string, error) {
parentDir := d.dir(parent)
parentDir, _, singleLayer, _ := d.dir2(parent, false)

// Ensure parent exists
if err := fileutils.Lexists(parentDir); err != nil {
return "", err
}

if singleLayer {
return parent, nil
}

// Read Parent link fileA
parentLink, err := os.ReadFile(path.Join(parentDir, "link"))
if err != nil {
Expand All @@ -1175,7 +1192,7 @@ func (d *Driver) getLower(parent string) (string, error) {
}

func (d *Driver) dir(id string) string {
p, _, _ := d.dir2(id, false)
p, _, _, _ := d.dir2(id, false)
return p
}

Expand All @@ -1187,7 +1204,7 @@ func (d *Driver) getAllImageStores() []string {
return additionalImageStores
}

func (d *Driver) dir2(id string, useImageStore bool) (string, string, bool) {
func (d *Driver) dir2(id string, useImageStore bool) (string, string, bool, bool) {
var homedir string

if useImageStore && d.imageStore != "" {
Expand All @@ -1198,16 +1215,25 @@ func (d *Driver) dir2(id string, useImageStore bool) (string, string, bool) {

newpath := path.Join(homedir, id)

allImageStores := d.getAllImageStores()

if err := fileutils.Exists(newpath); err != nil {
for _, p := range d.getAllImageStores() {
for _, p := range allImageStores {
l := path.Join(p, d.name, id)
err = fileutils.Exists(l)
if err == nil {
return l, homedir, true
return l, homedir, false, true
}
}
for _, p := range allImageStores {
l := path.Join(p, vfs.Name, "dir", id)
err = fileutils.Exists(l)
if err == nil {
return l, homedir, true, true
}
}
}
return newpath, homedir, false
return newpath, homedir, false, false
}

func (d *Driver) getLowerDirs(id string) ([]string, error) {
Expand Down Expand Up @@ -1417,7 +1443,7 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
}

func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountOpts) (_ string, retErr error) {
dir, _, inAdditionalStore := d.dir2(id, false)
dir, _, _, inAdditionalStore := d.dir2(id, false)
if err := fileutils.Exists(dir); err != nil {
return "", err
}
Expand Down Expand Up @@ -1574,10 +1600,11 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
continue
}

allImageStores := d.getAllImageStores()
lower := ""
newpath := path.Join(d.home, l)
if st, err := os.Stat(newpath); err != nil {
for _, p := range d.getAllImageStores() {
for _, p := range allImageStores {
lower = path.Join(p, d.name, l)
if st2, err2 := os.Stat(lower); err2 == nil {
if !permsKnown {
Expand All @@ -1588,6 +1615,20 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
}
lower = ""
}
if lower == "" {
for _, p := range allImageStores {
lower = path.Join(p, vfs.Name, "dir", l)
st2, err2 := os.Stat(lower)
if err2 == nil {
if !permsKnown {
perms = os.FileMode(st2.Mode())
permsKnown = true
}
break
}
lower = ""
}
}
// if it is a "not found" error, that means the symlinks were lost in a sudden reboot
// so call the recreateSymlinks function to go through all the layer dirs and recreate
// the symlinks with the name from their respective "link" files
Expand All @@ -1610,7 +1651,10 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO

linkContent, err := os.Readlink(lower)
if err != nil {
return "", err
if !errors.Is(err, unix.EINVAL) {
return "", err
}
linkContent = lower
}
lowerID := filepath.Base(filepath.Dir(linkContent))
composefsMount, err := maybeAddComposefsMount(lowerID, i+1, readWrite)
Expand Down Expand Up @@ -1835,10 +1879,14 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO

// Put unmounts the mount path created for the give id.
func (d *Driver) Put(id string) error {
dir, _, inAdditionalStore := d.dir2(id, false)
dir, _, singleLayer, inAdditionalStore := d.dir2(id, false)
if err := fileutils.Exists(dir); err != nil {
return err
}
if singleLayer {
return nil
}

mountpoint := path.Join(dir, "merged")
if count := d.ctr.Decrement(mountpoint); count > 0 {
return nil
Expand Down Expand Up @@ -2005,7 +2053,7 @@ func (g *overlayFileGetter) Close() error {
}

func (d *Driver) getStagingDir(id string) string {
_, homedir, _ := d.dir2(id, d.imageStore != "")
_, homedir, _, _ := d.dir2(id, d.imageStore != "")
return filepath.Join(homedir, stagingDir)
}

Expand Down Expand Up @@ -2283,7 +2331,7 @@ func (d *Driver) Changes(id string, idMappings *idtools.IDMappings, parent strin

// AdditionalImageStores returns additional image stores supported by the driver
func (d *Driver) AdditionalImageStores() ([]string, []string) {
return d.options.imageStores, []string{d.name}
return d.options.imageStores, []string{d.name, vfs.Name}
}

// UpdateLayerIDMap updates ID mappings in a from matching the ones specified
Expand Down
29 changes: 21 additions & 8 deletions tests/stores.bats
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@

load helpers

@test "additional-stores" {
case "$STORAGE_DRIVER" in
overlay*|vfs)
;;
*)
skip "not supported by driver $STORAGE_DRIVER"
;;
esac
additional_store_test() {
export STORAGE_DRIVER=$1
# Initialize a store somewhere that we'll later use as a read-only store.
storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot layers
# Fail this test if we can't initialize the driver with the option.
Expand Down Expand Up @@ -59,6 +53,8 @@ load helpers
# We no longer need to use the read-only root as a writeable location, so shut it down.
storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown

export STORAGE_DRIVER=$2

# Create a third layer based on the second one.
run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false create-layer "$midlayer"
[ "$status" -eq 0 ]
Expand Down Expand Up @@ -151,3 +147,20 @@ load helpers
[ "$output" != "" ]
! [[ "$output" =~ "Read Only: true" ]]
}

@test "additional-stores" {
case "$STORAGE_DRIVER" in
overlay*|vfs)
;;
*)
skip "not supported by driver $STORAGE_DRIVER"
;;
esac

additional_store_test $STORAGE_DRIVER $STORAGE_DRIVER

# if the graphdriver is overlay, also test overlay using an additional store on vfs
if test "$STORAGE_DRIVER" == "overlay"; then
additional_store_test vfs $STORAGE_DRIVER
fi
}

0 comments on commit ad0dd59

Please sign in to comment.