Skip to content

Commit

Permalink
servers: implement lock in all servers
Browse files Browse the repository at this point in the history
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
  • Loading branch information
rminnich committed Apr 15, 2022
1 parent fc8614a commit 9a4f65a
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 6 deletions.
5 changes: 5 additions & 0 deletions fsimpl/localfs/localfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ func (l *Local) ReadAt(p []byte, offset int64) (int, error) {
return l.file.ReadAt(p, offset)
}

// Lock implements p9.File.Lock.
func (l *Local) Lock(pid, locktype, flags int, start, length uint64, client string) error {
return l.lock(pid, locktype, flags, start, length, client)
}

// WriteAt implements p9.File.WriteAt.
func (l *Local) WriteAt(p []byte, offset int64) (int, error) {
return l.file.WriteAt(p, offset)
Expand Down
25 changes: 25 additions & 0 deletions fsimpl/localfs/system_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ package localfs
import (
"os"
"syscall"

"github.com/hugelgupf/p9/p9"
"golang.org/x/sys/unix"
)

func umask(mask int) int {
Expand All @@ -14,3 +17,25 @@ func umask(mask int) int {
func localToQid(_ string, fi os.FileInfo) (uint64, error) {
return uint64(fi.Sys().(*syscall.Stat_t).Ino), nil
}

// lock implements p9.File.Lock.
func (l *Local) lock(pid, locktype, flags int, start, length uint64, client string) error {
var err error
switch p9.LockType(locktype) {
case p9.ReadLock, p9.WriteLock:
if err := unix.Flock(int(l.file.Fd()), unix.LOCK_EX); err != nil {
err = p9.ELockError
}
case p9.Unlock:
if err := unix.Flock(int(l.file.Fd()), unix.LOCK_EX); err != nil {
err = p9.ELockError
}
default:
// 9P2000.L not only does not return an Rerror per standard,
// it does not have a way to say "not implemented" for a Lock type.
// They had 255 possible values, and use 3, ... ay yi yi.
// 9P2000.L doesn't really fit the spirit of 9P.
err = p9.ELockError
}
return err
}
8 changes: 8 additions & 0 deletions fsimpl/localfs/system_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@ func localToQid(path string, info os.FileInfo) (uint64, error) {
x := uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow)
return x, nil
}

// lock implements p9.File.Lock.
// As in FreeBSD NFS locking, we just say "sure, we did it" without actually
// doing anything; this lock design makes even less sense on Windows than
// it does on Linux (pid? really? what were they thinking?)
func (l *Local) lock(pid, locktype, flags int, start, length uint64, client string) error {
return nil
}
12 changes: 12 additions & 0 deletions fsimpl/staticfs/staticfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ func (d *dir) GetAttr(req p9.AttrMask) (p9.QID, p9.AttrMask, p9.Attr, error) {
}, nil
}

// Lock implements p9.File.Lock.
// It may seem odd to have a Lock on a dir, but 9P2000 does not distinguish
// dirs and files.
func (*dir) Lock(pid, locktype, flags int, start, length uint64, client string) error {
return nil
}

func min(a, b uint64) uint64 {
if a < b {
return a
Expand Down Expand Up @@ -215,3 +222,8 @@ func (f *file) GetAttr(req p9.AttrMask) (p9.QID, p9.AttrMask, p9.Attr, error) {
BlockSize: 4096, /* whatever? */
}, nil
}

// Lock implements p9.File.Lock.
func (*file) Lock(pid, locktype, flags int, start, length uint64, client string) error {
return nil
}
5 changes: 5 additions & 0 deletions fsimpl/templatefs/unimplfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,8 @@ func (NoopFile) Readdir(offset uint64, count uint32) (p9.Dirents, error) {
func (NoopFile) Readlink() (string, error) {
return "", linux.ENOSYS
}

// Lock implements p9.File.Lock.
func (NoopFile) Lock(pid, locktype, flags int, start, length uint64, client string) error {
return linux.ENOSYS
}
4 changes: 2 additions & 2 deletions p9/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -979,9 +979,9 @@ func (t *tlock) handle(cs *connState) message {
}
defer ref.DecRef()

r1 := LockOK
r1 := lockOK
if err := ref.file.Lock(int(t.PID), int(t.Type), int(t.Flags), t.Start, t.Length, t.Client); err != nil {
r1 = LockError
r1 = lockError
}
return &rlock{Status: uint8(r1)}
}
Expand Down
14 changes: 10 additions & 4 deletions p9/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package p9
import (
"fmt"
"math"
"syscall"
)

// ErrInvalidMsgType is returned when an unsupported message type is found.
Expand Down Expand Up @@ -2062,12 +2063,17 @@ type LockStat uint8

// These are the four current return values for Rlock.
const (
LockOK LockStat = 0
LockBlocked LockStat = 1
LockError LockStat = 2
LockGrace LockStat = 3
lockOK LockStat = 0
lockBlocked LockStat = 1
lockError LockStat = 2
lockGrace LockStat = 3
)

// ELockError is the overarching error for Tlock.
// The 9P2000.L lock errors are basically "something failed",
// i.e., not conformant with how 9P2000 is supposed to work.
var ELockError = syscall.Errno(lockError)

// The Linux v9fs client implements the fcntl(F_SETLKW) (blocking)
// lock request by calling lock with P9_LOCK_FLAGS_BLOCK set. If the
// response is P9_LOCK_BLOCKED, it retries the lock request in an
Expand Down

0 comments on commit 9a4f65a

Please sign in to comment.