cephfs: add ceph_flock() function

Added ceph_flock() function which applies or removes an advisory lock on an open file.

Fixes: https://github.com/ceph/go-ceph/issues/248

Signed-off-by: Mudit Agarwal muagarwa@redhat.com
This commit is contained in:
Mudit Agarwal 2020-05-18 16:03:12 +05:30 committed by John Mulligan
parent 1d30b636ff
commit 092c0b7832
2 changed files with 134 additions and 0 deletions

View File

@ -255,3 +255,41 @@ func (f *File) Fallocate(mode FallocFlags, offset, length int64) error {
ret := C.ceph_fallocate(f.mount.mount, f.fd, C.int(mode), C.int64_t(offset), C.int64_t(length))
return getError(ret)
}
// LockOp determines operations/type of locks which can be applied on a file.
type LockOp int
const (
// LockSH places a shared lock.
// More than one process may hold a shared lock for a given file at a given time.
LockSH = LockOp(C.LOCK_SH)
// LockEX places an exclusive lock.
// Only one process may hold an exclusive lock for a given file at a given time.
LockEX = LockOp(C.LOCK_EX)
// LockUN removes and existing lock held by this process.
LockUN = LockOp(C.LOCK_UN)
// LockNB can be ORed with any of the above to make a nonblocking call.
LockNB = LockOp(C.LOCK_NB)
)
// Flock applies or removes an advisory lock on an open file.
// Param owner is the user-supplied identifier for the owner of the
// lock, must be an arbitrary integer.
//
// Implements:
// int ceph_flock(struct ceph_mount_info *cmount, int fd, int operation, uint64_t owner);
func (f *File) Flock(operation LockOp, owner uint64) error {
if err := f.validate(); err != nil {
return err
}
// validate the operation values before passing it on.
switch operation &^ LockNB {
case LockSH, LockEX, LockUN:
default:
return errInvalid
}
ret := C.ceph_flock(f.mount.mount, f.fd, C.int(operation), C.uint64_t(owner))
return getError(ret)
}

View File

@ -615,3 +615,99 @@ func TestFallocate(t *testing.T) {
assert.Error(t, err)
})
}
func TestFlock(t *testing.T) {
mount := fsConnect(t)
defer fsDisconnect(t, mount)
t.Run("validate", func(t *testing.T) {
f := &File{}
err := f.Flock(LockSH, 1010)
assert.Error(t, err)
})
t.Run("validateOperation", func(t *testing.T) {
fname := "Flockfile.txt"
f, err := mount.Open(fname, os.O_RDWR|os.O_CREATE, 0666)
assert.NoError(t, err)
assert.NotNil(t, f)
defer func() {
assert.NoError(t, f.Close())
assert.NoError(t, mount.Unlink(fname))
}()
err = f.Flock(LockSH|LockEX, 1010)
assert.Error(t, err)
})
t.Run("basicLocking", func(t *testing.T) {
const (
anna = 42
bob = 43
chris = 44
)
fname1 := "Flockfile1.txt"
f1, err := mount.Open(fname1, os.O_RDWR|os.O_CREATE, 0666)
assert.NoError(t, err)
assert.NotNil(t, f1)
defer func() {
assert.NoError(t, f1.Close())
assert.NoError(t, mount.Unlink(fname1))
}()
// Lock exclusively twice.
t.Run("exclusiveTwiceBlock", func(t *testing.T) {
err := f1.Flock(LockEX, anna)
assert.NoError(t, err)
defer func() {
assert.NoError(t, f1.Flock(LockUN, anna))
}()
err = f1.Flock(LockEX|LockNB, bob)
assert.Error(t, err)
})
t.Run("exclusiveTwiceNonBlock", func(t *testing.T) {
err := f1.Flock(LockEX|LockNB, anna)
assert.NoError(t, err)
defer func() {
assert.NoError(t, f1.Flock(LockUN, anna))
}()
err = f1.Flock(LockEX|LockNB, bob)
assert.Error(t, err)
})
// Lock shared.
t.Run("sharedLock", func(t *testing.T) {
err := f1.Flock(LockSH, anna)
assert.NoError(t, err)
err = f1.Flock(LockSH, bob)
assert.NoError(t, err)
defer func() {
assert.NoError(t, f1.Flock(LockUN, anna))
assert.NoError(t, f1.Flock(LockUN, bob))
}()
// Now try to take exclusive lock.
err = f1.Flock(LockEX|LockNB, chris)
assert.Error(t, err)
})
// Lock shared with upgrade to exclusive.
t.Run("sharedLockUpExclusive", func(t *testing.T) {
err := f1.Flock(LockSH, bob)
assert.NoError(t, err)
defer func() {
assert.NoError(t, f1.Flock(LockUN, bob))
}()
err = f1.Flock(LockEX, bob)
assert.NoError(t, err)
})
// Lock exclusive with downgrade to shared.
t.Run("exclusiveLockDownShared", func(t *testing.T) {
err := f1.Flock(LockEX, bob)
assert.NoError(t, err)
defer func() {
assert.NoError(t, f1.Flock(LockUN, bob))
}()
err = f1.Flock(LockSH, bob)
assert.NoError(t, err)
})
})
}