Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
bd3380d
Improve test coverage of libfuse to above 90%
jfantinhardesty Feb 26, 2026
0c8b1c5
Fix lint issues
jfantinhardesty Feb 27, 2026
9bdd53b
Improve tests for read/write, handle ENOTEMPTY correctly
jfantinhardesty Mar 3, 2026
5fbe854
Fix tests for windows, fix umask parsing
jfantinhardesty Mar 3, 2026
34239d2
Improve tests around reading link and filling stats
jfantinhardesty Mar 3, 2026
448901a
Follow better testify practices, add some additional tests for rename…
jfantinhardesty Mar 3, 2026
0d016f4
Fix issue with log destroyed error message on mount and extra logs on…
jfantinhardesty Mar 3, 2026
d8087f5
Merge branch 'main' into improve_posix_compatability
jfantinhardesty Mar 4, 2026
1a5b25c
Merge branch 'fix_error_logging_mount_unmount' into improve_posix_com…
jfantinhardesty Mar 4, 2026
7dd0d78
Improve POSIX compatability with atime, ctime, errors, etc.
jfantinhardesty Mar 5, 2026
1e0e1b8
Merge branch 'main' into improve_posix_compatability
jfantinhardesty Mar 11, 2026
6b652cc
Small fixes in attr cache mode selection and rename symlink in s3storage
jfantinhardesty Mar 11, 2026
31fe4a1
Merge branch 'main' into improve_posix_compatability
jfantinhardesty Mar 13, 2026
db91aea
Error in createDirectory if too long
jfantinhardesty Mar 13, 2026
d674227
Address symlink issues with max length, attr_cache issues with no-cac…
jfantinhardesty Mar 13, 2026
4c7b8f5
Small performance improvment
jfantinhardesty Mar 13, 2026
3b42aaa
Merge branch 'main' into improve_posix_compatability
jfantinhardesty Apr 2, 2026
b75149b
Revert unnecessary changes
jfantinhardesty Apr 2, 2026
a276e21
Split attr-cache parent time updates
jfantinhardesty Apr 2, 2026
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
36 changes: 25 additions & 11 deletions component/attr_cache/attr_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,21 +299,14 @@ func (ac *AttrCache) moveCachedItem(
}
// generate the destination name
dstPath := strings.Replace(srcItem.attr.Path, srcDir, dstDir, 1)
// create the destination attr
var dstAttr *internal.ObjAttr
if srcItem.attr.IsDir() {
dstAttr = internal.CreateObjAttrDir(dstPath)
} else {
dstAttr = internal.CreateObjAttr(dstPath, srcItem.attr.Size, srcItem.attr.Mtime)
}
dstAttr := cloneMovedAttr(srcItem.attr, dstPath)
// add the destination item to the cache
dstItem := ac.cache.insert(insertOptions{
attr: dstAttr,
exists: true,
cachedAt: srcItem.cachedAt,
})
// copy the inCloud flag
dstItem.attr.Mode = srcItem.attr.Mode
dstItem.markInCloud(srcItem.isInCloud())
// recurse over any children
for _, srcChildItm := range srcItem.children {
Expand All @@ -325,6 +318,21 @@ func (ac *AttrCache) moveCachedItem(
return dstItem
}

func cloneMovedAttr(srcAttr *internal.ObjAttr, dstPath string) *internal.ObjAttr {
dstAttr := *srcAttr
dstAttr.Path = dstPath
dstAttr.Name = path.Base(dstPath)

if srcAttr.Metadata != nil {
dstAttr.Metadata = make(map[string]*string, len(srcAttr.Metadata))
for key, value := range srcAttr.Metadata {
dstAttr.Metadata[key] = value
}
}

return &dstAttr
}

// record that cloud storage has records of this directory and all its ancestors existing
func (ac *AttrCache) markAncestorsInCloud(dirPath string, time time.Time) {
if len(dirPath) != 0 {
Expand Down Expand Up @@ -428,6 +436,7 @@ func (ac *AttrCache) CreateDir(options internal.CreateDirOptions) error {
log.Trace("AttrCache::CreateDir : %s", options.Name)
err := ac.NextComponent().CreateDir(options)
if err == nil || err == syscall.EEXIST {
currentTime := time.Now()
ac.cacheLock.Lock()
defer ac.cacheLock.Unlock()
// does the directory already exist?
Expand All @@ -447,10 +456,13 @@ func (ac *AttrCache) CreateDir(options internal.CreateDirOptions) error {
newDirAttrCacheItem := ac.cache.insert(insertOptions{
attr: newDirAttr,
exists: true,
cachedAt: time.Now(),
cachedAt: currentTime,
})
if newDirAttrCacheItem != nil {
newDirAttrCacheItem.setMode(options.Mode)
}
// update flags for tracking directory existence
if ac.cacheDirs {
if ac.cacheDirs && newDirAttrCacheItem != nil {
newDirAttrCacheItem.markInCloud(false)
}
}
Expand Down Expand Up @@ -802,7 +814,9 @@ func (ac *AttrCache) CreateFile(options internal.CreateFileOptions) (*handlemap.
exists: true,
cachedAt: currentTime,
})
newFileEntry.setMode(options.Mode)
if newFileEntry != nil {
newFileEntry.setMode(options.Mode)
}
}

return h, err
Expand Down
7 changes: 5 additions & 2 deletions component/attr_cache/attr_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ func (suite *attrCacheTestSuite) TestCreateDir() {
suite.SetupTest()
suite.Run(path, func() {
truncatedPath := internal.TruncateDirName(path)
options := internal.CreateDirOptions{Name: path}
options := internal.CreateDirOptions{Name: path, Mode: 0o750}

// Error
suite.mock.EXPECT().CreateDir(options).Return(errors.New("Failed"))
Expand All @@ -399,8 +399,11 @@ func (suite *attrCacheTestSuite) TestCreateDir() {
err = suite.attrCache.CreateDir(options)
suite.assert.NoError(err)

_, found := suite.attrCache.cache.get(truncatedPath)
item, found := suite.attrCache.cache.get(truncatedPath)
suite.assert.True(found)
suite.assert.Equal(os.ModeDir, item.attr.Mode&os.ModeType)
suite.assert.Equal(options.Mode, item.attr.Mode&os.ModePerm)
suite.assert.False(item.attr.IsModeDefault())

// Entry Already Exists
suite.mock.EXPECT().CreateDir(options).Return(nil)
Expand Down
8 changes: 7 additions & 1 deletion component/attr_cache/cacheMap.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,18 @@ func (value *attrCacheItem) markInCloud(inCloud bool) {

func (value *attrCacheItem) setSize(size int64, changedAt time.Time) {
value.attr.Mtime = changedAt
value.attr.Ctime = changedAt
value.attr.Size = size
value.cachedAt = changedAt
}

func (value *attrCacheItem) setMode(mode os.FileMode) {
value.attr.Mode = mode
currentType := value.attr.Mode & os.ModeType
if currentType == 0 {
currentType = mode & os.ModeType
}
modeBits := mode & (os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky)
value.attr.Mode = currentType | modeBits
value.attr.Flags.Clear(internal.PropFlagModeDefault)
value.attr.Ctime = time.Now()
value.cachedAt = time.Now()
Expand Down
Loading
Loading