mirror of https://github.com/ceph/go-ceph
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:
parent
1d30b636ff
commit
092c0b7832
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue