mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-26 15:00:48 +01:00
* filer: in-memory POSIX lock authority (Manager) Concurrent multi-inode authority over the per-inode Set: a Set per opaque inode key (path, or hl:<HardLinkId>) plus a session->keys index so a dead mount's locks reap in O(locks held). Lock state stays in memory like the distributed lock manager's, off the replicated meta-log. TryLock/Unlock/ GetLk/ReleasePosixOwner/ReleaseFlockOwner/ReleaseSession; empty sets and stale index entries are pruned on release. * filer: routed PosixLock RPC over the in-memory authority Adds the PosixLock RPC (try/unlock/get_lk + the flush/release owner drops) that the owner filer answers from its in-memory Manager. The request key is the inode identity ring key; a non-owner filer forwards one hop (is_moved-bounded), mirroring ObjectTransaction, so the owner's table stays the single authority under a stale ring view. Strictly non-blocking; SetLkw polling lives in the mount.
96 lines
3.0 KiB
Go
96 lines
3.0 KiB
Go
package weed_server
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/filer/posixlock"
|
|
"github.com/seaweedfs/seaweedfs/weed/glog"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
|
)
|
|
|
|
// PosixLock applies one advisory lock operation against the in-memory lock table
|
|
// of the inode's owner filer. The owner is resolved from req.Key on the same
|
|
// ring the gateway and DLM use; a non-owner filer forwards the request one hop
|
|
// (is_moved bounds it), so the owner's table stays the single authority even when
|
|
// the caller's ring view is stale. Blocking (SetLkw) is the caller's job — this
|
|
// is strictly non-blocking try/release/query.
|
|
func (fs *FilerServer) PosixLock(ctx context.Context, req *filer_pb.PosixLockRequest) (*filer_pb.PosixLockResponse, error) {
|
|
if req.Key == "" {
|
|
return &filer_pb.PosixLockResponse{}, fmt.Errorf("key is required")
|
|
}
|
|
if req.Lock == nil {
|
|
return &filer_pb.PosixLockResponse{}, fmt.Errorf("lock is required")
|
|
}
|
|
|
|
if !req.IsMoved && fs.filer.Dlm != nil {
|
|
if owner := fs.filer.Dlm.LockRing.GetPrimary(req.Key); owner != "" && owner != fs.option.Host {
|
|
forwarded := &filer_pb.PosixLockRequest{
|
|
Key: req.Key,
|
|
IsMoved: true,
|
|
Op: req.Op,
|
|
Lock: req.Lock,
|
|
}
|
|
glog.V(4).InfofCtx(ctx, "PosixLock %s op=%v: forwarding to owner %s", req.Key, req.Op, owner)
|
|
var resp *filer_pb.PosixLockResponse
|
|
err := pb.WithFilerClient(false, 0, owner, fs.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
|
|
var e error
|
|
resp, e = client.PosixLock(ctx, forwarded)
|
|
return e
|
|
})
|
|
if err != nil {
|
|
return &filer_pb.PosixLockResponse{}, err
|
|
}
|
|
return resp, nil
|
|
}
|
|
}
|
|
|
|
lk := posixlock.Range{
|
|
Start: req.Lock.GetStart(),
|
|
End: req.Lock.GetEnd(),
|
|
Type: req.Lock.GetType(),
|
|
Sid: req.Lock.GetSid(),
|
|
Owner: req.Lock.GetOwner(),
|
|
Pid: req.Lock.GetPid(),
|
|
IsFlock: req.Lock.GetIsFlock(),
|
|
}
|
|
|
|
resp := &filer_pb.PosixLockResponse{}
|
|
switch req.Op {
|
|
case filer_pb.PosixLockOp_TRY_LOCK:
|
|
if c, granted := fs.posixLocks.TryLock(req.Key, lk); granted {
|
|
resp.Granted = true
|
|
} else {
|
|
resp.HasConflict = true
|
|
resp.Conflict = posixRangeToPb(c)
|
|
}
|
|
case filer_pb.PosixLockOp_UNLOCK:
|
|
fs.posixLocks.Unlock(req.Key, lk)
|
|
case filer_pb.PosixLockOp_GET_LK:
|
|
if c, found := fs.posixLocks.GetLk(req.Key, lk); found {
|
|
resp.HasConflict = true
|
|
resp.Conflict = posixRangeToPb(c)
|
|
}
|
|
case filer_pb.PosixLockOp_RELEASE_POSIX_OWNER:
|
|
fs.posixLocks.ReleasePosixOwner(req.Key, lk.Sid, lk.Owner)
|
|
case filer_pb.PosixLockOp_RELEASE_FLOCK_OWNER:
|
|
fs.posixLocks.ReleaseFlockOwner(req.Key, lk.Sid, lk.Owner)
|
|
default:
|
|
return &filer_pb.PosixLockResponse{}, fmt.Errorf("unknown posix lock op %v", req.Op)
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func posixRangeToPb(r posixlock.Range) *filer_pb.PosixLockRange {
|
|
return &filer_pb.PosixLockRange{
|
|
Start: r.Start,
|
|
End: r.End,
|
|
Type: r.Type,
|
|
Sid: r.Sid,
|
|
Owner: r.Owner,
|
|
Pid: r.Pid,
|
|
IsFlock: r.IsFlock,
|
|
}
|
|
}
|