Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store extended attributes in files in stead of in extended attributes #3649

Merged
merged 39 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
138f6b1
Store node attributes in actual files instead of xattrs
aduffeck Feb 9, 2023
a254e4a
Use our xattrs instead of xattr everywhere. Fix tests.
aduffeck Feb 10, 2023
c1ed5b2
Cops the type attribute when copying attributes
aduffeck Feb 10, 2023
e8d8268
Use mtime of the childre dir when no tmtime is set
aduffeck Feb 10, 2023
6de81da
Fix node.IsDir() logic
aduffeck Feb 13, 2023
69c4f38
Fix trash bin item types
aduffeck Feb 13, 2023
c490456
Fix part of the trashbin functionality
aduffeck Feb 14, 2023
06904e1
Fix node id of recycle items
aduffeck Feb 14, 2023
26c253a
Fix deleting references to subtrees that have been restored
aduffeck Feb 14, 2023
efcf327
Fix cleaning up after restoring items from the trash bin
aduffeck Feb 15, 2023
84ab98d
Fix purging subdirectories of trash bin entries
aduffeck Feb 15, 2023
9fa1eca
Hound fixes
aduffeck Feb 15, 2023
cf98c05
More linter fixes
aduffeck Feb 15, 2023
8fb0c5c
Use the node's GetTMTime() instead of reading it manually
aduffeck Feb 15, 2023
d8826c5
Do not change the mtime when setting attrs. xattrs don't do it either.
aduffeck Feb 15, 2023
ea87062
Fix error message
aduffeck Feb 15, 2023
e6745d4
Store file metadata separately instead of moving the children elsewhere
aduffeck Feb 15, 2023
cbd8299
Fix tests
aduffeck Feb 15, 2023
8d6d381
Filter meta files when listing revisions
aduffeck Feb 15, 2023
cd280b4
Fix tests
aduffeck Feb 15, 2023
175367d
Fix deep listing the recycle
aduffeck Feb 15, 2023
4cccab3
Fix reading items deeper in the trash
aduffeck Feb 15, 2023
57d50c5
Encode binary values
aduffeck Feb 15, 2023
a53e31f
Fall back to getting the node type by looking at the disk
aduffeck Feb 16, 2023
a9a2589
some xattr backend fixes
butonic Feb 16, 2023
3a6c15c
make metadata backend configurable
butonic Feb 16, 2023
bdfa862
make linter happy
butonic Feb 16, 2023
45de6e3
add changelog
butonic Feb 16, 2023
18cdc4d
Merge branch 'edge' into materialized-xattrs
butonic Feb 16, 2023
f133a25
add missing comments
butonic Feb 16, 2023
d0c3392
more linter fixes
butonic Feb 16, 2023
866388a
always initialize xattr backend to make tests pass
butonic Feb 16, 2023
ba9c47a
Fix typo
aduffeck Feb 17, 2023
782f374
Improve error messages
aduffeck Feb 17, 2023
c143380
Use lockedfile package to access metadata files
aduffeck Feb 17, 2023
ded5e6a
Cache file metadata
aduffeck Feb 17, 2023
1bf36a5
Tidy go modules
aduffeck Feb 17, 2023
eaf8a06
Do not ignore error when writing the cache
aduffeck Feb 17, 2023
3169cbd
use global var for regex
butonic Feb 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog/unreleased/materialized-xattrs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Introduce ini file based metadata backend

We added a new metadata backend for the decomposed storage driver that uses an additional `.ini` file to store file metadata. This allows scaling beyond some filesystem specific xattr limitations.

