Skip to content

Commit 4ba2fc2

Browse files
committed
feat: add noarchive to scoutfs part files
The part files for multipart uploads are considered temporary files and should not be archived by default. This adds the noarchive attribute to the part files to prevent scoutam from trying to archive these. There is a new parameter, disablenoarchive, that will prevent adding the noarchive attribute to these files for the case where there is a desire to archive these temp files.
1 parent 293e7fa commit 4ba2fc2

File tree

3 files changed

+80
-36
lines changed

3 files changed

+80
-36
lines changed

backend/scoutfs/scoutfs.go

+62-27
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ import (
4040
)
4141

4242
type ScoutfsOpts struct {
43-
ChownUID bool
44-
ChownGID bool
45-
GlacierMode bool
46-
BucketLinks bool
47-
NewDirPerm fs.FileMode
43+
ChownUID bool
44+
ChownGID bool
45+
GlacierMode bool
46+
BucketLinks bool
47+
NewDirPerm fs.FileMode
48+
DisableNoArchive bool
4849
}
4950

5051
type ScoutFS struct {
@@ -78,6 +79,11 @@ type ScoutFS struct {
7879

7980
// newDirPerm is the permissions to use when creating new directories
8081
newDirPerm fs.FileMode
82+
83+
// disableNoArchive is used to disable setting scoutam noarchive flag
84+
// on mutlipart parts. This is enabled by default to prevent archive
85+
// copies of temporary multipart parts.
86+
disableNoArchive bool
8187
}
8288

8389
var _ backend.Backend = &ScoutFS{}
@@ -156,6 +162,31 @@ func (s *ScoutFS) getChownIDs(acct auth.Account) (int, int, bool) {
156162
return uid, gid, needsChown
157163
}
158164

165+
func (s *ScoutFS) UploadPart(ctx context.Context, input *s3.UploadPartInput) (*s3.UploadPartOutput, error) {
166+
out, err := s.Posix.UploadPart(ctx, input)
167+
if err != nil {
168+
return nil, err
169+
}
170+
171+
if !s.disableNoArchive {
172+
object := *input.Key
173+
bucket := *input.Bucket
174+
uploadID := *input.UploadId
175+
part := *input.PartNumber
176+
sum := sha256.Sum256([]byte(object))
177+
objdir := filepath.Join(metaTmpMultipartDir, fmt.Sprintf("%x", sum))
178+
mpPath := filepath.Join(objdir, uploadID)
179+
partPath := filepath.Join(bucket, mpPath, fmt.Sprintf("%v", part))
180+
181+
err = setNoArchive(partPath)
182+
if err != nil {
183+
return nil, fmt.Errorf("set noarchive: %w", err)
184+
}
185+
}
186+
187+
return out, err
188+
}
189+
159190
// CompleteMultipartUpload scoutfs complete upload uses scoutfs move blocks
160191
// ioctl to not have to read and copy the part data to the final object. This
161192
// saves a read and write cycle for all mutlipart uploads.
@@ -932,56 +963,60 @@ func (s *ScoutFS) RestoreObject(_ context.Context, input *s3.RestoreObjectInput)
932963
return nil
933964
}
934965

935-
func setStaging(objname string) error {
966+
func isStaging(objname string) (bool, error) {
936967
b, err := xattr.Get(objname, flagskey)
937968
if err != nil && !isNoAttr(err) {
938-
return err
969+
return false, err
939970
}
940971

941-
var oldflags uint64
972+
var flags uint64
942973
if !isNoAttr(err) {
943-
err = json.Unmarshal(b, &oldflags)
974+
err = json.Unmarshal(b, &flags)
944975
if err != nil {
945-
return err
976+
return false, err
946977
}
947978
}
948979

949-
newflags := oldflags | Staging
950-
951-
if newflags == oldflags {
952-
// no flags change, just return
953-
return nil
954-
}
955-
956-
return fSetNewGlobalFlags(objname, newflags)
980+
return flags&Staging == Staging, nil
957981
}
958982

959-
func isStaging(objname string) (bool, error) {
983+
func setFlag(objname string, flag uint64) error {
960984
b, err := xattr.Get(objname, flagskey)
961985
if err != nil && !isNoAttr(err) {
962-
return false, err
986+
return err
963987
}
964988

965-
var flags uint64
989+
var oldflags uint64
966990
if !isNoAttr(err) {
967-
err = json.Unmarshal(b, &flags)
991+
err = json.Unmarshal(b, &oldflags)
968992
if err != nil {
969-
return false, err
993+
return err
970994
}
971995
}
972996

973-
return flags&Staging == Staging, nil
974-
}
997+
newflags := oldflags | flag
998+
999+
if newflags == oldflags {
1000+
// no flags change, just return
1001+
return nil
1002+
}
9751003

976-
func fSetNewGlobalFlags(objname string, flags uint64) error {
977-
b, err := json.Marshal(&flags)
1004+
b, err = json.Marshal(&newflags)
9781005
if err != nil {
9791006
return err
9801007
}
9811008

9821009
return xattr.Set(objname, flagskey, b)
9831010
}
9841011

1012+
func setStaging(objname string) error {
1013+
return setFlag(objname, Staging)
1014+
}
1015+
1016+
func setNoArchive(objname string) error {
1017+
return setFlag(objname, NoArchive)
1018+
}
1019+
9851020
func isNoAttr(err error) bool {
9861021
xerr, ok := err.(*xattr.Error)
9871022
if ok && xerr.Err == xattr.ENOATTR {

backend/scoutfs/scoutfs_compat.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,15 @@ func New(rootdir string, opts ScoutfsOpts) (*ScoutFS, error) {
5252
}
5353

5454
return &ScoutFS{
55-
Posix: p,
56-
rootfd: f,
57-
rootdir: rootdir,
58-
meta: metastore,
59-
chownuid: opts.ChownUID,
60-
chowngid: opts.ChownGID,
61-
glaciermode: opts.GlacierMode,
62-
newDirPerm: opts.NewDirPerm,
55+
Posix: p,
56+
rootfd: f,
57+
rootdir: rootdir,
58+
meta: metastore,
59+
chownuid: opts.ChownUID,
60+
chowngid: opts.ChownGID,
61+
glaciermode: opts.GlacierMode,
62+
newDirPerm: opts.NewDirPerm,
63+
disableNoArchive: opts.DisableNoArchive,
6364
}, nil
6465
}
6566

cmd/versitygw/scoutfs.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import (
2424
)
2525

2626
var (
27-
glacier bool
27+
glacier bool
28+
disableNoArchive bool
2829
)
2930

3031
func scoutfsCommand() *cli.Command {
@@ -79,6 +80,12 @@ move interfaces as well as support for tiered filesystems.`,
7980
DefaultText: "0755",
8081
Value: 0755,
8182
},
83+
&cli.BoolFlag{
84+
Name: "disablenoarchive",
85+
Usage: "disable setting noarchive for multipart part uploads",
86+
EnvVars: []string{"VGW_DISABLE_NOARCHIVE"},
87+
Destination: &disableNoArchive,
88+
},
8289
},
8390
}
8491
}
@@ -98,6 +105,7 @@ func runScoutfs(ctx *cli.Context) error {
98105
opts.ChownGID = chowngid
99106
opts.BucketLinks = bucketlinks
100107
opts.NewDirPerm = fs.FileMode(dirPerms)
108+
opts.DisableNoArchive = disableNoArchive
101109

102110
be, err := scoutfs.New(ctx.Args().Get(0), opts)
103111
if err != nil {

0 commit comments

Comments
 (0)