filer/posixlock: remove the unused lock-set serde (#9676)

The codec (Set.Marshal/Unmarshal) and its posix_lock.proto were built to
let the lock set ride in an inode's entry metadata, but the authority is
in-memory and ownership handoff/restart is handled by mounts re-asserting
their held locks over the RPC — neither serializes the set. Nothing calls
the serde outside its own tests, so drop it (codec, proto, generated pb,
Makefile). The in-memory Set/Manager are unchanged.
This commit is contained in:
Chris Lu
2026-05-25 13:15:19 -07:00
committed by GitHub
parent 85ca3cb757
commit c9868dcf2f
5 changed files with 0 additions and 394 deletions

View File

@@ -1,6 +0,0 @@
all: gen
.PHONY : gen
gen:
protoc posix_lock.proto --go_out=. --go-grpc_out=. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative

View File

@@ -1,58 +0,0 @@
package posixlock
import (
"fmt"
"google.golang.org/protobuf/proto"
)
// The held lock set rides in an inode's entry metadata, so the wire format must
// stay backward compatible across filer versions. It is a protobuf message
// (LockSetProto), so new fields can be added without breaking old readers.
// Marshal encodes the held locks for storage in the inode's entry metadata. A
// lock-free set encodes to nil, so an inode that holds no locks carries no blob.
func (s *Set) Marshal() ([]byte, error) {
if len(s.locks) == 0 {
return nil, nil
}
pb := &LockSetProto{Locks: make([]*LockProto, len(s.locks))}
for i, l := range s.locks {
pb.Locks[i] = &LockProto{
Start: l.Start,
End: l.End,
Type: l.Type,
Sid: l.Sid,
Owner: l.Owner,
Pid: l.Pid,
IsFlock: l.IsFlock,
}
}
return proto.Marshal(pb)
}
// Unmarshal decodes a Set produced by Marshal. Empty input is an empty set, so a
// missing metadata key reads back as "no locks held". A malformed blob is
// rejected rather than silently misread.
func Unmarshal(b []byte) (*Set, error) {
if len(b) == 0 {
return &Set{}, nil
}
pb := &LockSetProto{}
if err := proto.Unmarshal(b, pb); err != nil {
return nil, fmt.Errorf("posixlock: %w", err)
}
locks := make([]Range, len(pb.Locks))
for i, l := range pb.Locks {
locks[i] = Range{
Start: l.Start,
End: l.End,
Type: l.Type,
Sid: l.Sid,
Owner: l.Owner,
Pid: l.Pid,
IsFlock: l.IsFlock,
}
}
return &Set{locks: locks}, nil
}

View File

@@ -1,75 +0,0 @@
package posixlock
import (
"math"
"reflect"
"testing"
)
func TestMarshalEmptyIsNil(t *testing.T) {
s := &Set{}
b, err := s.Marshal()
if err != nil {
t.Fatalf("marshal empty: %v", err)
}
if b != nil {
t.Fatalf("empty set should marshal to nil, got %d bytes", len(b))
}
got, err := Unmarshal(nil)
if err != nil {
t.Fatalf("unmarshal nil: %v", err)
}
if !got.Empty() {
t.Fatal("unmarshal nil should be an empty set")
}
}
func TestMarshalRoundTrip(t *testing.T) {
s := &Set{}
// A spread of fields: EOF range, both namespaces, two sessions, distinct pids.
mustAcquire(t, s, Range{Start: 0, End: 99, Type: Write, Sid: 1, Owner: 7, Pid: 10})
mustAcquire(t, s, Range{Start: 200, End: math.MaxUint64, Type: Read, Sid: 2, Owner: 7, Pid: 20})
mustAcquire(t, s, Range{Start: 0, End: math.MaxUint64, Type: Write, Sid: 2, Owner: 9, Pid: 30, IsFlock: true})
b, err := s.Marshal()
if err != nil {
t.Fatalf("marshal: %v", err)
}
got, err := Unmarshal(b)
if err != nil {
t.Fatalf("unmarshal: %v", err)
}
if !reflect.DeepEqual(got.Locks(), s.Locks()) {
t.Fatalf("round-trip mismatch:\n got %+v\nwant %+v", got.Locks(), s.Locks())
}
}
func TestUnmarshalRejectsMalformed(t *testing.T) {
// field 1 (locks), wire type 2 (length-delimited) declaring 5 bytes that
// are not there: a corrupt blob must fail loudly, not read back as empty.
if _, err := Unmarshal([]byte{0x0A, 0x05}); err == nil {
t.Fatal("expected an error on malformed input")
}
}
// A decoded set must behave identically — conflict detection still fires.
func TestRoundTripPreservesConflict(t *testing.T) {
s := &Set{}
mustAcquire(t, s, Range{Start: 0, End: 99, Type: Write, Sid: 1, Owner: 1, Pid: 10})
b, err := s.Marshal()
if err != nil {
t.Fatalf("marshal: %v", err)
}
decoded, err := Unmarshal(b)
if err != nil {
t.Fatalf("unmarshal: %v", err)
}
if _, granted := decoded.Acquire(Range{Start: 50, End: 149, Type: Write, Sid: 2, Owner: 1, Pid: 20}); granted {
t.Fatal("decoded set should still report the conflict")
}
// Same owner across the wire is still the same owner.
if _, granted := decoded.Acquire(Range{Start: 0, End: 99, Type: Read, Sid: 1, Owner: 1, Pid: 10}); !granted {
t.Fatal("decoded set should still recognize the same (sid,owner)")
}
}

View File

@@ -1,230 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc v6.33.4
// source: posix_lock.proto
package posixlock
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// LockSetProto is the serialized set of advisory locks held on one inode. It
// rides in the inode's entry metadata, so the schema must stay backward
// compatible across filer versions.
type LockSetProto struct {
state protoimpl.MessageState `protogen:"open.v1"`
Locks []*LockProto `protobuf:"bytes,1,rep,name=locks,proto3" json:"locks,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LockSetProto) Reset() {
*x = LockSetProto{}
mi := &file_posix_lock_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LockSetProto) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LockSetProto) ProtoMessage() {}
func (x *LockSetProto) ProtoReflect() protoreflect.Message {
mi := &file_posix_lock_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LockSetProto.ProtoReflect.Descriptor instead.
func (*LockSetProto) Descriptor() ([]byte, []int) {
return file_posix_lock_proto_rawDescGZIP(), []int{0}
}
func (x *LockSetProto) GetLocks() []*LockProto {
if x != nil {
return x.Locks
}
return nil
}
// LockProto mirrors Range. Owner identity is the (sid, owner) pair; end is
// inclusive and max uint64 means EOF; is_flock separates the flock and fcntl
// namespaces, which never conflict.
type LockProto struct {
state protoimpl.MessageState `protogen:"open.v1"`
Start uint64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"`
End uint64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"`
Type uint32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
Sid uint64 `protobuf:"varint,4,opt,name=sid,proto3" json:"sid,omitempty"`
Owner uint64 `protobuf:"varint,5,opt,name=owner,proto3" json:"owner,omitempty"`
Pid uint32 `protobuf:"varint,6,opt,name=pid,proto3" json:"pid,omitempty"`
IsFlock bool `protobuf:"varint,7,opt,name=is_flock,json=isFlock,proto3" json:"is_flock,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LockProto) Reset() {
*x = LockProto{}
mi := &file_posix_lock_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LockProto) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LockProto) ProtoMessage() {}
func (x *LockProto) ProtoReflect() protoreflect.Message {
mi := &file_posix_lock_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LockProto.ProtoReflect.Descriptor instead.
func (*LockProto) Descriptor() ([]byte, []int) {
return file_posix_lock_proto_rawDescGZIP(), []int{1}
}
func (x *LockProto) GetStart() uint64 {
if x != nil {
return x.Start
}
return 0
}
func (x *LockProto) GetEnd() uint64 {
if x != nil {
return x.End
}
return 0
}
func (x *LockProto) GetType() uint32 {
if x != nil {
return x.Type
}
return 0
}
func (x *LockProto) GetSid() uint64 {
if x != nil {
return x.Sid
}
return 0
}
func (x *LockProto) GetOwner() uint64 {
if x != nil {
return x.Owner
}
return 0
}
func (x *LockProto) GetPid() uint32 {
if x != nil {
return x.Pid
}
return 0
}
func (x *LockProto) GetIsFlock() bool {
if x != nil {
return x.IsFlock
}
return false
}
var File_posix_lock_proto protoreflect.FileDescriptor
const file_posix_lock_proto_rawDesc = "" +
"\n" +
"\x10posix_lock.proto\x12\tposixlock\":\n" +
"\fLockSetProto\x12*\n" +
"\x05locks\x18\x01 \x03(\v2\x14.posixlock.LockProtoR\x05locks\"\x9c\x01\n" +
"\tLockProto\x12\x14\n" +
"\x05start\x18\x01 \x01(\x04R\x05start\x12\x10\n" +
"\x03end\x18\x02 \x01(\x04R\x03end\x12\x12\n" +
"\x04type\x18\x03 \x01(\rR\x04type\x12\x10\n" +
"\x03sid\x18\x04 \x01(\x04R\x03sid\x12\x14\n" +
"\x05owner\x18\x05 \x01(\x04R\x05owner\x12\x10\n" +
"\x03pid\x18\x06 \x01(\rR\x03pid\x12\x19\n" +
"\bis_flock\x18\a \x01(\bR\aisFlockB5Z3github.com/seaweedfs/seaweedfs/weed/filer/posixlockb\x06proto3"
var (
file_posix_lock_proto_rawDescOnce sync.Once
file_posix_lock_proto_rawDescData []byte
)
func file_posix_lock_proto_rawDescGZIP() []byte {
file_posix_lock_proto_rawDescOnce.Do(func() {
file_posix_lock_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_posix_lock_proto_rawDesc), len(file_posix_lock_proto_rawDesc)))
})
return file_posix_lock_proto_rawDescData
}
var file_posix_lock_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_posix_lock_proto_goTypes = []any{
(*LockSetProto)(nil), // 0: posixlock.LockSetProto
(*LockProto)(nil), // 1: posixlock.LockProto
}
var file_posix_lock_proto_depIdxs = []int32{
1, // 0: posixlock.LockSetProto.locks:type_name -> posixlock.LockProto
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_posix_lock_proto_init() }
func file_posix_lock_proto_init() {
if File_posix_lock_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_posix_lock_proto_rawDesc), len(file_posix_lock_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_posix_lock_proto_goTypes,
DependencyIndexes: file_posix_lock_proto_depIdxs,
MessageInfos: file_posix_lock_proto_msgTypes,
}.Build()
File_posix_lock_proto = out.File
file_posix_lock_proto_goTypes = nil
file_posix_lock_proto_depIdxs = nil
}

View File

@@ -1,25 +0,0 @@
syntax = "proto3";
package posixlock;
option go_package = "github.com/seaweedfs/seaweedfs/weed/filer/posixlock";
// LockSetProto is the serialized set of advisory locks held on one inode. It
// rides in the inode's entry metadata, so the schema must stay backward
// compatible across filer versions.
message LockSetProto {
repeated LockProto locks = 1;
}
// LockProto mirrors Range. Owner identity is the (sid, owner) pair; end is
// inclusive and max uint64 means EOF; is_flock separates the flock and fcntl
// namespaces, which never conflict.
message LockProto {
uint64 start = 1;
uint64 end = 2;
uint32 type = 3;
uint64 sid = 4;
uint64 owner = 5;
uint32 pid = 6;
bool is_flock = 7;
}