https://github.com/cs3org/reva/pull/3649
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ require (
github.com/pkg/xattr v0.4.9
github.com/prometheus/alertmanager v0.24.0
github.com/prometheus/client_golang v1.13.0
github.com/rogpeppe/go-internal v1.3.0
github.com/rs/cors v1.8.2
github.com/rs/zerolog v1.28.0
github.com/sciencemesh/meshdirectory-web v1.0.4
Expand All @@ -84,6 +85,7 @@ require (
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e
google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.1
gopkg.in/ini.v1 v1.67.0
gotest.tools v2.2.0+incompatible
)

Expand Down Expand Up @@ -201,7 +203,6 @@ require (
golang.org/x/time v0.1.0 // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
Expand Down
13 changes: 12 additions & 1 deletion pkg/storage/utils/decomposedfs/decomposedfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package decomposedfs

import (
"context"
"fmt"
"io"
"net/url"
"os"
Expand Down Expand Up @@ -51,6 +52,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs/prefixes"
"github.com/cs3org/reva/v2/pkg/storage/utils/filelocks"
"github.com/cs3org/reva/v2/pkg/storage/utils/templates"
"github.com/cs3org/reva/v2/pkg/storagespace"
Expand Down Expand Up @@ -101,6 +103,15 @@ func NewDefault(m map[string]interface{}, bs tree.Blobstore, es events.Stream) (
return nil, err
}

switch o.MetadataBackend {
case "xattrs":
xattrs.UseXattrsBackend()
case "ini":
xattrs.UseIniBackend()
default:
return nil, fmt.Errorf("unknown metadata backend %s, only 'ini' or 'xattrs' (default) supported", o.MetadataBackend)
}

lu := &lookup.Lookup{}
lu.Options = o

Expand Down Expand Up @@ -566,7 +577,7 @@ func (fs *Decomposedfs) CreateDir(ctx context.Context, ref *provider.Reference)

if fs.o.TreeTimeAccounting || fs.o.TreeSizeAccounting {
// mark the home node as the end of propagation
if err = n.SetXattr(xattrs.PropagationAttr, "1"); err != nil {
if err = n.SetXattr(prefixes.PropagationAttr, "1"); err != nil {
appctx.GetLogger(ctx).Error().Err(err).Interface("node", n).Msg("could not mark node to propagate")

// FIXME: This does not return an error at all, but results in a severe situation that the
Expand Down
11 changes: 6 additions & 5 deletions pkg/storage/utils/decomposedfs/grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storage/utils/ace"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs/prefixes"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils"
)
Expand Down Expand Up @@ -202,9 +203,9 @@ func (fs *Decomposedfs) RemoveGrant(ctx context.Context, ref *provider.Reference

var attr string
if g.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_GROUP {
attr = xattrs.GrantGroupAcePrefix + g.Grantee.GetGroupId().OpaqueId
attr = prefixes.GrantGroupAcePrefix + g.Grantee.GetGroupId().OpaqueId
} else {
attr = xattrs.GrantUserAcePrefix + g.Grantee.GetUserId().OpaqueId
attr = prefixes.GrantUserAcePrefix + g.Grantee.GetUserId().OpaqueId
}

if err = xattrs.Remove(grantNode.InternalPath(), attr); err != nil {
Expand Down Expand Up @@ -309,7 +310,7 @@ func (fs *Decomposedfs) storeGrant(ctx context.Context, n *node.Node, g *provide
// set the grant
e := ace.FromGrant(g)
principal, value := e.Marshal()
if err := n.SetXattr(xattrs.GrantPrefix+principal, string(value)); err != nil {
if err := n.SetXattr(prefixes.GrantPrefix+principal, string(value)); err != nil {
appctx.GetLogger(ctx).Error().Err(err).
Str("principal", principal).Msg("Could not set grant for principal")
return err
Expand All @@ -329,15 +330,15 @@ func extractACEsFromAttrs(ctx context.Context, fsfn string, attrs []string) (ent
log := appctx.GetLogger(ctx)
entries = []*ace.ACE{}
for i := range attrs {
if strings.HasPrefix(attrs[i], xattrs.GrantPrefix) {
if strings.HasPrefix(attrs[i], prefixes.GrantPrefix) {
var value string
var err error
if value, err = xattrs.Get(fsfn, attrs[i]); err != nil {
log.Error().Err(err).Str("attr", attrs[i]).Msg("could not read attribute")
continue
}
var e *ace.ACE
principal := attrs[i][len(xattrs.GrantPrefix):]
principal := attrs[i][len(prefixes.GrantPrefix):]
if e, err = ace.Unmarshal(principal, []byte(value)); err != nil {
log.Error().Err(err).Str("principal", principal).Str("attr", attrs[i]).Msg("could not unmarshal ace")
continue
Expand Down
6 changes: 3 additions & 3 deletions pkg/storage/utils/decomposedfs/grants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
helpers "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/testhelpers"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs/prefixes"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/pkg/xattr"
"github.com/stretchr/testify/mock"
)

Expand Down Expand Up @@ -140,9 +140,9 @@ var _ = Describe("Grants", func() {

o := env.Owner.GetId()
localPath := n.InternalPath()
attr, err := xattr.Get(localPath, xattrs.GrantUserAcePrefix+grant.Grantee.GetUserId().OpaqueId)
attr, err := xattrs.Get(localPath, prefixes.GrantUserAcePrefix+grant.Grantee.GetUserId().OpaqueId)
Expect(err).ToNot(HaveOccurred())
Expect(string(attr)).To(Equal(fmt.Sprintf("\x00t=A:f=:p=rw:c=%s:e=0\n", o.GetOpaqueId()))) // NOTE: this tests ace package
Expect(attr).To(Equal(fmt.Sprintf("\x00t=A:f=:p=rw:c=%s:e=0\n", o.GetOpaqueId()))) // NOTE: this tests ace package
})

It("creates a storage space per created grant", func() {
Expand Down
3 changes: 2 additions & 1 deletion pkg/storage/utils/decomposedfs/lookup/lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs/prefixes"
)

// Lookup implements transformations from filepath to node and back
Expand Down Expand Up @@ -138,7 +139,7 @@ func (lu *Lookup) WalkPath(ctx context.Context, r *node.Node, p string, followRe
}

if followReferences {
if attrBytes, err := r.Xattr(xattrs.ReferenceAttr); err == nil {
if attrBytes, err := r.Xattr(prefixes.ReferenceAttr); err == nil {
realNodeID := attrBytes
ref, err := xattrs.ReferenceFromAttr([]byte(realNodeID))
if err != nil {
Expand Down
7 changes: 4 additions & 3 deletions pkg/storage/utils/decomposedfs/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs"
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs/prefixes"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/pkg/errors"
Expand Down Expand Up @@ -109,7 +110,7 @@ func (fs *Decomposedfs) SetArbitraryMetadata(ctx context.Context, ref *provider.
}
}
for k, v := range md.Metadata {
attrName := xattrs.MetadataPrefix + k
attrName := prefixes.MetadataPrefix + k
if err = n.SetXattr(attrName, v); err != nil {
errs = append(errs, errors.Wrap(err, "Decomposedfs: could not set metadata attribute "+attrName+" to "+k))
}
Expand Down Expand Up @@ -182,7 +183,7 @@ func (fs *Decomposedfs) UnsetArbitraryMetadata(ctx context.Context, ref *provide
errs = append(errs, errors.Wrap(errtypes.UserRequired("userrequired"), "user has no id"))
continue
}
fa := fmt.Sprintf("%s:%s:%s@%s", xattrs.FavPrefix, utils.UserTypeToString(uid.GetType()), uid.GetOpaqueId(), uid.GetIdp())
fa := fmt.Sprintf("%s:%s:%s@%s", prefixes.FavPrefix, utils.UserTypeToString(uid.GetType()), uid.GetOpaqueId(), uid.GetIdp())
if err := n.RemoveXattr(fa); err != nil {
if xattrs.IsAttrUnset(err) {
continue // already gone, ignore
Expand All @@ -194,7 +195,7 @@ func (fs *Decomposedfs) UnsetArbitraryMetadata(ctx context.Context, ref *provide
errs = append(errs, errors.Wrap(err, "could not unset favorite flag"))
}
default:
if err = n.RemoveXattr(xattrs.MetadataPrefix + k); err != nil {
if err = n.RemoveXattr(prefixes.MetadataPrefix + k); err != nil {
if xattrs.IsAttrUnset(err) {
continue // already gone, ignore
}
Expand Down
Loading