Skip to content

Commit

Permalink
libindex: add fallback path for O_TMPFILE not being supported
Browse files Browse the repository at this point in the history
Signed-off-by: Hank Donnay <hdonnay@redhat.com>
  • Loading branch information
hdonnay committed Mar 20, 2024
1 parent 4fc28be commit 385671e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 10 deletions.
6 changes: 0 additions & 6 deletions libindex/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ var (
_ indexer.DescriptionRealizer = (*FetchProxy)(nil)
)

// BUG(hank) On Linux, the [RemoteFetchArena] makes use of the O_TMPFILE flag to
// [open(2)], which requires version 3.11 or newer. There is no fallback for
// older kernels.
//
// [open(2)]: https://man7.org/linux/man-pages/man2/open.2.html

// RemoteFetchArena uses disk space to track fetched layers, removing them once
// all users are done with the layers.
type RemoteFetchArena struct {
Expand Down
47 changes: 43 additions & 4 deletions libindex/tempfile_linux.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,63 @@
package libindex

import (
"errors"
"fmt"
"os"
"sync"

"golang.org/x/sys/unix"
)

var tmpMap sync.Map

func canTmp(dir string) (ok, loaded bool) {
v, loaded := tmpMap.Load(dir)
if v == nil {
return false, loaded
}
return v.(bool), loaded
}

func setTmp(dir string, ok bool) {
tmpMap.Store(dir, ok)
}

type tempFile struct {
*os.File
}

func openTemp(dir string) (*tempFile, error) {
f, err := os.OpenFile(dir, os.O_WRONLY|unix.O_TMPFILE, 0644)
var f *os.File
var err error

ok, loaded := canTmp(dir)
switch {
case loaded && ok:
f, err = os.OpenFile(dir, os.O_WRONLY|unix.O_TMPFILE, 0644)
case loaded && !ok:
f, err = os.CreateTemp(dir, "fetcher.*")
case !loaded:
f, err = os.OpenFile(dir, os.O_WRONLY|unix.O_TMPFILE, 0644)
if err == nil || !errors.Is(err, unix.ENOTSUP) {
ok = true
break
}
f, err = os.CreateTemp(dir, "fetcher.*")
default:
panic("unreachable")
}
if !loaded {
setTmp(dir, ok)
}
if !ok && err == nil {
f.Close()
}

if err != nil {
return nil, err
}
return &tempFile{
File: f,
}, nil
return &tempFile{File: f}, nil
}

func (t *tempFile) Reopen() (*os.File, error) {
Expand Down

0 comments on commit 385671e

Please sign in to comment.