Skip to content

Commit

Permalink
fix deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
zhijian-pro committed Mar 21, 2023
1 parent 0a0b3a3 commit b913a97
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 24 deletions.
50 changes: 26 additions & 24 deletions pkg/meta/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -3577,29 +3577,37 @@ func (m *dbMeta) Clone(ctx Context, srcIno, dstParentIno Ino, dstName string, cm
if eno == 0 {
err = m.txn(func(s *xorm.Session) error {
// check dst edge again
if exist, err = s.ForUpdate().Get(&edge{Parent: dstParentIno, Name: []byte(dstName)}); err != nil {
if exist, err = s.Get(&edge{Parent: dstParentIno, Name: []byte(dstName)}); err != nil {
return errno(err)
} else if exist {
return syscall.EEXIST
}

if err = mustInsert(s, &edge{Parent: dstParentIno, Name: []byte(dstName), Inode: dstIno, Type: TypeDirectory}); err != nil {
if utils.IsDuplicateEntryErr(err) {
return syscall.EEXIST
}
return err
}

newSpace := align4K(0)
m.updateStats(newSpace, 1)
m.updateDirStat(ctx, dstParentIno, 0, newSpace, 1)

// update parent nlink
dstParentAttr := &Attr{}
if eno := m.doGetAttr(ctx, dstParentIno, dstParentAttr); eno != 0 {
return eno
var n = node{Inode: dstParentIno}
ok, err := s.ForUpdate().Get(&n)
if err == nil {
if ok {
_, err = s.Cols("nlink").Update(&node{Nlink: n.Nlink + 1}, &node{Inode: dstParentIno})
} else {
err = syscall.ENOENT
}
}
_, err := s.Cols("nlink").Update(&node{Nlink: dstParentAttr.Nlink + 1}, &node{Inode: dstParentIno})
return err
})
}, dstParentIno)
if err != nil {
cloneEno = errno(err)
} else {
newSpace := align4K(0)
m.updateStats(newSpace, 1)
m.updateDirStat(ctx, dstParentIno, 0, newSpace, 1)
}
}
// delete the dst tree if clone failed
Expand Down Expand Up @@ -3641,16 +3649,13 @@ func (m *dbMeta) cloneEntry(ctx Context, srcIno Ino, srcType uint8, dstParentIno
case TypeDirectory:
srcNode := node{Inode: srcIno}
if err = m.txn(func(s *xorm.Session) error {
ok, err := s.ForUpdate().Get(&srcNode)
ok, err := s.Get(&srcNode)
if err != nil {
return err
}
if !ok {
return syscall.ENOENT
}
if err := m.mkNodeWithAttr(ctx, s, srcIno, &srcNode, dstParentIno, dstName, dstIno, cmode, cumask, attach); err != nil {
return err
}
return m.mkNodeWithAttr(ctx, s, srcIno, &srcNode, dstParentIno, dstName, dstIno, cmode, cumask, attach)
}); err != nil {
return errno(err)
Expand All @@ -3661,8 +3666,7 @@ func (m *dbMeta) cloneEntry(ctx Context, srcIno Ino, srcType uint8, dstParentIno
return errno(err)
}
var entries []*Entry
eno := m.doReaddir(ctx, srcIno, 0, &entries, -1)
if eno != 0 {
if eno := m.doReaddir(ctx, srcIno, 0, &entries, -1); eno != 0 {
return eno
}
atomic.AddUint64(total, uint64(len(entries)))
Expand Down Expand Up @@ -3732,7 +3736,7 @@ func (m *dbMeta) cloneEntry(ctx Context, srcIno Ino, srcType uint8, dstParentIno
case TypeFile:
srcNode := node{Inode: srcIno}
err = m.txn(func(s *xorm.Session) error {
ok, err := s.ForUpdate().Get(&srcNode)
ok, err := s.Get(&srcNode)
if err != nil {
return err
}
Expand Down Expand Up @@ -3776,7 +3780,7 @@ func (m *dbMeta) cloneEntry(ctx Context, srcIno Ino, srcType uint8, dstParentIno
case TypeSymlink:
err = m.txn(func(s *xorm.Session) error {
srcNode := node{Inode: srcIno}
ok, err := s.ForUpdate().Get(&srcNode)
ok, err := s.Get(&srcNode)
if err != nil {
return err
}
Expand All @@ -3787,7 +3791,7 @@ func (m *dbMeta) cloneEntry(ctx Context, srcIno Ino, srcType uint8, dstParentIno
return err
}
sym := symlink{Inode: srcIno}
if exists, err := s.ForUpdate().Get(&sym); err != nil {
if exists, err := s.Get(&sym); err != nil {
return err
} else if !exists {
return syscall.ENOENT
Expand All @@ -3799,7 +3803,7 @@ func (m *dbMeta) cloneEntry(ctx Context, srcIno Ino, srcType uint8, dstParentIno
default:
err = m.txn(func(s *xorm.Session) error {
srcNode := node{Inode: srcIno}
ok, err := s.ForUpdate().Get(&srcNode)
ok, err := s.Get(&srcNode)
if err != nil {
return err
}
Expand Down Expand Up @@ -3855,7 +3859,7 @@ func (m *dbMeta) mkNodeWithAttr(ctx Context, s *xorm.Session, srcIno Ino, srcNod
return syscall.EPERM
}

if exist, err := s.ForUpdate().Get(&edge{Parent: dstParentIno, Name: []byte(dstName)}); err != nil {
if exist, err := s.Get(&edge{Parent: dstParentIno, Name: []byte(dstName)}); err != nil {
return err
} else if exist {
return syscall.EEXIST
Expand Down Expand Up @@ -3883,9 +3887,7 @@ func (m *dbMeta) mkNodeWithAttr(ctx Context, s *xorm.Session, srcIno Ino, srcNod

if attach {
// set edge
if err := mustInsert(s, &edge{Parent: dstParentIno, Name: []byte(dstName), Inode: *dstIno, Type: srcNode.Type}); err != nil {
return err
}
return mustInsert(s, &edge{Parent: dstParentIno, Name: []byte(dstName), Inode: *dstIno, Type: srcNode.Type})
}
return nil
}
17 changes: 17 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import (
"sync"
"time"

"github.com/go-sql-driver/mysql"
"github.com/jackc/pgx/v5/pgconn"
"github.com/mattn/go-sqlite3"

"github.com/mattn/go-isatty"
)

Expand Down Expand Up @@ -214,3 +218,16 @@ func LookupGroup(name string) int {
groups[name] = gid
return gid
}

func IsDuplicateEntryErr(err error) bool {
switch e := err.(type) {
case *mysql.MySQLError:
return e.Number == 1062
case *pgconn.PgError:
return e.Code == "23505"
case sqlite3.Error:
return e.Code == sqlite3.ErrConstraint
default:
return false
}
}

0 comments on commit b913a97

Please sign in to comment.