From 4ecda392f1a49fd81b20b5e03b01cbece58b097e Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Mon, 21 Mar 2022 14:50:18 -0700 Subject: [PATCH 01/11] Enforce ENAMETOOLONG --- iclient/dev.conf | 1 + iclient/iclient.conf | 1 + iclient/iclientpkg/api.go | 1 + iclient/iclientpkg/fission.go | 51 ++++++++++++++++++++++++++++++++ iclient/iclientpkg/globals.go | 6 ++++ iclient/iclientpkg/utils_test.go | 1 + 6 files changed, 61 insertions(+) diff --git a/iclient/dev.conf b/iclient/dev.conf index 90990c8b..a61e4f6b 100644 --- a/iclient/dev.conf +++ b/iclient/dev.conf @@ -13,6 +13,7 @@ FUSEMaxRead: 1048576 FUSEMaxWrite: 1048576 FUSEEntryValidDuration: 250ms FUSEAttrValidDuration: 250ms +FUSENameLenMax: 1024 AuthPlugInPath: iauth/iauth-swift/iauth-swift.so AuthPlugInEnvName: AuthPlugInEnvValue: {"AuthURL":"http://swift:8080/auth/v1.0"\u002C"AuthUser":"test:tester"\u002C"AuthKey":"testing"\u002C"Account":"AUTH_test"\u002C"Container":"con"} diff --git a/iclient/iclient.conf b/iclient/iclient.conf index 798341fb..381d8034 100644 --- a/iclient/iclient.conf +++ b/iclient/iclient.conf @@ -13,6 +13,7 @@ FUSEMaxRead: 1048576 FUSEMaxWrite: 1048576 FUSEEntryValidDuration: 250ms FUSEAttrValidDuration: 250ms +FUSENameLenMax: 1024 AuthPlugInPath: iauth-swift.so AuthPlugInEnvName: AuthPlugInEnvValue: {"AuthURL":"http://swift:8080/auth/v1.0"\u002C"AuthUser":"test:tester"\u002C"AuthKey":"testing"\u002C"Account":"AUTH_test"\u002C"Container":"con"} diff --git a/iclient/iclientpkg/api.go b/iclient/iclientpkg/api.go index 3647aa6d..956049cb 100644 --- a/iclient/iclientpkg/api.go +++ b/iclient/iclientpkg/api.go @@ -19,6 +19,7 @@ // FUSEMaxWrite: 1048576 # 1MiB == FUSEMaxPages(256) * 4KiB // FUSEEntryValidDuration: 250ms // FUSEAttrValidDuration: 250ms +// FUSENameLenMax: 1024 // AuthPlugInPath: iauth-swift.so // AuthPlugInEnvName: # Only used if not defining AuthPlugInEnvValue here // AuthPlugInEnvValue: {"AuthURL":"http://swift:8080/auth/v1.0"\u002C"AuthUser":"test:tester"\u002C"AuthKey":"testing"\u002C"Account":"AUTH_test"\u002C"Container":"con"} diff --git a/iclient/iclientpkg/fission.go b/iclient/iclientpkg/fission.go index cb4c9187..c795c877 100644 --- a/iclient/iclientpkg/fission.go +++ b/iclient/iclientpkg/fission.go @@ -98,6 +98,12 @@ func (dummy *globalsStruct) DoLookup(inHeader *fission.InHeader, lookupIn *fissi globals.stats.DoLookupUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if len(lookupIn.Name) > int(globals.config.FUSENameLenMax) { + lookupOut = nil + errno = syscall.ENAMETOOLONG + return + } + Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID @@ -498,6 +504,12 @@ func (dummy *globalsStruct) DoSymLink(inHeader *fission.InHeader, symLinkIn *fis globals.stats.DoSymLinkUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if (len(symLinkIn.Name) > int(globals.config.FUSENameLenMax)) || (len(symLinkIn.Data) > int(globals.config.FUSENameLenMax)) { + symLinkOut = nil + errno = syscall.ENAMETOOLONG + return + } + Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID @@ -702,6 +714,12 @@ func (dummy *globalsStruct) DoMkDir(inHeader *fission.InHeader, mkDirIn *fission globals.stats.DoMkDirUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if len(mkDirIn.Name) > int(globals.config.FUSENameLenMax) { + mkDirOut = nil + errno = syscall.ENAMETOOLONG + return + } + Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID @@ -931,6 +949,11 @@ func (dummy *globalsStruct) DoUnlink(inHeader *fission.InHeader, unlinkIn *fissi globals.stats.DoUnlinkUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if len(unlinkIn.Name) > int(globals.config.FUSENameLenMax) { + errno = syscall.ENAMETOOLONG + return + } + Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID @@ -1085,6 +1108,11 @@ func (dummy *globalsStruct) DoRmDir(inHeader *fission.InHeader, rmDirIn *fission globals.stats.DoRmDirUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if len(rmDirIn.Name) > int(globals.config.FUSENameLenMax) { + errno = syscall.ENAMETOOLONG + return + } + Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID @@ -1241,6 +1269,11 @@ func (dummy *globalsStruct) DoRename(inHeader *fission.InHeader, renameIn *fissi globals.stats.DoRenameUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if (len(renameIn.OldName) > int(globals.config.FUSENameLenMax)) || (len(renameIn.NewName) > int(globals.config.FUSENameLenMax)) { + errno = syscall.ENAMETOOLONG + return + } + errno = doRenameCommon(inHeader.NodeID, string(renameIn.OldName[:]), renameIn.NewDir, string(renameIn.NewName[:]), startTime) return } @@ -1264,6 +1297,12 @@ func (dummy *globalsStruct) DoLink(inHeader *fission.InHeader, linkIn *fission.L globals.stats.DoLinkUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if len(linkIn.Name) > int(globals.config.FUSENameLenMax) { + linkOut = nil + errno = syscall.ENAMETOOLONG + return + } + Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID @@ -2122,6 +2161,7 @@ func (dummy *globalsStruct) DoStatFS(inHeader *fission.InHeader) (statFSOut *fis Files: math.MaxUint64, FFree: math.MaxUint64, BSize: globals.config.FUSEBlockSize, + NameLen: globals.config.FUSENameLenMax, FRSize: globals.config.FUSEBlockSize, Padding: 0, Spare: [6]uint32{0, 0, 0, 0, 0, 0}, @@ -3113,6 +3153,12 @@ func (dummy *globalsStruct) DoCreate(inHeader *fission.InHeader, createIn *fissi globals.stats.DoCreateUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if len(createIn.Name) > int(globals.config.FUSENameLenMax) { + createOut = nil + errno = syscall.ENAMETOOLONG + return + } + Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID @@ -3641,6 +3687,11 @@ func (dummy *globalsStruct) DoRename2(inHeader *fission.InHeader, rename2In *fis globals.stats.DoRename2Usecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() + if (len(rename2In.OldName) > int(globals.config.FUSENameLenMax)) || (len(rename2In.NewName) > int(globals.config.FUSENameLenMax)) { + errno = syscall.ENAMETOOLONG + return + } + errno = doRenameCommon(inHeader.NodeID, string(rename2In.OldName[:]), rename2In.NewDir, string(rename2In.NewName[:]), startTime) return } diff --git a/iclient/iclientpkg/globals.go b/iclient/iclientpkg/globals.go index 6f63df37..4cdd0f7d 100644 --- a/iclient/iclientpkg/globals.go +++ b/iclient/iclientpkg/globals.go @@ -34,6 +34,7 @@ type configStruct struct { FUSEMaxWrite uint32 FUSEEntryValidDuration time.Duration FUSEAttrValidDuration time.Duration + FUSENameLenMax uint32 AuthPlugInPath string AuthPlugInEnvName string AuthPlugInEnvValue string @@ -334,6 +335,10 @@ func initializeGlobals(confMap conf.ConfMap, fissionErrChan chan error) (err err if nil != err { logFatal(err) } + globals.config.FUSENameLenMax, err = confMap.FetchOptionValueUint32("ICLIENT", "FUSENameLenMax") + if nil != err { + logFatal(err) + } globals.config.AuthPlugInPath, err = confMap.FetchOptionValueString("ICLIENT", "AuthPlugInPath") if nil != err { logFatal(err) @@ -562,6 +567,7 @@ func uninitializeGlobals() (err error) { globals.config.FUSEMaxWrite = 0 globals.config.FUSEEntryValidDuration = time.Duration(0) globals.config.FUSEAttrValidDuration = time.Duration(0) + globals.config.FUSENameLenMax = 0 globals.config.AuthPlugInPath = "" globals.config.AuthPlugInEnvName = "" globals.config.AuthPlugInEnvValue = "" diff --git a/iclient/iclientpkg/utils_test.go b/iclient/iclientpkg/utils_test.go index b831c233..52b588a7 100644 --- a/iclient/iclientpkg/utils_test.go +++ b/iclient/iclientpkg/utils_test.go @@ -141,6 +141,7 @@ func testSetup(t *testing.T) { "ICLIENT.FUSEMaxWrite=1048576", "ICLIENT.FUSEEntryValidDuration=250ms", "ICLIENT.FUSEAttrValidDuration=250ms", + "ICLIENT.FUSENameLenMax=1024", "ICLIENT.AuthPlugInPath=../../iauth/iauth-swift/iauth-swift.so", "ICLIENT.AuthPlugInEnvName=", "ICLIENT.AuthPlugInEnvValue=" + fmt.Sprintf("{\"AuthURL\":\"http://%s:%d/auth/v1.0\"\\u002C\"AuthUser\":\"%s\"\\u002C\"AuthKey\":\"%s\"\\u002C\"Account\":\"%s\"\\u002C\"Container\":\"%s\"}", testIPAddr, testSwiftProxyTCPPort, testSwiftAuthUser, testSwiftAuthKey, testAccount, testContainer), From 10aeb25b655805b5a503674a9659fabbfdb7a2ec Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Mon, 21 Mar 2022 15:29:11 -0700 Subject: [PATCH 02/11] Let's try a more traditional value (255) for FUSENameLenMax --- iclient/dev.conf | 2 +- iclient/iclient.conf | 2 +- iclient/iclientpkg/api.go | 2 +- iclient/iclientpkg/utils_test.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/iclient/dev.conf b/iclient/dev.conf index a61e4f6b..b1012c88 100644 --- a/iclient/dev.conf +++ b/iclient/dev.conf @@ -13,7 +13,7 @@ FUSEMaxRead: 1048576 FUSEMaxWrite: 1048576 FUSEEntryValidDuration: 250ms FUSEAttrValidDuration: 250ms -FUSENameLenMax: 1024 +FUSENameLenMax: 255 AuthPlugInPath: iauth/iauth-swift/iauth-swift.so AuthPlugInEnvName: AuthPlugInEnvValue: {"AuthURL":"http://swift:8080/auth/v1.0"\u002C"AuthUser":"test:tester"\u002C"AuthKey":"testing"\u002C"Account":"AUTH_test"\u002C"Container":"con"} diff --git a/iclient/iclient.conf b/iclient/iclient.conf index 381d8034..a2f88a59 100644 --- a/iclient/iclient.conf +++ b/iclient/iclient.conf @@ -13,7 +13,7 @@ FUSEMaxRead: 1048576 FUSEMaxWrite: 1048576 FUSEEntryValidDuration: 250ms FUSEAttrValidDuration: 250ms -FUSENameLenMax: 1024 +FUSENameLenMax: 255 AuthPlugInPath: iauth-swift.so AuthPlugInEnvName: AuthPlugInEnvValue: {"AuthURL":"http://swift:8080/auth/v1.0"\u002C"AuthUser":"test:tester"\u002C"AuthKey":"testing"\u002C"Account":"AUTH_test"\u002C"Container":"con"} diff --git a/iclient/iclientpkg/api.go b/iclient/iclientpkg/api.go index 956049cb..2ca80da8 100644 --- a/iclient/iclientpkg/api.go +++ b/iclient/iclientpkg/api.go @@ -19,7 +19,7 @@ // FUSEMaxWrite: 1048576 # 1MiB == FUSEMaxPages(256) * 4KiB // FUSEEntryValidDuration: 250ms // FUSEAttrValidDuration: 250ms -// FUSENameLenMax: 1024 +// FUSENameLenMax: 255 // AuthPlugInPath: iauth-swift.so // AuthPlugInEnvName: # Only used if not defining AuthPlugInEnvValue here // AuthPlugInEnvValue: {"AuthURL":"http://swift:8080/auth/v1.0"\u002C"AuthUser":"test:tester"\u002C"AuthKey":"testing"\u002C"Account":"AUTH_test"\u002C"Container":"con"} diff --git a/iclient/iclientpkg/utils_test.go b/iclient/iclientpkg/utils_test.go index 52b588a7..bfeee432 100644 --- a/iclient/iclientpkg/utils_test.go +++ b/iclient/iclientpkg/utils_test.go @@ -141,7 +141,7 @@ func testSetup(t *testing.T) { "ICLIENT.FUSEMaxWrite=1048576", "ICLIENT.FUSEEntryValidDuration=250ms", "ICLIENT.FUSEAttrValidDuration=250ms", - "ICLIENT.FUSENameLenMax=1024", + "ICLIENT.FUSENameLenMax=255", "ICLIENT.AuthPlugInPath=../../iauth/iauth-swift/iauth-swift.so", "ICLIENT.AuthPlugInEnvName=", "ICLIENT.AuthPlugInEnvValue=" + fmt.Sprintf("{\"AuthURL\":\"http://%s:%d/auth/v1.0\"\\u002C\"AuthUser\":\"%s\"\\u002C\"AuthKey\":\"%s\"\\u002C\"Account\":\"%s\"\\u002C\"Container\":\"%s\"}", testIPAddr, testSwiftProxyTCPPort, testSwiftAuthUser, testSwiftAuthKey, testAccount, testContainer), From 4655d79247387f9d420631fd8e59f2f3dd1de4d5 Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Mon, 21 Mar 2022 16:03:39 -0700 Subject: [PATCH 03/11] Allow DoSymLink symLinkIn.Data length to exceed FUSENameLenMax --- iclient/iclientpkg/fission.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iclient/iclientpkg/fission.go b/iclient/iclientpkg/fission.go index c795c877..a7aeb2cb 100644 --- a/iclient/iclientpkg/fission.go +++ b/iclient/iclientpkg/fission.go @@ -504,7 +504,9 @@ func (dummy *globalsStruct) DoSymLink(inHeader *fission.InHeader, symLinkIn *fis globals.stats.DoSymLinkUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if (len(symLinkIn.Name) > int(globals.config.FUSENameLenMax)) || (len(symLinkIn.Data) > int(globals.config.FUSENameLenMax)) { + // TODO: Resolve why some (e.g. PJDFSTEST) tests insist .Data length should not be checked + + if len(symLinkIn.Name) > int(globals.config.FUSENameLenMax) { symLinkOut = nil errno = syscall.ENAMETOOLONG return From 3fcf69d3e05490ee4bec931ff0a39b21e0bc52fc Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Wed, 23 Mar 2022 16:28:10 -0700 Subject: [PATCH 04/11] Fix removal of ".." reference from oldDir when renaming subdir out of oldDir --- iclient/iclientpkg/fission.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iclient/iclientpkg/fission.go b/iclient/iclientpkg/fission.go index a7aeb2cb..2b6cdd0f 100644 --- a/iclient/iclientpkg/fission.go +++ b/iclient/iclientpkg/fission.go @@ -4085,7 +4085,7 @@ Retry: delete(oldDirInode.linkSet, ilayout.InodeLinkTableEntryStruct{ ParentDirInodeNumber: renamedInode.inodeNumber, - ParentDirEntryName: oldName, + ParentDirEntryName: "..", }) ok, err = oldDirInode.payload.DeleteByKey(oldName) From 6e72a02dee5151e2f2719effa28f01bddc23cc8d Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Fri, 25 Mar 2022 13:59:20 -0700 Subject: [PATCH 05/11] Return ENOTEMPTY on renaming dir over top of non-empty dir --- iclient/iclientpkg/fission.go | 331 ++++++++++++++-------------------- 1 file changed, 137 insertions(+), 194 deletions(-) diff --git a/iclient/iclientpkg/fission.go b/iclient/iclientpkg/fission.go index 2b6cdd0f..06b0e374 100644 --- a/iclient/iclientpkg/fission.go +++ b/iclient/iclientpkg/fission.go @@ -4,6 +4,7 @@ package iclientpkg import ( + "bytes" "container/list" "fmt" "math" @@ -98,9 +99,9 @@ func (dummy *globalsStruct) DoLookup(inHeader *fission.InHeader, lookupIn *fissi globals.stats.DoLookupUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if len(lookupIn.Name) > int(globals.config.FUSENameLenMax) { + errno = checkName(lookupIn.Name) + if errno != 0 { lookupOut = nil - errno = syscall.ENAMETOOLONG return } @@ -125,10 +126,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - lookupOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -142,10 +140,7 @@ Retry: if nil == inode.payload { err = inode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - lookupOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.oldPayload() failed: %v", err) } } @@ -250,10 +245,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - getAttrOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -331,10 +323,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - setAttrOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -456,10 +445,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - readLinkOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -506,9 +492,9 @@ func (dummy *globalsStruct) DoSymLink(inHeader *fission.InHeader, symLinkIn *fis // TODO: Resolve why some (e.g. PJDFSTEST) tests insist .Data length should not be checked - if len(symLinkIn.Name) > int(globals.config.FUSENameLenMax) { + errno = checkName(symLinkIn.Name) + if errno != 0 { symLinkOut = nil - errno = syscall.ENAMETOOLONG return } @@ -533,20 +519,14 @@ Retry: if nil == dirInode.inodeHeadV1 { err = dirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - symLinkOut = nil - errno = syscall.ENOENT - return + logFatalf("dirInode.populateInodeHeadV1() failed: %v", err) } } if dirInode.payload == nil { err = dirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - symLinkOut = nil - errno = syscall.ENOENT - return + logFatalf("dirInode.oldPayload() failed: %v", err) } } @@ -716,9 +696,9 @@ func (dummy *globalsStruct) DoMkDir(inHeader *fission.InHeader, mkDirIn *fission globals.stats.DoMkDirUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if len(mkDirIn.Name) > int(globals.config.FUSENameLenMax) { + errno = checkName(mkDirIn.Name) + if errno != 0 { mkDirOut = nil - errno = syscall.ENAMETOOLONG return } @@ -743,20 +723,14 @@ Retry: if nil == parentDirInode.inodeHeadV1 { err = parentDirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - mkDirOut = nil - errno = syscall.ENOENT - return + logFatalf("parentDirInode.populateInodeHeadV1() failed: %v", err) } } if parentDirInode.payload == nil { err = parentDirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - mkDirOut = nil - errno = syscall.ENOENT - return + logFatalf("parentDirInode.oldPayload() failed: %v", err) } } @@ -951,8 +925,8 @@ func (dummy *globalsStruct) DoUnlink(inHeader *fission.InHeader, unlinkIn *fissi globals.stats.DoUnlinkUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if len(unlinkIn.Name) > int(globals.config.FUSENameLenMax) { - errno = syscall.ENAMETOOLONG + errno = checkName(unlinkIn.Name) + if errno != 0 { return } @@ -976,9 +950,7 @@ Retry: if nil == dirInode.inodeHeadV1 { err = dirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("dirInode.populateInodeHeadV1() failed: %v", err) } } @@ -991,9 +963,7 @@ Retry: if dirInode.payload == nil { err = dirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("dirInode.oldPayload() failed: %v", err) } } @@ -1030,9 +1000,7 @@ Retry: if nil == targetInode.inodeHeadV1 { err = targetInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("targetInode.populateInodeHeadV1() failed: %v", err) } } @@ -1110,8 +1078,8 @@ func (dummy *globalsStruct) DoRmDir(inHeader *fission.InHeader, rmDirIn *fission globals.stats.DoRmDirUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if len(rmDirIn.Name) > int(globals.config.FUSENameLenMax) { - errno = syscall.ENAMETOOLONG + errno = checkName(rmDirIn.Name) + if errno != 0 { return } @@ -1135,9 +1103,7 @@ Retry: if nil == parentDirInode.inodeHeadV1 { err = parentDirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("parentDirInode.populateInodeHeadV1() failed: %v", err) } } @@ -1150,9 +1116,7 @@ Retry: if parentDirInode.payload == nil { err = parentDirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("parentDirInode.oldPayload() failed: %v", err) } } @@ -1189,9 +1153,7 @@ Retry: if nil == childDirInode.inodeHeadV1 { err = childDirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("childDirInode.populateInodeHeadV1() failed: %v", err) } } @@ -1204,9 +1166,7 @@ Retry: if childDirInode.payload == nil { err = childDirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("childDirInode.oldPayload() failed: %v", err) } } @@ -1271,8 +1231,12 @@ func (dummy *globalsStruct) DoRename(inHeader *fission.InHeader, renameIn *fissi globals.stats.DoRenameUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if (len(renameIn.OldName) > int(globals.config.FUSENameLenMax)) || (len(renameIn.NewName) > int(globals.config.FUSENameLenMax)) { - errno = syscall.ENAMETOOLONG + errno = checkName(renameIn.OldName) + if errno != 0 { + return + } + errno = checkName(renameIn.NewName) + if errno != 0 { return } @@ -1299,9 +1263,9 @@ func (dummy *globalsStruct) DoLink(inHeader *fission.InHeader, linkIn *fission.L globals.stats.DoLinkUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if len(linkIn.Name) > int(globals.config.FUSENameLenMax) { + errno = checkName(linkIn.Name) + if errno != 0 { linkOut = nil - errno = syscall.ENAMETOOLONG return } @@ -1326,10 +1290,7 @@ Retry: if nil == dirInode.inodeHeadV1 { err = dirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - linkOut = nil - errno = syscall.ENOENT - return + logFatalf("dirInode.populateInodeHeadV1() failed: %v", err) } } @@ -1343,10 +1304,7 @@ Retry: if dirInode.payload == nil { err = dirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - linkOut = nil - errno = syscall.ENOENT - return + logFatalf("dirInode.oldPayload() failed: %v", err) } } @@ -1478,10 +1436,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - openOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -1619,10 +1574,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - readOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -1675,13 +1627,13 @@ Retry: if nil == inode.payload { err = inode.oldPayload() if nil != err { - logFatal(err) + logFatalf("inode.oldPayload() failed: %v", err) } } extentMapEntryIndexV1, _, err = inode.payload.BisectLeft(curOffset) if nil != err { - logFatal(err) + logFatalf("inode.payload.BisectLeft(curOffset) failed: %v", err) } if extentMapEntryIndexV1 < 0 { // Correct for case where curOffset is to the left of the first extent @@ -2040,10 +1992,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - writeOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2224,9 +2173,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2311,9 +2258,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2371,9 +2316,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2455,10 +2398,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - getXAttrOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2543,10 +2483,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - listXAttrOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2629,9 +2566,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2754,10 +2689,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - openDirOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2856,10 +2788,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - readDirOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -2873,10 +2802,7 @@ Retry: if nil == inode.payload { err = inode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - readDirOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.oldPayload() failed: %v", err) } } @@ -3004,9 +2930,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -3155,9 +3079,9 @@ func (dummy *globalsStruct) DoCreate(inHeader *fission.InHeader, createIn *fissi globals.stats.DoCreateUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if len(createIn.Name) > int(globals.config.FUSENameLenMax) { + errno = checkName(createIn.Name) + if errno != 0 { createOut = nil - errno = syscall.ENAMETOOLONG return } @@ -3182,10 +3106,7 @@ Retry: if nil == dirInode.inodeHeadV1 { err = dirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - createOut = nil - errno = syscall.ENOENT - return + logFatalf("dirInode.populateInodeHeadV1() failed: %v", err) } } @@ -3199,10 +3120,7 @@ Retry: if dirInode.payload == nil { err = dirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - createOut = nil - errno = syscall.ENOENT - return + logFatalf("dirInode.oldPayload() failed: %v", err) } } @@ -3549,10 +3467,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - readDirPlusOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -3566,10 +3481,7 @@ Retry: if nil == inode.payload { err = inode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - readDirPlusOut = nil - errno = syscall.ENOENT - return + logFatalf("inode.oldPayload() failed: %v", err) } } @@ -3689,8 +3601,12 @@ func (dummy *globalsStruct) DoRename2(inHeader *fission.InHeader, rename2In *fis globals.stats.DoRename2Usecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - if (len(rename2In.OldName) > int(globals.config.FUSENameLenMax)) || (len(rename2In.NewName) > int(globals.config.FUSENameLenMax)) { - errno = syscall.ENAMETOOLONG + errno = checkName(rename2In.OldName) + if errno != 0 { + return + } + errno = checkName(rename2In.NewName) + if errno != 0 { return } @@ -3793,9 +3709,7 @@ Retry: if nil == inode.inodeHeadV1 { err = inode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - err = fmt.Errorf("inode.populateInodeHeadV1() failed: %v", err) - return + logFatalf("inode.populateInodeHeadV1() failed: %v", err) } } @@ -3850,6 +3764,20 @@ func fixAttrSizes(attr *fission.Attr) { } } +func checkName(name []byte) (errno syscall.Errno) { + if bytes.Compare(name, []byte{'.'}) == 0 { + errno = syscall.EINVAL + } else if bytes.Compare(name, []byte{'.', '.'}) == 0 { + errno = syscall.EINVAL + } else if len(name) > int(globals.config.FUSENameLenMax) { + errno = syscall.ENAMETOOLONG + } else { + errno = 0 + } + + return +} + func doRenameCommon(oldDirInodeNumber uint64, oldName string, newDirInodeNumber uint64, newName string, startTime time.Time) (errno syscall.Errno) { var ( deleteInodeTableEntryRequest *imgrpkg.DeleteInodeTableEntryRequestStruct @@ -3863,6 +3791,7 @@ func doRenameCommon(oldDirInodeNumber uint64, oldName string, newDirInodeNumber oldDirInode *inodeStruct renamedInode *inodeStruct replacedInode *inodeStruct + replacedInodePayloadLen int ) Retry: @@ -3885,9 +3814,7 @@ Retry: if nil == oldDirInode.inodeHeadV1 { err = oldDirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("oldDirInode.populateInodeHeadV1() failed: %v", err) } } @@ -3900,9 +3827,7 @@ Retry: if oldDirInode.payload == nil { err = oldDirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("oldDirInode.oldPayload() failed: %v", err) } } @@ -3938,9 +3863,7 @@ Retry: if nil == renamedInode.inodeHeadV1 { err = renamedInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("renamedInode.populateInodeHeadV1() failed: %v", err) } } @@ -3976,18 +3899,14 @@ Retry: if nil == newDirInode.inodeHeadV1 { err = newDirInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("newDirInode.populateInodeHeadV1() failed: %v", err) } } if newDirInode.payload == nil { err = newDirInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("newDirInode.oldPayload() failed: %v", err) } } } @@ -4020,15 +3939,39 @@ Retry: if nil == replacedInode.inodeHeadV1 { err = replacedInode.populateInodeHeadV1() if nil != err { - inodeLockRequest.unlockAll() - goto Retry + logFatalf("replacedInode.populateInodeHeadV1() failed: %v", err) } } - if replacedInode.inodeHeadV1.InodeType == ilayout.InodeTypeDir { - inodeLockRequest.unlockAll() - errno = syscall.EISDIR - return + if renamedInode.inodeHeadV1.InodeType == ilayout.InodeTypeDir { + if replacedInode.inodeHeadV1.InodeType == ilayout.InodeTypeDir { + if replacedInode.payload == nil { + err = replacedInode.oldPayload() + if nil != err { + logFatalf("replacedInode.oldPayload() failed: %v", err) + } + } + + replacedInodePayloadLen, err = replacedInode.payload.Len() + if nil != err { + logFatalf("replacedInode.payload.Len() failed: %v", err) + } + if replacedInodePayloadLen != 2 { + inodeLockRequest.unlockAll() + errno = syscall.ENOTEMPTY + return + } + } else { // replacedInode.inodeHeadV1.InodeType != ilayout.InodeTypeDir + inodeLockRequest.unlockAll() + errno = syscall.ENOTDIR + return + } + } else { // renamedInode.inodeHeadV1.InodeType != ilayout.InodeTypeDir + if replacedInode.inodeHeadV1.InodeType == ilayout.InodeTypeDir { + inodeLockRequest.unlockAll() + errno = syscall.EISDIR + return + } } } else { replacedInode = nil @@ -4036,6 +3979,8 @@ Retry: if renamedInode.inodeHeadV1.InodeType == ilayout.InodeTypeDir { if replacedInode != nil { + logWarnf("TODO: must do the equivalent of rmdir() here...") + inodeLockRequest.unlockAll() errno = syscall.EISDIR return @@ -4044,9 +3989,7 @@ Retry: if renamedInode.payload == nil { err = renamedInode.oldPayload() if nil != err { - inodeLockRequest.unlockAll() - errno = syscall.ENOENT - return + logFatalf("renamedInode.oldPayload() failed: %v", err) } } @@ -4118,18 +4061,8 @@ Retry: if !ok { logFatalf("newDirInode.payload.Put(newName,) returned !ok") } - } else { - if replacedInode != nil { - replacedInode.dirty = true - - replacedInode.inodeHeadV1.ModificationTime = startTime - replacedInode.inodeHeadV1.StatusChangeTime = startTime - - delete(replacedInode.linkSet, ilayout.InodeLinkTableEntryStruct{ - ParentDirInodeNumber: newDirInodeNumber, - ParentDirEntryName: newName, - }) - + } else { // renamedInode.inodeHeadV1.InodeType != ilayout.InodeTypeDir + if replacedInode == nil { renamedInode.dirty = true renamedInode.inodeHeadV1.ModificationTime = startTime @@ -4163,19 +4096,29 @@ Retry: newDirInode.inodeHeadV1.ModificationTime = startTime newDirInode.inodeHeadV1.StatusChangeTime = startTime - ok, err = newDirInode.payload.PatchByKey( + ok, err = newDirInode.payload.Put( newName, &ilayout.DirectoryEntryValueV1Struct{ InodeNumber: renamedInode.inodeNumber, InodeType: ilayout.InodeTypeDir, }) if nil != err { - logFatalf("newDirInode.payload.PatchByKey(newName,) failed: %v", err) + logFatalf("newDirInode.payload.Put(newName,) failed: %v", err) } if !ok { - logFatalf("newDirInode.payload.PatchByKey(newName,) returned !ok") + logFatalf("newDirInode.payload.Put(newName,) returned !ok") } - } else { + } else { // replacedInode != nil + replacedInode.dirty = true + + replacedInode.inodeHeadV1.ModificationTime = startTime + replacedInode.inodeHeadV1.StatusChangeTime = startTime + + delete(replacedInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: newDirInodeNumber, + ParentDirEntryName: newName, + }) + renamedInode.dirty = true renamedInode.inodeHeadV1.ModificationTime = startTime @@ -4209,17 +4152,17 @@ Retry: newDirInode.inodeHeadV1.ModificationTime = startTime newDirInode.inodeHeadV1.StatusChangeTime = startTime - ok, err = newDirInode.payload.Put( + ok, err = newDirInode.payload.PatchByKey( newName, &ilayout.DirectoryEntryValueV1Struct{ InodeNumber: renamedInode.inodeNumber, InodeType: ilayout.InodeTypeDir, }) if nil != err { - logFatalf("newDirInode.payload.Put(newName,) failed: %v", err) + logFatalf("newDirInode.payload.PatchByKey(newName,) failed: %v", err) } if !ok { - logFatalf("newDirInode.payload.Put(newName,) returned !ok") + logFatalf("newDirInode.payload.PatchByKey(newName,) returned !ok") } } } From d43b29dd17edc4b6beee06957082825825286c73 Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Fri, 25 Mar 2022 14:50:17 -0700 Subject: [PATCH 06/11] Return 0 (OK) on renaming dir over top of empty dir --- iclient/iclientpkg/fission.go | 214 ++++++++++++++++++++++++---------- 1 file changed, 151 insertions(+), 63 deletions(-) diff --git a/iclient/iclientpkg/fission.go b/iclient/iclientpkg/fission.go index 06b0e374..00d6c460 100644 --- a/iclient/iclientpkg/fission.go +++ b/iclient/iclientpkg/fission.go @@ -3978,88 +3978,176 @@ Retry: } if renamedInode.inodeHeadV1.InodeType == ilayout.InodeTypeDir { - if replacedInode != nil { - logWarnf("TODO: must do the equivalent of rmdir() here...") + if replacedInode == nil { + if renamedInode.payload == nil { + err = renamedInode.oldPayload() + if nil != err { + logFatalf("renamedInode.oldPayload() failed: %v", err) + } + } - inodeLockRequest.unlockAll() - errno = syscall.EISDIR - return - } + renamedInode.dirty = true - if renamedInode.payload == nil { - err = renamedInode.oldPayload() + renamedInode.inodeHeadV1.ModificationTime = startTime + renamedInode.inodeHeadV1.StatusChangeTime = startTime + + delete(renamedInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: oldDirInodeNumber, + ParentDirEntryName: oldName, + }) + + renamedInode.linkSet[ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: newDirInodeNumber, + ParentDirEntryName: newName, + }] = struct{}{} + + ok, err = renamedInode.payload.PatchByKey( + "..", + &ilayout.DirectoryEntryValueV1Struct{ + InodeNumber: newDirInodeNumber, + InodeType: ilayout.InodeTypeDir, + }) if nil != err { - logFatalf("renamedInode.oldPayload() failed: %v", err) + logFatalf("renamedInode.payload.PatchByKey(\"..\",) failed: %v", err) + } + if !ok { + logFatalf("renamedInode.payload.PatchByKey(\"..\",) returned !ok") } - } - renamedInode.dirty = true + oldDirInode.dirty = true - renamedInode.inodeHeadV1.ModificationTime = startTime - renamedInode.inodeHeadV1.StatusChangeTime = startTime + oldDirInode.inodeHeadV1.ModificationTime = startTime + oldDirInode.inodeHeadV1.StatusChangeTime = startTime - delete(renamedInode.linkSet, ilayout.InodeLinkTableEntryStruct{ - ParentDirInodeNumber: oldDirInodeNumber, - ParentDirEntryName: oldName, - }) + delete(oldDirInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: renamedInode.inodeNumber, + ParentDirEntryName: "..", + }) - renamedInode.linkSet[ilayout.InodeLinkTableEntryStruct{ - ParentDirInodeNumber: newDirInodeNumber, - ParentDirEntryName: newName, - }] = struct{}{} + ok, err = oldDirInode.payload.DeleteByKey(oldName) + if nil != err { + logFatalf("oldDirInode.payload.DeleteByKey(oldName) failed: %v", err) + } + if !ok { + logFatalf("oldDirInode.payload.DeleteByKey(oldName) returned !ok") + } - ok, err = renamedInode.payload.PatchByKey( - "..", - &ilayout.DirectoryEntryValueV1Struct{ - InodeNumber: newDirInodeNumber, - InodeType: ilayout.InodeTypeDir, + newDirInode.dirty = true + + newDirInode.inodeHeadV1.ModificationTime = startTime + newDirInode.inodeHeadV1.StatusChangeTime = startTime + + newDirInode.linkSet[ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: renamedInode.inodeNumber, + ParentDirEntryName: "..", + }] = struct{}{} + + ok, err = newDirInode.payload.Put( + newName, + &ilayout.DirectoryEntryValueV1Struct{ + InodeNumber: renamedInode.inodeNumber, + InodeType: ilayout.InodeTypeDir, + }) + if nil != err { + logFatalf("newDirInode.payload.Put(newName,) failed: %v", err) + } + if !ok { + logFatalf("newDirInode.payload.Put(newName,) returned !ok") + } + } else { // replacedInode != nil + replacedInode.dirty = true + + replacedInode.inodeHeadV1.ModificationTime = startTime + replacedInode.inodeHeadV1.StatusChangeTime = startTime + + delete(replacedInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: replacedInode.inodeNumber, + ParentDirEntryName: ".", + }) + delete(replacedInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: newDirInodeNumber, + ParentDirEntryName: newName, }) - if nil != err { - logFatalf("renamedInode.payload.PatchByKey(\"..\",) failed: %v", err) - } - if !ok { - logFatalf("renamedInode.payload.PatchByKey(\"..\",) returned !ok") - } - oldDirInode.dirty = true + if renamedInode.payload == nil { + err = renamedInode.oldPayload() + if nil != err { + logFatalf("renamedInode.oldPayload() failed: %v", err) + } + } - oldDirInode.inodeHeadV1.ModificationTime = startTime - oldDirInode.inodeHeadV1.StatusChangeTime = startTime + renamedInode.dirty = true - delete(oldDirInode.linkSet, ilayout.InodeLinkTableEntryStruct{ - ParentDirInodeNumber: renamedInode.inodeNumber, - ParentDirEntryName: "..", - }) + renamedInode.inodeHeadV1.ModificationTime = startTime + renamedInode.inodeHeadV1.StatusChangeTime = startTime - ok, err = oldDirInode.payload.DeleteByKey(oldName) - if nil != err { - logFatalf("oldDirInode.payload.DeleteByKey(oldName) failed: %v", err) - } - if !ok { - logFatalf("oldDirInode.payload.DeleteByKey(oldName) returned !ok") - } + delete(renamedInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: oldDirInodeNumber, + ParentDirEntryName: oldName, + }) - newDirInode.dirty = true + renamedInode.linkSet[ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: newDirInodeNumber, + ParentDirEntryName: newName, + }] = struct{}{} - newDirInode.inodeHeadV1.ModificationTime = startTime - newDirInode.inodeHeadV1.StatusChangeTime = startTime + ok, err = renamedInode.payload.PatchByKey( + "..", + &ilayout.DirectoryEntryValueV1Struct{ + InodeNumber: newDirInodeNumber, + InodeType: ilayout.InodeTypeDir, + }) + if nil != err { + logFatalf("renamedInode.payload.PatchByKey(\"..\",) failed: %v", err) + } + if !ok { + logFatalf("renamedInode.payload.PatchByKey(\"..\",) returned !ok") + } - newDirInode.linkSet[ilayout.InodeLinkTableEntryStruct{ - ParentDirInodeNumber: renamedInode.inodeNumber, - ParentDirEntryName: "..", - }] = struct{}{} + oldDirInode.dirty = true - ok, err = newDirInode.payload.Put( - newName, - &ilayout.DirectoryEntryValueV1Struct{ - InodeNumber: renamedInode.inodeNumber, - InodeType: ilayout.InodeTypeDir, + oldDirInode.inodeHeadV1.ModificationTime = startTime + oldDirInode.inodeHeadV1.StatusChangeTime = startTime + + delete(oldDirInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: renamedInode.inodeNumber, + ParentDirEntryName: "..", }) - if nil != err { - logFatalf("newDirInode.payload.Put(newName,) failed: %v", err) - } - if !ok { - logFatalf("newDirInode.payload.Put(newName,) returned !ok") + + ok, err = oldDirInode.payload.DeleteByKey(oldName) + if nil != err { + logFatalf("oldDirInode.payload.DeleteByKey(oldName) failed: %v", err) + } + if !ok { + logFatalf("oldDirInode.payload.DeleteByKey(oldName) returned !ok") + } + + newDirInode.dirty = true + + newDirInode.inodeHeadV1.ModificationTime = startTime + newDirInode.inodeHeadV1.StatusChangeTime = startTime + + delete(newDirInode.linkSet, ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: replacedInode.inodeNumber, + ParentDirEntryName: "..", + }) + newDirInode.linkSet[ilayout.InodeLinkTableEntryStruct{ + ParentDirInodeNumber: renamedInode.inodeNumber, + ParentDirEntryName: "..", + }] = struct{}{} + + ok, err = newDirInode.payload.PatchByKey( + newName, + &ilayout.DirectoryEntryValueV1Struct{ + InodeNumber: renamedInode.inodeNumber, + InodeType: ilayout.InodeTypeDir, + }) + if nil != err { + logFatalf("newDirInode.payload.PatchByKey(newName,) failed: %v", err) + } + if !ok { + logFatalf("newDirInode.payload.PatchByKey(newName,) returned !ok") + } } } else { // renamedInode.inodeHeadV1.InodeType != ilayout.InodeTypeDir if replacedInode == nil { From 963136a154f652290adc5ab28dc3b8e4a80eefac Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Tue, 29 Mar 2022 11:08:17 -0700 Subject: [PATCH 07/11] Fixed mishandling of O_TRUNC on DoOpen() calls in iclientpkg --- iclient/iclientpkg/fission.go | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/iclient/iclientpkg/fission.go b/iclient/iclientpkg/fission.go index 00d6c460..49448559 100644 --- a/iclient/iclientpkg/fission.go +++ b/iclient/iclientpkg/fission.go @@ -354,6 +354,7 @@ Retry: if (setAttrIn.Valid & fission.SetAttrInValidSize) != 0 { if setAttrIn.Size != inode.inodeHeadV1.Size { inode.dirty = true + inode.inodeHeadV1.ModificationTime = startTime if setAttrIn.Size < inode.inodeHeadV1.Size { @@ -366,6 +367,7 @@ Retry: inode.unmapExtent(setAttrIn.Size, 0) } + inode.inodeHeadV1.Size = setAttrIn.Size } } @@ -1399,6 +1401,7 @@ func (dummy *globalsStruct) DoOpen(inHeader *fission.InHeader, openIn *fission.O err error inode *inodeStruct inodeLockRequest *inodeLockRequestStruct + inodeToBeModified bool openHandle *openHandleStruct startTime time.Time = time.Now() ) @@ -1412,13 +1415,28 @@ func (dummy *globalsStruct) DoOpen(inHeader *fission.InHeader, openIn *fission.O globals.stats.DoOpenUsecs.Add(uint64(time.Since(startTime) / time.Microsecond)) }() - // TODO: Validate simply ignoring openIn.Flags containing fission.FOpenRequestEXCL is ok - // TODO: Need to handle openIn.Flags containing fission.FOpenRequestCREAT + switch openIn.Flags & syscall.O_ACCMODE { + case fission.FOpenRequestRDONLY: + if (openIn.Flags & fission.FOpenRequestTRUNC) == fission.FOpenRequestTRUNC { + openOut = nil + errno = syscall.EACCES + return + } + inodeToBeModified = false + case fission.FOpenRequestWRONLY: + inodeToBeModified = ((openIn.Flags & fission.FOpenRequestTRUNC) == fission.FOpenRequestTRUNC) + case fission.FOpenRequestRDWR: + inodeToBeModified = ((openIn.Flags & fission.FOpenRequestTRUNC) == fission.FOpenRequestTRUNC) + default: + openOut = nil + errno = syscall.EACCES + return + } Retry: inodeLockRequest = newLockRequest() inodeLockRequest.inodeNumber = inHeader.NodeID - inodeLockRequest.exclusive = false + inodeLockRequest.exclusive = inodeToBeModified inodeLockRequest.addThisLock() if len(inodeLockRequest.locksHeld) == 0 { performInodeLockRetryDelay() @@ -1455,7 +1473,16 @@ Retry: } } + inode.dirty = true + + inode.inodeHeadV1.ModificationTime = startTime + inode.inodeHeadV1.StatusChangeTime = startTime + inode.unmapExtent(0, 0) + + inode.inodeHeadV1.Size = 0 + + flushInodesInSlice([]*inodeStruct{inode}) } adjustInodeTableEntryOpenCountRequest = &imgrpkg.AdjustInodeTableEntryOpenCountRequestStruct{ From 5da753772ee4ee109a504cc3b6a93d83d6eb3fe8 Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Tue, 29 Mar 2022 11:53:23 -0700 Subject: [PATCH 08/11] Return expected EINVAL on bad FACCESS bit combo in DoOpen() --- iclient/iclientpkg/fission.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iclient/iclientpkg/fission.go b/iclient/iclientpkg/fission.go index 49448559..6de5f71c 100644 --- a/iclient/iclientpkg/fission.go +++ b/iclient/iclientpkg/fission.go @@ -1419,7 +1419,7 @@ func (dummy *globalsStruct) DoOpen(inHeader *fission.InHeader, openIn *fission.O case fission.FOpenRequestRDONLY: if (openIn.Flags & fission.FOpenRequestTRUNC) == fission.FOpenRequestTRUNC { openOut = nil - errno = syscall.EACCES + errno = syscall.EINVAL return } inodeToBeModified = false @@ -1429,7 +1429,7 @@ func (dummy *globalsStruct) DoOpen(inHeader *fission.InHeader, openIn *fission.O inodeToBeModified = ((openIn.Flags & fission.FOpenRequestTRUNC) == fission.FOpenRequestTRUNC) default: openOut = nil - errno = syscall.EACCES + errno = syscall.EINVAL return } From b00f4d7f7649111b57b84b00bb976a9a384ec6dd Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Tue, 5 Apr 2022 10:33:24 -0700 Subject: [PATCH 09/11] Impose cap on number of mounts enabled by imgr --- iclient/iclientpkg/utils_test.go | 1 + imgr/dev.conf | 1 + imgr/imgr.conf | 1 + imgr/imgrpkg/api.go | 4 ++-- imgr/imgrpkg/globals.go | 9 ++++++- imgr/imgrpkg/lease.go | 32 +++++++++++++++---------- imgr/imgrpkg/retry-rpc.go | 35 +++++++++++++++++---------- imgr/imgrpkg/utils_test.go | 1 + imgr/imgrpkg/volume.go | 41 ++++++++++++++++++++++---------- 9 files changed, 85 insertions(+), 40 deletions(-) diff --git a/iclient/iclientpkg/utils_test.go b/iclient/iclientpkg/utils_test.go index bfeee432..4e18caa1 100644 --- a/iclient/iclientpkg/utils_test.go +++ b/iclient/iclientpkg/utils_test.go @@ -195,6 +195,7 @@ func testSetup(t *testing.T) { "IMGR.FetchNonceRangeToReturn=100", + "IMGR.MountLimit=10000", "IMGR.OpenFileLimit=100000", "IMGR.MinLeaseDuration=250ms", diff --git a/imgr/dev.conf b/imgr/dev.conf index d223e200..b1567e91 100644 --- a/imgr/dev.conf +++ b/imgr/dev.conf @@ -30,6 +30,7 @@ AuthTokenCheckInterval: 1m FetchNonceRangeToReturn: 100 +MountLimit: 10000 OpenFileLimit: 100000 MinLeaseDuration: 250ms diff --git a/imgr/imgr.conf b/imgr/imgr.conf index 72c723d6..917540ee 100644 --- a/imgr/imgr.conf +++ b/imgr/imgr.conf @@ -30,6 +30,7 @@ AuthTokenCheckInterval: 1m FetchNonceRangeToReturn: 100 +MountLimit: 10000 OpenFileLimit: 100000 MinLeaseDuration: 250ms diff --git a/imgr/imgrpkg/api.go b/imgr/imgrpkg/api.go index 8c55888c..df4d5149 100644 --- a/imgr/imgrpkg/api.go +++ b/imgr/imgrpkg/api.go @@ -43,6 +43,7 @@ // // FetchNonceRangeToReturn: 100 // +// MountLimit: 10000 // OpenFileLimit: 100000 // // MinLeaseDuration: 250ms @@ -198,13 +199,12 @@ const ( EBadOpenCountAdjustment = "EBadOpenCountAdjustment:" ELeaseRequestDenied = "ELeaseRequestDenied:" EMissingLease = "EMissingLease:" + ETooManyMounts = "ETooManyMounts" ETooManyOpens = "ETooManyOpens" EVolumeBeingDeleted = "EVolumeBeingDeleted:" EUnknownInodeNumber = "EUnknownInodeNumber:" EUnknownMountID = "EUnknownMountID:" EUnknownVolumeName = "EUnknownVolumeName:" - - ETODO = "ETODO:" ) type RetryRPCServerStruct struct{} diff --git a/imgr/imgrpkg/globals.go b/imgr/imgrpkg/globals.go index 35666bc6..cb4cb142 100644 --- a/imgr/imgrpkg/globals.go +++ b/imgr/imgrpkg/globals.go @@ -50,6 +50,7 @@ type configStruct struct { FetchNonceRangeToReturn uint64 + MountLimit uint64 OpenFileLimit uint64 MinLeaseDuration time.Duration @@ -220,7 +221,7 @@ type mountStruct struct { volume *volumeStruct // mountID string // retryRPCClientID uint64 // - unmounting bool // + unmountWGList *list.List // if nil, not currently unmounting; if non-nil, elements are *sync.WaitGroup of any unmount waiters leaseRequestMap map[uint64]*leaseRequestStruct // key == leaseRequestStruct.inodeLease.inodeNumber authToken string // lastAuthTime time.Time // used to periodically check TTL of authToken @@ -279,6 +280,7 @@ type globalsStruct struct { inodeLeaseExpirerWG *sync.WaitGroup // != nil means there is an inodeLeaseExpirer running volumeMap sortedmap.LLRBTree // key == volumeStruct.name; value == *volumeStruct mountMap map[string]*mountStruct // key == mountStruct.mountID + unmountsInProgress uint64 // checkPointHTTPClient *http.Client // checkPointURL []string // swiftHTTPClient *http.Client // @@ -557,6 +559,10 @@ func initializeGlobals(confMap conf.ConfMap) (err error) { logFatal(err) } + globals.config.MountLimit, err = confMap.FetchOptionValueUint64("IMGR", "MountLimit") + if nil != err { + logFatal(err) + } globals.config.OpenFileLimit, err = confMap.FetchOptionValueUint64("IMGR", "OpenFileLimit") if nil != err { logFatal(err) @@ -691,6 +697,7 @@ func uninitializeGlobals() (err error) { globals.config.FetchNonceRangeToReturn = 0 + globals.config.MountLimit = 0 globals.config.OpenFileLimit = 0 globals.config.MinLeaseDuration = time.Duration(0) diff --git a/imgr/imgrpkg/lease.go b/imgr/imgrpkg/lease.go index d783737c..200dd1bc 100644 --- a/imgr/imgrpkg/lease.go +++ b/imgr/imgrpkg/lease.go @@ -825,10 +825,12 @@ func (inodeLease *inodeLeaseStruct) handleInterruptTimerPop() { delete(leaseRequest.mount.leaseRequestMap, inodeLease.inodeNumber) - if !leaseRequest.mount.unmounting { - leaseRequest.mount.unmounting = true + if leaseRequest.mount.unmountWGList == nil { + leaseRequest.mount.unmountWGList = list.New() - go leaseRequest.mount.performUnmount(nil) + globals.unmountsInProgress++ + + go leaseRequest.mount.performUnmount() } inodeLease.releasingHoldersList.Remove(leaseRequestElement) @@ -858,10 +860,12 @@ func (inodeLease *inodeLeaseStruct) handleInterruptTimerPop() { delete(leaseRequest.mount.leaseRequestMap, inodeLease.inodeNumber) - if !leaseRequest.mount.unmounting { - leaseRequest.mount.unmounting = true + if leaseRequest.mount.unmountWGList == nil { + leaseRequest.mount.unmountWGList = list.New() + + globals.unmountsInProgress++ - go leaseRequest.mount.performUnmount(nil) + go leaseRequest.mount.performUnmount() } inodeLease.releasingHoldersList.Remove(leaseRequestElement) @@ -898,10 +902,12 @@ func (inodeLease *inodeLeaseStruct) handleInterruptTimerPop() { delete(inodeLease.demotingHolder.mount.leaseRequestMap, inodeLease.inodeNumber) - if !inodeLease.demotingHolder.mount.unmounting { - inodeLease.demotingHolder.mount.unmounting = true + if inodeLease.demotingHolder.mount.unmountWGList == nil { + inodeLease.demotingHolder.mount.unmountWGList = list.New() - go inodeLease.demotingHolder.mount.performUnmount(nil) + globals.unmountsInProgress++ + + go inodeLease.demotingHolder.mount.performUnmount() } inodeLease.demotingHolder = nil @@ -948,10 +954,12 @@ func (inodeLease *inodeLeaseStruct) handleInterruptTimerPop() { delete(leaseRequest.mount.leaseRequestMap, inodeLease.inodeNumber) - if !leaseRequest.mount.unmounting { - leaseRequest.mount.unmounting = true + if leaseRequest.mount.unmountWGList == nil { + leaseRequest.mount.unmountWGList = list.New() + + globals.unmountsInProgress++ - go leaseRequest.mount.performUnmount(nil) + go leaseRequest.mount.performUnmount() } inodeLease.releasingHoldersList.Remove(leaseRequestElement) diff --git a/imgr/imgrpkg/retry-rpc.go b/imgr/imgrpkg/retry-rpc.go index 25ba3da7..c0508f7e 100644 --- a/imgr/imgrpkg/retry-rpc.go +++ b/imgr/imgrpkg/retry-rpc.go @@ -107,6 +107,12 @@ func mount(retryRPCClientID uint64, mountRequest *MountRequestStruct, mountRespo globals.Lock() + if (uint64(len(globals.mountMap)) - globals.unmountsInProgress) >= globals.config.MountLimit { + globals.Unlock() + err = fmt.Errorf("%s", ETooManyMounts) + return + } + volumeAsValue, ok, err = globals.volumeMap.GetByKey(mountRequest.VolumeName) if nil != err { logFatalf("globals.volumeMap.GetByKey() failed: %v", err) @@ -162,7 +168,7 @@ retryGenerateMountID: volume: volume, mountID: mountIDAsString, retryRPCClientID: retryRPCClientID, - unmounting: false, + unmountWGList: nil, leaseRequestMap: make(map[uint64]*leaseRequestStruct), authToken: mountRequest.AuthToken, lastAuthTime: startTime, @@ -244,7 +250,7 @@ func renewMount(renewMountRequest *RenewMountRequestStruct, renewMountResponse * globals.Lock() mount, ok = globals.mountMap[renewMountRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, renewMountRequest.MountID) return @@ -309,17 +315,20 @@ func unmount(unmountRequest *UnmountRequestStruct, unmountResponse *UnmountRespo globals.Lock() mount, ok = globals.mountMap[unmountRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, unmountRequest.MountID) return } - mount.unmounting = true + mount.unmountWGList = list.New() unmountFinishedWG.Add(1) + _ = mount.unmountWGList.PushBack(&unmountFinishedWG) + + globals.unmountsInProgress++ - go mount.performUnmount(&unmountFinishedWG) + go mount.performUnmount() globals.Unlock() @@ -356,7 +365,7 @@ func volumeStatus(volumeStatusRequest *VolumeStatusRequestStruct, volumeStatusRe globals.Lock() mount, ok = globals.mountMap[volumeStatusRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, volumeStatusRequest.MountID) return @@ -403,7 +412,7 @@ func fetchNonceRange(fetchNonceRangeRequest *FetchNonceRangeRequestStruct, fetch globals.Lock() mount, ok = globals.mountMap[fetchNonceRangeRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, fetchNonceRangeRequest.MountID) return @@ -449,7 +458,7 @@ func getInodeTableEntry(getInodeTableEntryRequest *GetInodeTableEntryRequestStru globals.Lock() mount, ok = globals.mountMap[getInodeTableEntryRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, getInodeTableEntryRequest.MountID) return @@ -522,7 +531,7 @@ func putInodeTableEntries(putInodeTableEntriesRequest *PutInodeTableEntriesReque globals.Lock() mount, ok = globals.mountMap[putInodeTableEntriesRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, putInodeTableEntriesRequest.MountID) return @@ -607,7 +616,7 @@ func deleteInodeTableEntry(deleteInodeTableEntryRequest *DeleteInodeTableEntryRe globals.Lock() mount, ok = globals.mountMap[deleteInodeTableEntryRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, deleteInodeTableEntryRequest.MountID) return @@ -670,7 +679,7 @@ func adjustInodeTableEntryOpenCount(adjustInodeTableEntryOpenCountRequest *Adjus globals.Lock() mount, ok = globals.mountMap[adjustInodeTableEntryOpenCountRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, adjustInodeTableEntryOpenCountRequest.MountID) return @@ -790,7 +799,7 @@ func flush(flushRequest *FlushRequestStruct, flushResponse *FlushResponseStruct) globals.Lock() mount, ok = globals.mountMap[flushRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, flushRequest.MountID) return @@ -872,7 +881,7 @@ func lease(leaseRequest *LeaseRequestStruct, leaseResponse *LeaseResponseStruct) globals.Lock() mount, ok = globals.mountMap[leaseRequest.MountID] - if !ok || mount.unmounting { + if !ok || (mount.unmountWGList != nil) { globals.Unlock() err = fmt.Errorf("%s %s", EUnknownMountID, leaseRequest.MountID) return diff --git a/imgr/imgrpkg/utils_test.go b/imgr/imgrpkg/utils_test.go index d05b67de..7516f7bc 100644 --- a/imgr/imgrpkg/utils_test.go +++ b/imgr/imgrpkg/utils_test.go @@ -138,6 +138,7 @@ func testSetup(t *testing.T, overrideConfStrings []string, retryrpcCallbacks int "IMGR.FetchNonceRangeToReturn=100", + "IMGR.MountLimit=10000", "IMGR.OpenFileLimit=100000", "IMGR.MinLeaseDuration=250ms", diff --git a/imgr/imgrpkg/volume.go b/imgr/imgrpkg/volume.go index 7de98c23..a2d3917f 100644 --- a/imgr/imgrpkg/volume.go +++ b/imgr/imgrpkg/volume.go @@ -113,6 +113,7 @@ func startVolumeManagement() (err error) { globals.inodeLeaseExpirerWG = nil globals.volumeMap = sortedmap.NewLLRBTree(sortedmap.CompareString, &globals) globals.mountMap = make(map[string]*mountStruct) + globals.unmountsInProgress = 0 err = nil return @@ -183,6 +184,7 @@ func stopVolumeManagement() (err error) { globals.inodeLeaseExpirerWG = nil globals.volumeMap = nil globals.mountMap = nil + globals.unmountsInProgress = 0 err = nil return @@ -2010,16 +2012,18 @@ func (volume *volumeStruct) checkPointWrite(body io.ReadSeeker) (authOK bool, er return } -func (mount *mountStruct) performUnmount(unmountFinishedWG *sync.WaitGroup) { +func (mount *mountStruct) performUnmount() { var ( - inodeNumber uint64 - inodeNumberList *list.List - inodeNumberListElement *list.Element - inodeOpenMapElement *inodeOpenMapElementStruct - leaseReleaseFinishedWG sync.WaitGroup - leaseRequest *leaseRequestStruct - leaseRequestOperation *leaseRequestOperationStruct - ok bool + inodeNumber uint64 + inodeNumberList *list.List + inodeNumberListElement *list.Element + inodeOpenMapElement *inodeOpenMapElementStruct + leaseReleaseFinishedWG sync.WaitGroup + leaseRequest *leaseRequestStruct + leaseRequestOperation *leaseRequestOperationStruct + ok bool + unmountFinishedWG *sync.WaitGroup + unmountFinishedWGListElement *list.Element ) globals.Lock() @@ -2093,11 +2097,24 @@ func (mount *mountStruct) performUnmount(unmountFinishedWG *sync.WaitGroup) { logFatalf("mount.mountListMembership (%v) not one of on{Healthy|AuthTokenExpired|LeasesExpired}MountList") } - mount.volume.mountMapWG.Done() + globals.unmountsInProgress-- - globals.Unlock() + unmountFinishedWGListElement = mount.unmountWGList.Front() + + for unmountFinishedWGListElement != nil { + unmountFinishedWG, ok = unmountFinishedWGListElement.Value.(*sync.WaitGroup) + if !ok { + logFatalf("unmountFinishedWGListElement.Value.(*sync.WaitGroup) returned !ok") + } - if unmountFinishedWG != nil { unmountFinishedWG.Done() + + mount.unmountWGList.Remove(unmountFinishedWGListElement) + + unmountFinishedWGListElement = mount.unmountWGList.Front() } + + mount.volume.mountMapWG.Done() + + globals.Unlock() } From 005408184df06c817879c0e0d7f054ebfd84ccd7 Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Wed, 20 Apr 2022 13:51:00 -0700 Subject: [PATCH 10/11] Beef up error reporting BodyText in imgr's HTTP POST/PUT /volume paths --- imgr/imgrpkg/http-server.go | 38 ++++++++++++++++++++++++++++++------- imgr/imgrpkg/volume.go | 15 +++++++++++++-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/imgr/imgrpkg/http-server.go b/imgr/imgrpkg/http-server.go index 8b04703f..191ccc07 100644 --- a/imgr/imgrpkg/http-server.go +++ b/imgr/imgrpkg/http-server.go @@ -1307,9 +1307,11 @@ type serveHTTPPostOfVolumeRequestBodyAsJSONStruct struct { func serveHTTPPostOfVolume(responseWriter http.ResponseWriter, request *http.Request, requestBody []byte) { var ( - err error - requestBodyAsJSON serveHTTPPostOfVolumeRequestBodyAsJSONStruct - startTime time.Time = time.Now() + conflictReason []byte + confligtReasonWriteErr error + err error + requestBodyAsJSON serveHTTPPostOfVolumeRequestBodyAsJSONStruct + startTime time.Time = time.Now() ) defer func() { @@ -1326,7 +1328,17 @@ func serveHTTPPostOfVolume(responseWriter http.ResponseWriter, request *http.Req if nil == err { responseWriter.WriteHeader(http.StatusCreated) } else { + conflictReason = []byte(fmt.Sprintf("%v\n", err)) + + responseWriter.Header().Set("Content-Length", fmt.Sprintf("%d", len(conflictReason))) + responseWriter.Header().Set("Content-Type", "text/html") + responseWriter.WriteHeader(http.StatusConflict) + + _, confligtReasonWriteErr = responseWriter.Write(conflictReason) + if nil != confligtReasonWriteErr { + logWarnf("responseWriter.Write(conflictReason) failed: %v", confligtReasonWriteErr) + } } } @@ -1346,10 +1358,12 @@ type serveHTTPPutOfVolumeRequestBodyAsJSONStruct struct { func serveHTTPPutOfVolume(responseWriter http.ResponseWriter, request *http.Request, requestPath string, requestBody []byte) { var ( - err error - pathSplit []string - requestBodyAsJSON serveHTTPPutOfVolumeRequestBodyAsJSONStruct - startTime time.Time = time.Now() + conflictReason []byte + confligtReasonWriteErr error + err error + pathSplit []string + requestBodyAsJSON serveHTTPPutOfVolumeRequestBodyAsJSONStruct + startTime time.Time = time.Now() ) pathSplit = strings.Split(requestPath, "/") @@ -1370,7 +1384,17 @@ func serveHTTPPutOfVolume(responseWriter http.ResponseWriter, request *http.Requ if nil == err { responseWriter.WriteHeader(http.StatusCreated) } else { + conflictReason = []byte(fmt.Sprintf("%v\n", err)) + + responseWriter.Header().Set("Content-Length", fmt.Sprintf("%d", len(conflictReason))) + responseWriter.Header().Set("Content-Type", "text/html") + responseWriter.WriteHeader(http.StatusConflict) + + _, confligtReasonWriteErr = responseWriter.Write(conflictReason) + if nil != confligtReasonWriteErr { + logWarnf("responseWriter.Write(conflictReason) failed: %v", confligtReasonWriteErr) + } } default: responseWriter.WriteHeader(http.StatusBadRequest) diff --git a/imgr/imgrpkg/volume.go b/imgr/imgrpkg/volume.go index a2d3917f..f8492fae 100644 --- a/imgr/imgrpkg/volume.go +++ b/imgr/imgrpkg/volume.go @@ -605,6 +605,7 @@ func postVolume(storageURL string, authToken string) (err error) { InodeType: ilayout.InodeTypeDir, }) if nil != err { + err = fmt.Errorf("rootDirDirectory.Put(\".\",) failed: %v", err) return } if !ok { @@ -619,15 +620,17 @@ func postVolume(storageURL string, authToken string) (err error) { InodeType: ilayout.InodeTypeDir, }) if nil != err { + err = fmt.Errorf("rootDirDirectory.Put(\"..\",) failed: %v", err) return } if !ok { - err = fmt.Errorf("rootDirDirectory.Put(\".\",) returned !ok") + err = fmt.Errorf("rootDirDirectory.Put(\"..\",) returned !ok") return } _, rootDirInodeObjectOffset, rootDirInodeObjectLength, err = rootDirDirectory.Flush(false) if nil != err { + err = fmt.Errorf("rootDirDirectory.Flush(false) failed: %v", err) return } @@ -666,6 +669,7 @@ func postVolume(storageURL string, authToken string) (err error) { rootDirInodeHeadV1Buf, err = rootDirInodeHeadV1.MarshalInodeHeadV1() if nil != err { + err = fmt.Errorf("rootDirInodeHeadV1.MarshalInodeHeadV1() failed: %v", err) return } @@ -673,6 +677,7 @@ func postVolume(storageURL string, authToken string) (err error) { err = swiftObjectPut(storageURL, authToken, rootDirInodeObjectNumber, postVolumeRootDirDirectoryCallbacks) if nil != err { + err = fmt.Errorf("swiftObjectPut(storageURL, authToken, rootDirInodeObjectNumber, postVolumeRootDirDirectoryCallbacks) failed: %v", err) return } @@ -697,15 +702,17 @@ func postVolume(storageURL string, authToken string) (err error) { InodeHeadLength: uint64(len(rootDirInodeHeadV1Buf)), }) if nil != err { + err = fmt.Errorf("inodeTable.Put(ilayout.RootDirInodeNumber,) failed: %v", err) return } if !ok { - err = fmt.Errorf("inodeTable.Put(RootDirInodeNumber,) returned !ok") + err = fmt.Errorf("inodeTable.Put(ilayout.RootDirInodeNumber,) returned !ok") return } _, superBlockObjectOffset, superBlockObjectLength, err = inodeTable.Flush(false) if nil != err { + err = fmt.Errorf("inodeTable.Flush(false) failed: %v", err) return } @@ -727,6 +734,7 @@ func postVolume(storageURL string, authToken string) (err error) { superBlockV1Buf, err = superBlockV1.MarshalSuperBlockV1() if nil != err { + err = fmt.Errorf("superBlockV1.MarshalSuperBlockV1() failed: %v", err) return } @@ -734,6 +742,7 @@ func postVolume(storageURL string, authToken string) (err error) { err = swiftObjectPut(storageURL, authToken, superBlockObjectNumber, postVolumeSuperBlockInodeTableCallbacks) if nil != err { + err = fmt.Errorf("swiftObjectPut(storageURL, authToken, superBlockObjectNumber, postVolumeSuperBlockInodeTableCallbacks) failed: %v", err) return } @@ -748,11 +757,13 @@ func postVolume(storageURL string, authToken string) (err error) { checkPointV1String, err = checkPointV1.MarshalCheckPointV1() if nil != err { + err = fmt.Errorf("checkPointV1.MarshalCheckPointV1() failed: %v", err) return } err = checkPointWrite(storageURL, authToken, strings.NewReader(checkPointV1String)) if nil != err { + err = fmt.Errorf("checkPointWrite(storageURL, authToken, strings.NewReader(checkPointV1String)) failed: %v", err) return } From 1143933a8e29804a5b7461e79047cedda239924b Mon Sep 17 00:00:00 2001 From: Ed McClanahan Date: Fri, 6 May 2022 17:15:37 -0700 Subject: [PATCH 11/11] Added 2.02.0 release notes --- release_notes.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/release_notes.md b/release_notes.md index b9691293..69d235dd 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,5 +1,13 @@ # ProxyFS Release Notes +## 2.02.0 (May 6, 2022) + +### Notes: + +This release marks the functional completeness point for ProxyFS. It is also notable in that the supported portions of popular file system test suites (most recently [PJDFSTEST](https://github.com/pjd/pjdfstest)) now verify correctness. It is important to point out the limitations of this functionality, however. While ProxyFS provides a form of network attached storage, it has focused on traditional hierarchical file systems presented over a network. Thus, directories and files, along with symbolic links, are fully supported. Other inode types, however are not. Further, concepts like SETUID and SETGID are explicitly disabled as is the Sticky Bit (traits normally maintained in an inode's MODE attribute). As might be imagined, excluding test cases reliant on special inode attributes as well as inote types other than these three was a non-trivial exercise. But the result has been well worth it. + +Enjoy this distributed file system atop your OpenStack Swift scale out storage! + ## 2.01.0 (March 16, 2022) ### Notes: