@@ -2638,10 +2638,6 @@ func (m *dbMeta) doBatchUnlink(ctx Context, parent Ino, entries []*Entry, length
26382638 }
26392639 delNodes := make (map [Ino ]* dNode )
26402640 var totalLength , totalSpace , totalInodes int64
2641- if userGroupQuotas != nil {
2642- * userGroupQuotas = make ([]userGroupQuotaDelta , 0 , len (entries ))
2643- }
2644- // main transaction: validate, collect metadata, update inode/link counts, and prepare DB mutations
26452641 err := m .txn (func (s * xorm.Session ) error {
26462642 pn := node {Inode : parent }
26472643 ok , err := s .Get (& pn )
@@ -2662,19 +2658,30 @@ func (m *dbMeta) doBatchUnlink(ctx Context, parent Ino, entries []*Entry, length
26622658 if (pn .Flags & FlagAppend != 0 ) || (pn .Flags & FlagImmutable ) != 0 {
26632659 return syscall .EPERM
26642660 }
2665- entryInfos = make ([]* entryInfo , 0 , len (entries ))
26662661 now := time .Now ().UnixNano ()
2662+ entryInfos = make ([]* entryInfo , 0 , len (entries ))
2663+ names := make ([][]byte , 0 , len (entries ))
2664+ for _ , entry := range entries {
2665+ names = append (names , entry .Name )
2666+ }
2667+ var foundEdges []edge
2668+ if err := s .Where ("parent=?" , parent ).In ("name" , names ).Find (& foundEdges ); err != nil {
2669+ return err
2670+ }
2671+ entryMap := make (map [string ]* edge )
2672+ for i := range foundEdges {
2673+ entryMap [string (foundEdges [i ].Name )] = & foundEdges [i ]
2674+ }
26672675
2668- // collect unique inode ids from entries (avoid operating N times on same inode for hard links)
26692676 inodes := make ([]Ino , 0 , len (entries ))
26702677 inodeM := make (map [Ino ]struct {}) // filter hardlinks
26712678 for _ , entry := range entries {
2672- e := & edge { Parent : parent , Name : entry . Name , Inode : entry .Inode }
2673- if entry . Attr != nil {
2674- if entry . Attr . Typ == TypeDirectory {
2675- continue
2676- }
2677- e . Type = entry . Attr . Typ
2679+ e , ok := entryMap [ string ( entry .Name )]
2680+ if ! ok {
2681+ continue
2682+ }
2683+ if e . Inode != entry . Inode || e . Type == TypeDirectory || ( entry . Attr != nil && e . Type != entry . Attr . Typ ) {
2684+ continue
26782685 }
26792686 entryInfos = append (entryInfos , & entryInfo {e : e , trash : trash })
26802687 if _ , exists := inodeM [entry .Inode ]; ! exists {
@@ -2766,7 +2773,9 @@ func (m *dbMeta) doBatchUnlink(ctx Context, parent Ino, entries []*Entry, length
27662773 symlinksDel := make ([]Ino , 0 )
27672774 xattrsDel := make ([]Ino , 0 )
27682775 edgesIns := make ([]interface {}, 0 )
2769-
2776+ if userGroupQuotas != nil {
2777+ * userGroupQuotas = make ([]userGroupQuotaDelta , 0 , len (entries ))
2778+ }
27702779 // walk each edge to decide whether to move to trash, decrement nlink or delete inode & xattrs
27712780 for _ , info := range entryInfos {
27722781 edgesDel = append (edgesDel , edge {Parent : parent , Name : info .e .Name })
0 commit comments