From 52f2317304ead5239aba0857fc8c3f249a74c18e Mon Sep 17 00:00:00 2001 From: chihe Date: Fri, 1 Mar 2024 11:27:41 +0800 Subject: [PATCH] fix(metanode): support empty file migration Signed-off-by: chihe --- lcnode/lc_transition.go | 8 ++++++++ metanode/partition_fsmop_inode.go | 6 +++++- metanode/partition_op_inode.go | 26 +++++++++++++++++--------- metanode/sorted_extents.go | 6 ++++++ metanode/sorted_obj_extents.go | 6 ++++++ proto/fs_proto.go | 12 ++++++------ 6 files changed, 48 insertions(+), 16 deletions(-) diff --git a/lcnode/lc_transition.go b/lcnode/lc_transition.go index 8fe8a07f6..a2d0df36b 100644 --- a/lcnode/lc_transition.go +++ b/lcnode/lc_transition.go @@ -49,6 +49,10 @@ type TransitionMgr struct { } func (t *TransitionMgr) migrate(e *proto.ScanDentry) (err error) { + if e.Size == 0 { + log.LogInfof("skip migration, size=0, inode(%v)", e.Inode) + return + } if err = t.ec.OpenStream(e.Inode, false, false); err != nil { log.LogErrorf("migrate: ec OpenStream fail, inode(%v) err: %v", e.Inode, err) return @@ -204,6 +208,10 @@ func (t *TransitionMgr) readFromExtentClient(e *proto.ScanDentry, writer io.Writ } func (t *TransitionMgr) migrateToEbs(e *proto.ScanDentry) (oek []proto.ObjExtentKey, err error) { + if e.Size == 0 { + log.LogInfof("skip migration, size=0, inode(%v)", e.Inode) + return + } if err = t.ec.OpenStream(e.Inode, false, false); err != nil { log.LogErrorf("migrateToEbs: OpenStream fail, inode(%v) err: %v", e.Inode, err) return diff --git a/metanode/partition_fsmop_inode.go b/metanode/partition_fsmop_inode.go index b3fff52c1..fa06a89c6 100644 --- a/metanode/partition_fsmop_inode.go +++ b/metanode/partition_fsmop_inode.go @@ -717,6 +717,10 @@ func (mp *metaPartition) checkAndInsertFreeList(ino *Inode) { } else if ino.ShouldDeleteMigrationExtentKey(true) { mp.freeList.Push(ino.Inode) } + if atomic.LoadUint32(&ino.ForbiddenMigration) == ForbiddenToMigration { + mp.fmList.Put(ino.Inode) + log.LogDebugf("action[checkAndInsertFreeList] put ino %v to forbidden migration check list", ino.Inode) + } } func (mp *metaPartition) fsmSetAttr(req *SetattrRequest) (err error) { @@ -1081,7 +1085,7 @@ func (mp *metaPartition) fsmUpdateExtentKeyAfterMigration(inoParam *Inode) (resp func logCurrentExtentKeys(storageClass uint32, sortedEks interface{}, inode uint64) { if sortedEks == nil { - log.LogErrorf("action[fsmUpdateExtentKeyAfterMigration] inode %v current ek empty", inode) + log.LogInfof("action[fsmUpdateExtentKeyAfterMigration] inode %v current ek empty", inode) } else { if proto.IsStorageClassReplica(storageClass) { log.LogInfof("action[fsmUpdateExtentKeyAfterMigration] inode %v current ek %v", diff --git a/metanode/partition_op_inode.go b/metanode/partition_op_inode.go index 38bc49d71..a64dc0bcc 100644 --- a/metanode/partition_op_inode.go +++ b/metanode/partition_op_inode.go @@ -83,10 +83,10 @@ func replyInfo(info *proto.InodeInfo, ino *Inode, quotaInfos map[uint32]*proto.M info.ForbiddenLc = true } info.MigrationStorageClass = ino.HybridCouldExtentsMigration.storageClass - if ino.HybridCouldExtentsMigration.storageClass != proto.StorageClass_Unspecified { + if ino.HybridCouldExtentsMigration.sortedEks != nil { info.HasMigrationEk = true } - info.MigrationExtentKeyExpiredTime = time.Unix(ino.HybridCouldExtentsMigration.expiredTime, 0).Format("2006-01-02 15:04:05") + info.MigrationExtentKeyExpiredTime = time.Unix(ino.HybridCouldExtentsMigration.expiredTime, 0) return true } @@ -1164,15 +1164,23 @@ func (mp *metaPartition) UpdateExtentKeyAfterMigration(req *proto.UpdateExtentKe ino.HybridCouldExtentsMigration.storageClass = req.StorageClass ino.HybridCouldExtentsMigration.expiredTime = time.Now().Add(time.Duration(req.DelayDeleteMinute) * time.Minute).Unix() if req.StorageClass == proto.StorageClass_BlobStore { + //may be ino.HybridCouldExtentsMigration.sortedEks = NewSortedObjExtentsFromObjEks(req.NewObjExtentKeys) - } else if req.StorageClass == proto.MediaType_HDD { - if item.(*Inode).HybridCouldExtentsMigration.storageClass != proto.MediaType_HDD { - err = fmt.Errorf("mp %v inode %v migration class now is %v", - mp.config.PartitionId, ino.Inode, item.(*Inode).HybridCouldExtentsMigration.storageClass) - log.LogErrorf("action[UpdateExtentKeyAfterMigration] %v", err) - p.PacketErrorWithBody(proto.OpErr, []byte(err.Error())) + } else if req.StorageClass == proto.StorageClass_Replica_HDD { + if item.(*Inode).HybridCouldExtentsMigration.sortedEks == nil && + item.(*Inode).HybridCouldExtentsMigration.storageClass == proto.StorageClass_Unspecified { + log.LogDebugf("action[UpdateExtentKeyAfterMigration] ino %v has no migration data", ino.Inode) + ino.HybridCouldExtentsMigration.sortedEks = NewSortedExtents() + } else { + if item.(*Inode).HybridCouldExtentsMigration.storageClass != proto.StorageClass_Replica_HDD { + err = fmt.Errorf("mp %v inode %v migration class now is %v", + mp.config.PartitionId, ino.Inode, item.(*Inode).HybridCouldExtentsMigration.storageClass) + log.LogErrorf("action[UpdateExtentKeyAfterMigration] %v", err) + p.PacketErrorWithBody(proto.OpErr, []byte(err.Error())) + return + } + ino.HybridCouldExtentsMigration.sortedEks = item.(*Inode).HybridCouldExtentsMigration.sortedEks } - ino.HybridCouldExtentsMigration.sortedEks = item.(*Inode).HybridCouldExtentsMigration.sortedEks } else { err = fmt.Errorf("mp %v inode %v unsupport new migration storage class %v", mp.config.PartitionId, ino.Inode, req.StorageClass) diff --git a/metanode/sorted_extents.go b/metanode/sorted_extents.go index 247bc819e..ddc98fa1a 100644 --- a/metanode/sorted_extents.go +++ b/metanode/sorted_extents.go @@ -28,6 +28,12 @@ func NewSortedExtentsFromEks(eks []proto.ExtentKey) *SortedExtents { } } +func (se *SortedExtents) IsEmpty() bool { + se.RLock() + defer se.RUnlock() + return len(se.eks) == 0 +} + func (se *SortedExtents) String() string { se.RLock() data, err := json.Marshal(se.eks) diff --git a/metanode/sorted_obj_extents.go b/metanode/sorted_obj_extents.go index 3016d9cbf..b77b18c87 100644 --- a/metanode/sorted_obj_extents.go +++ b/metanode/sorted_obj_extents.go @@ -36,6 +36,12 @@ func (se *SortedObjExtents) String() string { return string(data) } +func (se *SortedObjExtents) IsEmpty() bool { + se.RLock() + defer se.RUnlock() + return len(se.eks) == 0 +} + func (se *SortedObjExtents) MarshalBinary() ([]byte, error) { var data []byte diff --git a/proto/fs_proto.go b/proto/fs_proto.go index 83e0a0935..d892e7fd9 100644 --- a/proto/fs_proto.go +++ b/proto/fs_proto.go @@ -96,12 +96,12 @@ type InodeInfo struct { expiration int64 PersistAccessTime time.Time `json:"pat"` - StorageClass uint32 `json:"storageClass"` - WriteGen uint64 `json:"writeGen"` - ForbiddenLc bool `json:"forbiddenLc"` - MigrationStorageClass uint32 `json:"migrationStorageClass"` - HasMigrationEk bool `json:"hasMigrationEk"` - MigrationExtentKeyExpiredTime string `json:"mekExpiredTime"` + StorageClass uint32 `json:"storageClass"` + WriteGen uint64 `json:"writeGen"` + ForbiddenLc bool `json:"forbiddenLc"` + MigrationStorageClass uint32 `json:"migrationStorageClass"` + HasMigrationEk bool `json:"hasMigrationEk"` + MigrationExtentKeyExpiredTime time.Time `json:"mekExpiredTime"` } type SimpleExtInfo struct {