From e2f5b0dd6012f2d439db6d7012492acf99d4f78f Mon Sep 17 00:00:00 2001 From: Davies Liu Date: Mon, 20 Nov 2023 15:39:29 +0800 Subject: [PATCH] meta: convert current write lock into read lock (#4179) flock should convert current exclusive lock into a shared lock. --- pkg/meta/base_test.go | 6 ++++++ pkg/meta/redis_lock.go | 2 +- pkg/meta/sql_lock.go | 18 +++++++++--------- pkg/meta/tkv_lock.go | 4 ++-- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pkg/meta/base_test.go b/pkg/meta/base_test.go index 3808f1c6bb53..0ce9b7b3f4f7 100644 --- a/pkg/meta/base_test.go +++ b/pkg/meta/base_test.go @@ -860,6 +860,12 @@ func testLocks(t *testing.T, m Meta) { if st := m.Flock(ctx, inode, o1, syscall.F_WRLCK, false); st != 0 { t.Fatalf("flock wlock: %s", st) } + if st := m.Flock(ctx, inode, o1, syscall.F_RDLCK, false); st != 0 { + t.Fatalf("flock rlock: %s", st) + } + if st := m.Flock(ctx, inode, o1, syscall.F_WRLCK, false); st != 0 { + t.Fatalf("flock wlock: %s", st) + } if st := m.Flock(ctx, inode, o1, syscall.F_UNLCK, false); st != 0 { t.Fatalf("flock unlock: %s", st) } diff --git a/pkg/meta/redis_lock.go b/pkg/meta/redis_lock.go index 075c852968d5..897964a44200 100644 --- a/pkg/meta/redis_lock.go +++ b/pkg/meta/redis_lock.go @@ -55,6 +55,7 @@ func (r *redisMeta) Flock(ctx Context, inode Ino, owner uint64, ltype uint32, bl if err != nil { return err } + delete(owners, lkey) if ltype == F_RDLCK { for _, v := range owners { if v == "W" { @@ -67,7 +68,6 @@ func (r *redisMeta) Flock(ctx Context, inode Ino, owner uint64, ltype uint32, bl }) return err } - delete(owners, lkey) if len(owners) > 0 { return syscall.EAGAIN } diff --git a/pkg/meta/sql_lock.go b/pkg/meta/sql_lock.go index 3f22282329cf..3dcd356aa3f8 100644 --- a/pkg/meta/sql_lock.go +++ b/pkg/meta/sql_lock.go @@ -60,29 +60,29 @@ func (m *dbMeta) Flock(ctx Context, inode Ino, owner_ uint64, ltype uint32, bloc locks[key{l.Sid, l.Owner}] = l } + me := key{m.sid, owner} + flk, ok := locks[me] + delete(locks, me) + var typec byte = 'W' if ltype == F_RDLCK { for _, l := range locks { if l.Ltype == 'W' { return syscall.EAGAIN } } - return mustInsert(s, flock{Inode: inode, Owner: owner, Ltype: 'R', Sid: m.sid}) - } - me := key{m.sid, owner} - flk, ok := locks[me] - delete(locks, me) - if len(locks) > 0 { + typec = 'R' + } else if len(locks) > 0 { return syscall.EAGAIN } var n int64 if ok { - if flk.Ltype != 'W' { - n, err = s.Cols("Ltype").Update(&flock{Ltype: 'W'}, &flock{Inode: inode, Owner: owner, Sid: m.sid}) + if flk.Ltype != typec { + n, err = s.Cols("Ltype").Update(&flock{Ltype: typec}, &flock{Inode: inode, Owner: owner, Sid: m.sid}) } else { n = 1 } } else { - n, err = s.InsertOne(&flock{Inode: inode, Owner: owner, Ltype: 'W', Sid: m.sid}) + n, err = s.InsertOne(&flock{Inode: inode, Owner: owner, Ltype: typec, Sid: m.sid}) } if err == nil && n == 0 { err = fmt.Errorf("insert/update failed") diff --git a/pkg/meta/tkv_lock.go b/pkg/meta/tkv_lock.go index 8b799fed6f5c..5606a744a1cc 100644 --- a/pkg/meta/tkv_lock.go +++ b/pkg/meta/tkv_lock.go @@ -63,8 +63,8 @@ func (m *kvMeta) Flock(ctx Context, inode Ino, owner uint64, ltype uint32, block case F_UNLCK: delete(ls, lkey) case F_RDLCK: - for _, l := range ls { - if l == 'W' { + for o, l := range ls { + if l == 'W' && o != lkey { return syscall.EAGAIN } }