fix(meta): empty file not check storage class. #22735527

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
This commit is contained in:
Victor1319 2024-10-31 18:14:06 +08:00
parent d1d8f1dfe1
commit b00afa2e33
3 changed files with 287 additions and 27 deletions

View File

@ -149,6 +149,10 @@ func (i *Inode) setVerNoCheck(seq uint64) {
i.verUpdate(seq)
}
func (i *Inode) IsFile() bool {
return proto.IsRegular(i.Type)
}
func (i *Inode) setVer(seq uint64) {
if i.getVer() > seq {
syslog.Println(fmt.Sprintf("inode[%v] old seq [%v] cann't use seq [%v]", i.getVer(), seq, string(debug.Stack())))
@ -778,7 +782,7 @@ func (i *Inode) MarshalInodeValue(buff *bytes.Buffer) {
isFile := proto.IsRegular(i.Type)
// to check flag
if !proto.IsValidStorageClass(i.StorageClass) && isFile {
if !proto.IsValidStorageClass(i.StorageClass) && isFile && i.Size > 0 {
panic(fmt.Sprintf("ino(%v) MarshalInodeValue failed, unsupport StorageClass %v", i.Inode, i.StorageClass))
}
@ -1031,14 +1035,14 @@ func (i *Inode) UnmarshalInodeValue(buff *bytes.Buffer) (err error) {
i.HybridCouldExtents = NewSortedHybridCloudExtents()
}
isFile := proto.IsRegular(i.Type)
isFile := i.IsFile()
v3 := i.Reserved&V3EnableSnapInodeFlag > 0
v4 := i.Reserved&V4EnableHybridCloud > 0
if i.Reserved == 0 {
log.LogDebugf("#### [UnmarshalInodeValue] not v2 v3 V4, ino(%v), isFile %v", i.Inode, isFile)
log.LogDebugf("#### [UnmarshalInodeValue] not v2 v3 V4, ino(%v), isFile %v, size %d", i.Inode, isFile, i.Size)
i.StorageClass = legacyReplicaStorageClass
if !isFile {
if !isFile || i.Size == 0 {
return
}
@ -1219,7 +1223,7 @@ func (i *Inode) UnmarshalInodeValue(buff *bytes.Buffer) (err error) {
}
func (i *Inode) GetSpaceSize() (extSize uint64) {
if i.IsTempFile() {
if i.IsTempFile() || !i.IsFile() {
return
}
if i.HybridCouldExtents.sortedEks == nil {

View File

@ -3,6 +3,8 @@ package metanode
import (
"bytes"
"encoding/binary"
"io"
"os"
"reflect"
"sync"
"testing"
@ -107,6 +109,8 @@ func TestV1InodeStoreInSSDToV4Inode_UnMarshal(t *testing.T) {
FileOffset: 11, PartitionId: 12,
ExtentId: 13, ExtentOffset: 0, Size: 0, CRC: 0,
}})
ino.Size = 10
var data []byte
data, _ = ino.Marshal()
targetIno := NewInode(0, 0)
@ -221,6 +225,65 @@ func TestV4MigrationInodeCopyDirectly(t *testing.T) {
assert.True(t, ino.Equal(temp))
}
func TestCompitableWithOldVersion(t *testing.T) {
// normal(dir, file, empty file), ebs(dir, file, empty file)
legacyReplicaStorageClass = proto.MediaType_Unspecified
checkInodeCompatibility := func(oldIno *OldVersionInode, t *testing.T) {
newIno := NewInode(0, 0)
data, err := oldIno.Marshal()
require.NoError(t, err)
err = newIno.Unmarshal(data)
require.NoError(t, err)
require.True(t, oldIno.EqualNew(newIno))
data, err = newIno.Marshal()
require.NoError(t, err)
oldIno2 := NewOldVersionInode(0, 0)
err = oldIno2.Unmarshal(data)
require.NoError(t, err)
require.True(t, oldIno2.EqualNew(newIno))
}
oldIno := NewOldVersionInode(1024, uint32(os.ModeDir))
oldIno.Uid = 101
oldIno.Gid = 102
oldIno.Generation = 104
oldIno.CreateTime = 105
oldIno.AccessTime = 106
oldIno.ModifyTime = 107
oldIno.LinkTarget = []byte("test op")
oldIno.NLink = 108
oldIno.Flag = 109
// dir
oldIno.Type = uint32(os.ModeDir)
checkInodeCompatibility(oldIno, t)
// empty file
oldIno.Type = 0
checkInodeCompatibility(oldIno, t)
// old ebs file
oldIno.ObjExtents = NewSortedObjExtentsFromObjEks([]proto.ObjExtentKey{{Size: uint64(100), FileOffset: uint64(100)}})
oldIno.Size = 1024
checkInodeCompatibility(oldIno, t)
// file
oldIno.Extents = NewSortedExtentsFromEks([]proto.ExtentKey{{FileOffset: 100}})
oldIno.ObjExtents = nil
oldIno.Size = 1024
data, err := oldIno.Marshal()
require.NoError(t, err)
newIno := NewInode(0, 0)
err = newIno.Unmarshal(data)
require.Error(t, err)
legacyReplicaStorageClass = proto.StorageClass_Replica_HDD
checkInodeCompatibility(oldIno, t)
}
func NewOldVersionInode(ino uint64, t uint32) *OldVersionInode {
ts := timeutil.GetCurrentTimeUnix()
i := &OldVersionInode{
@ -258,6 +321,41 @@ type OldVersionInode struct {
// Extents *ExtentsTree
Extents *SortedExtents
ObjExtents *SortedObjExtents
multiSnap *InodeMultiSnap
}
func (i *OldVersionInode) EqualNew(i1 *Inode) bool {
if i.Inode != i1.Inode || i.Type != i1.Type || i.Uid != i1.Uid || i.Gid != i1.Gid || i.Size != i1.Size {
return false
}
if i.Generation != i1.Generation || i.CreateTime != i1.CreateTime || i.AccessTime != i1.AccessTime {
return false
}
if i.AccessTime != i1.AccessTime || i.ModifyTime != i1.ModifyTime || !bytes.Equal(i.LinkTarget, i1.LinkTarget) {
return false
}
if i.NLink != i1.NLink || i.Flag != i1.Flag {
return false
}
if i.Extents != nil && !i.Extents.IsEmpty() {
ext := i1.HybridCouldExtents.sortedEks.(*SortedExtents)
if !i.Extents.Equals(ext) {
return false
}
}
if i.ObjExtents != nil && !i.ObjExtents.IsEmpty() {
ext := i1.HybridCouldExtents.sortedEks.(*SortedObjExtents)
if !i.ObjExtents.Equals(ext) {
return false
}
}
return true
}
func (i *OldVersionInode) Marshal() (result []byte, err error) {
@ -288,11 +386,12 @@ func (i *OldVersionInode) MarshalKey() (k []byte) {
return
}
func (i *OldVersionInode) MarshalValue() (val []byte) {
var err error
// MarshalValue marshals the value to bytes.
func (i *OldVersionInode) MarshalValue() []byte {
buff := bytes.NewBuffer(make([]byte, 0, 128))
buff.Grow(64)
i.RLock()
var err error
if err = binary.Write(buff, binary.BigEndian, &i.Type); err != nil {
panic(err)
}
@ -332,25 +431,35 @@ func (i *OldVersionInode) MarshalValue() (val []byte) {
if err = binary.Write(buff, binary.BigEndian, &i.Flag); err != nil {
panic(err)
}
i.Reserved = 0
if i.ObjExtents != nil && len(i.ObjExtents.eks) > 0 {
i.Reserved = V2EnableEbsFlag
i.Reserved |= V2EnableEbsFlag
}
if i.multiSnap != nil {
i.Reserved |= V3EnableSnapInodeFlag
}
// log.LogInfof("action[MarshalInodeValue] inode[%v] Reserved %v", i.Inode, i.Reserved)
if err = binary.Write(buff, binary.BigEndian, &i.Reserved); err != nil {
panic(err)
}
if i.Reserved == V2EnableEbsFlag {
// marshal ExtentsKey
extData, err := i.Extents.MarshalBinary(false)
if err != nil {
panic(err)
}
// marshal ExtentsKey
extData, err := i.Extents.MarshalBinary(i.Reserved&V3EnableSnapInodeFlag > 0)
if err != nil {
panic(err)
}
if i.Reserved != 0 {
if err = binary.Write(buff, binary.BigEndian, uint32(len(extData))); err != nil {
panic(err)
}
if _, err = buff.Write(extData); err != nil {
panic(err)
}
}
if _, err = buff.Write(extData); err != nil {
panic(err)
}
if i.Reserved&V2EnableEbsFlag > 0 {
// marshal ObjExtentsKey
objExtData, err := i.ObjExtents.MarshalBinary()
if err != nil {
@ -362,18 +471,164 @@ func (i *OldVersionInode) MarshalValue() (val []byte) {
if _, err = buff.Write(objExtData); err != nil {
panic(err)
}
} else {
// marshal ExtentsKey
extData, err := i.Extents.MarshalBinary(false)
if err != nil {
panic(err)
}
if _, err = buff.Write(extData); err != nil {
}
if i.multiSnap != nil {
if err = binary.Write(buff, binary.BigEndian, i.multiSnap.verSeq); err != nil {
panic(err)
}
}
return buff.Bytes()
}
func (i *OldVersionInode) Unmarshal(raw []byte) (err error) {
var (
keyLen uint32
valLen uint32
)
buff := bytes.NewBuffer(raw)
if err = binary.Read(buff, binary.BigEndian, &keyLen); err != nil {
return
}
keyBytes := make([]byte, keyLen)
if _, err = buff.Read(keyBytes); err != nil {
return
}
if err = i.UnmarshalKey(keyBytes); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &valLen); err != nil {
return
}
valBytes := make([]byte, valLen)
if _, err = buff.Read(valBytes); err != nil {
return
}
err = i.UnmarshalValue(valBytes)
return
}
func (i *OldVersionInode) UnmarshalKey(k []byte) (err error) {
i.Inode = binary.BigEndian.Uint64(k)
return
}
// UnmarshalValue unmarshals the value from bytes.
func (i *OldVersionInode) UnmarshalValue(val []byte) (err error) {
buff := bytes.NewBuffer(val)
if err = binary.Read(buff, binary.BigEndian, &i.Type); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.Uid); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.Gid); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.Size); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.Generation); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.CreateTime); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.AccessTime); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.ModifyTime); err != nil {
return
}
// read symLink
symSize := uint32(0)
if err = binary.Read(buff, binary.BigEndian, &symSize); err != nil {
return
}
if symSize > 0 {
i.LinkTarget = make([]byte, symSize)
if _, err = io.ReadFull(buff, i.LinkTarget); err != nil {
return
}
}
if err = binary.Read(buff, binary.BigEndian, &i.NLink); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.Flag); err != nil {
return
}
if err = binary.Read(buff, binary.BigEndian, &i.Reserved); err != nil {
return
}
// unmarshal ExtentsKey
if i.Extents == nil {
i.Extents = NewSortedExtents()
}
if i.ObjExtents == nil {
i.ObjExtents = NewSortedObjExtents()
}
if i.Reserved == 0 {
if err, _ = i.Extents.UnmarshalBinary(buff.Bytes(), false); err != nil {
return
}
return
}
v3 := i.Reserved&V3EnableSnapInodeFlag > 0
v2 := i.Reserved&V2EnableEbsFlag > 0
extSize := uint32(0)
if err = binary.Read(buff, binary.BigEndian, &extSize); err != nil {
return
}
if extSize > 0 {
extBytes := make([]byte, extSize)
if _, err = io.ReadFull(buff, extBytes); err != nil {
return
}
var ekRef *sync.Map
if err, ekRef = i.Extents.UnmarshalBinary(extBytes, v3); err != nil {
return
}
// log.LogDebugf("inode[%v] ekRef %v", i.Inode, ekRef)
if ekRef != nil {
if i.multiSnap == nil {
i.multiSnap = NewMultiSnap(0)
}
// log.LogDebugf("inode[%v] ekRef %v", i.Inode, ekRef)
i.multiSnap.ekRefMap = ekRef
}
}
if v2 {
// unmarshal ObjExtentsKey
ObjExtSize := uint32(0)
if err = binary.Read(buff, binary.BigEndian, &ObjExtSize); err != nil {
return
}
if ObjExtSize > 0 {
objExtBytes := make([]byte, ObjExtSize)
if _, err = io.ReadFull(buff, objExtBytes); err != nil {
return
}
if err = i.ObjExtents.UnmarshalBinary(objExtBytes); err != nil {
return
}
}
}
if v3 {
var seq uint64
if err = binary.Read(buff, binary.BigEndian, &seq); err != nil {
return
}
if seq != 0 {
// i.setVer(seq)
}
}
val = buff.Bytes()
i.RUnlock()
return
}

View File

@ -40,6 +40,7 @@ func (se *SortedObjExtents) String() string {
func (se *SortedObjExtents) IsEmpty() bool {
se.RLock()
defer se.RUnlock()
return len(se.eks) == 0
}