🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Commit 1739b1c

Browse files
committed
space/cleanup: validate completed chunk manifests
* verify completed manifests by loading the chunk manifest instead of trusting only the chunked LOM flag * remove completed-shaped manifests that fail validation and cover the corrupted-manifest cleanup path Signed-off-by: Tony Chen <a122774007@gmail.com>
1 parent 904be6c commit 1739b1c

3 files changed

Lines changed: 50 additions & 11 deletions

File tree

‎cmn/err.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,8 +912,8 @@ func (e *ErrLmetaCorrupted) Error() string { return e.err.Error() }
912912
func (e *ErrLmetaCorrupted) Unwrap() (err error) { return e.err }
913913

914914
func IsErrLmetaCorrupted(err error) bool {
915-
_, ok := err.(*ErrLmetaCorrupted)
916-
return ok
915+
var wrapped *ErrLmetaCorrupted
916+
return errors.As(err, &wrapped)
917917
}
918918

919919
func NewErrLmetaNotFound(name string, err error) *ErrLmetaNotFound {

‎space/cleanup.go‎

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -765,18 +765,43 @@ func (j *clnJ) visitChunk(chunkFQN string, lom *core.LOM, uploadID string) {
765765
j.rmAnyBatch(flagRmOldWork)
766766
}
767767

768-
func (*clnJ) isCompletedManifest(parsed *fs.ParsedFQN) bool {
769-
objFQN := parsed.Mountpath.MakePathFQN(&parsed.Bck, fs.ObjCT, parsed.ObjName)
770-
771-
lom := core.AllocLOM("")
768+
// isCompletedManifest returns true when a fs.ChunkMetaCT entry must be kept as
769+
// a valid completed manifest. Ambiguous source/manifest errors are kept for retry.
770+
func (*clnJ) isCompletedManifest(parsed *fs.ParsedFQN) (keep bool) {
771+
lom := core.AllocLOM(parsed.ObjName)
772772
defer core.FreeLOM(lom)
773-
if err := lom.InitFQN(objFQN, nil); err != nil {
774-
return false
773+
if err := lom.InitCmnBck(&parsed.Bck); err != nil {
774+
return true
775+
}
776+
if !lom.TryLock(false) {
777+
return true
775778
}
776-
if err := lom.Load(false /*cache*/, false /*locked*/); err != nil {
777-
return false // %ob/<obj> absent or unreadable -> not a chunked-LOM manifest
779+
defer lom.Unlock(false)
780+
781+
// force md loading from disk
782+
lom.Uncache()
783+
if err := lom.Load(false /*cache*/, true /*locked*/); err != nil {
784+
return !cos.IsNotExist(err) // remove when the source object is absent or unreadable
785+
}
786+
if !lom.IsChunked() {
787+
return false // remove when the source object is not marked as chunked
778788
}
779-
return lom.IsChunked()
789+
790+
manifest, err := core.NewUfest("", lom, true /*mustExist*/)
791+
if err != nil {
792+
return true
793+
}
794+
if err := manifest.LoadCompleted(lom); err != nil {
795+
// Keep when the error indicates missing/ambiguous metadata that should be retried.
796+
if cos.IsNotExist(err) {
797+
return true // nothing to do
798+
}
799+
if cmn.IsErrLmetaCorrupted(err) || cmn.IsErrLmetaNotFound(err) {
800+
return true // cannot decide
801+
}
802+
return false // failed chunk-manifest load is garbage
803+
}
804+
return true
780805
}
781806

782807
func (j *clnJ) _getCompletedID(lom *core.LOM) (id string) {

‎space/cleanup_test.go‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,20 @@ var _ = Describe("AIStore content cleanup tests", func() {
730730
Entry("suffix shape collides with uploadID", "regress/foo.r4kzG8GMfA"),
731731
)
732732

733+
It("keeps completed manifest when source metadata cannot be loaded", func() {
734+
lom, _ := makeChunkedLOM(&bck, "regress/source-meta-unreadable.tar")
735+
defer core.FreeLOM(lom)
736+
737+
completedFQN := lom.GenFQN(fs.ChunkMetaCT)
738+
Expect(fs.SetXattr(lom.FQN, fs.XattrLOM, []byte{0x00, 0xff, 0x13, 0x37})).NotTo(HaveOccurred())
739+
Expect(os.Chtimes(completedFQN, old, old)).NotTo(HaveOccurred())
740+
741+
space.RunCleanup(ini)
742+
743+
Expect(completedFQN).To(BeAnExistingFile())
744+
Expect(lom.FQN).To(BeAnExistingFile())
745+
})
746+
733747
It("removes stale partial manifest of an absent LOM", func() {
734748
lom := core.AllocLOM("regress/parent-obj")
735749
defer core.FreeLOM(lom)

0 commit comments

Comments
 (0)