Skip to content

Commit

Permalink
overlay: support "userxattr" option (kernel 5.11)
Browse files Browse the repository at this point in the history
ref: containerd/containerd#5076

Signed-off-by: Akihiro Suda <[email protected]>
  • Loading branch information
AkihiroSuda committed Mar 19, 2021
1 parent eacc54a commit d60ca9f
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 11 deletions.
19 changes: 12 additions & 7 deletions fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ import (
"golang.org/x/sys/unix"
)

var opaqueXattrs = []string{"trusted.overlay.opaque", "user.overlay.opaque"}

const (
blockSize = 4096
whiteoutPrefix = ".wh."
whiteoutOpaqueDir = whiteoutPrefix + whiteoutPrefix + ".opq"
opaqueXattr = "trusted.overlay.opaque"
opaqueXattrValue = "y"
stateDirName = ".stargz-snapshotter"
defaultMaxConcurrency = 2
Expand Down Expand Up @@ -545,12 +546,14 @@ func (n *node) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrO
var _ = (fusefs.NodeGetxattrer)((*node)(nil))

func (n *node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
if attr == opaqueXattr && n.opaque {
// This node is an opaque directory so give overlayfs-compliant indicator.
if len(dest) < len(opaqueXattrValue) {
return uint32(len(opaqueXattrValue)), syscall.ERANGE
for _, opaqueXattr := range opaqueXattrs {
if attr == opaqueXattr && n.opaque {
// This node is an opaque directory so give overlayfs-compliant indicator.
if len(dest) < len(opaqueXattrValue) {
return uint32(len(opaqueXattrValue)), syscall.ERANGE
}
return uint32(copy(dest, opaqueXattrValue)), 0
}
return uint32(copy(dest, opaqueXattrValue)), 0
}
if v, ok := n.e.Xattrs[attr]; ok {
if len(dest) < len(v) {
Expand All @@ -567,7 +570,9 @@ func (n *node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errn
var attrs []byte
if n.opaque {
// This node is an opaque directory so add overlayfs-compliant indicator.
attrs = append(attrs, []byte(opaqueXattr+"\x00")...)
for _, opaqueXattr := range opaqueXattrs {
attrs = append(attrs, []byte(opaqueXattr+"\x00")...)
}
}
for k := range n.e.Xattrs {
attrs = append(attrs, []byte(k+"\x00")...)
Expand Down
9 changes: 6 additions & 3 deletions fs/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ func TestExistence(t *testing.T) {
testutil.File("foo/.wh..wh..opq", ""),
},
want: []check{
hasNodeXattrs("foo/", opaqueXattr, opaqueXattrValue),
hasNodeXattrs("foo/", opaqueXattrs[0], opaqueXattrValue),
hasNodeXattrs("foo/", opaqueXattrs[1], opaqueXattrValue),
fileNotExist("foo/.wh..wh..opq"),
},
},
Expand All @@ -250,7 +251,8 @@ func TestExistence(t *testing.T) {
testutil.File("foo/bar.txt", "test"),
},
want: []check{
hasNodeXattrs("foo/", opaqueXattr, opaqueXattrValue),
hasNodeXattrs("foo/", opaqueXattrs[0], opaqueXattrValue),
hasNodeXattrs("foo/", opaqueXattrs[1], opaqueXattrValue),
hasFileDigest("foo/bar.txt", digestFor("test")),
fileNotExist("foo/.wh..wh..opq"),
},
Expand All @@ -262,7 +264,8 @@ func TestExistence(t *testing.T) {
testutil.File("foo/.wh..wh..opq", ""),
},
want: []check{
hasNodeXattrs("foo/", opaqueXattr, opaqueXattrValue),
hasNodeXattrs("foo/", opaqueXattrs[0], opaqueXattrValue),
hasNodeXattrs("foo/", opaqueXattrs[1], opaqueXattrValue),
hasNodeXattrs("foo/", "foo", "bar"),
fileNotExist("foo/.wh..wh..opq"),
},
Expand Down
14 changes: 13 additions & 1 deletion snapshot/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ import (
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/containerd/snapshots/overlay/overlayutils"
"github.com/containerd/containerd/snapshots/storage"
"github.com/containerd/continuity/fs"
"github.com/moby/sys/mountinfo"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
)

Expand Down Expand Up @@ -91,7 +93,8 @@ type snapshotter struct {
asyncRemove bool

// fs is a filesystem that this snapshotter recognizes.
fs FileSystem
fs FileSystem
userxattr bool // whether to enable "userxattr" mount option
}

// NewSnapshotter returns a Snapshotter which can use unpacked remote layers
Expand Down Expand Up @@ -129,11 +132,17 @@ func NewSnapshotter(ctx context.Context, root string, targetFs FileSystem, opts
return nil, err
}

userxattr, err := overlayutils.NeedsUserXAttr(root)
if err != nil {
logrus.WithError(err).Warnf("cannot detect whether \"userxattr\" option needs to be used, assuming to be %v", userxattr)
}

o := &snapshotter{
root: root,
ms: ms,
asyncRemove: config.asyncRemove,
fs: targetFs,
userxattr: userxattr,
}

if err := o.restoreRemoteSnapshot(ctx); err != nil {
Expand Down Expand Up @@ -598,6 +607,9 @@ func (o *snapshotter) mounts(ctx context.Context, s storage.Snapshot, checkKey s
}

options = append(options, fmt.Sprintf("lowerdir=%s", strings.Join(parentPaths, ":")))
if o.userxattr {
options = append(options, "userxattr")
}
return []mount.Mount{
{
Type: "overlay",
Expand Down

0 comments on commit d60ca9f

Please sign in to comment.