summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
authorAnoop C S <anoopcs@redhat.com>2016-01-19 14:35:18 +0530
committerNiels de Vos <ndevos@redhat.com>2018-01-22 09:54:02 +0000
commitec3df9e65a3a2e1005cd4d50d06a8819fd3ab5f6 (patch)
tree847ac98b10927e4e1081ba35260beb4b18996d47 /api
parent10d74166f17fa44c06bd1357e0a4b0b052265425 (diff)
libgfapi: Add new api for supporting mandatory-locks
The current API for byte-range locks [glfs_posix_lock()] doesn't allow applications to specify whether it is advisory or mandatory type locks. This particular change is to introduce an extended byte-range lock API with an additional argument for including the byte-range lock mode to be one among advisory(default) or mandatory. Patch also includes a gfapi test case which make use of this new api to acquire mandatory locks. Ref: https://github.com/gluster/glusterfs-specs/blob/master/done/GlusterFS%203.8/Mandatory%20Locks.md Change-Id: Ia09042c755d891895d96da857321abc4ce03e20c Updates #393 Signed-off-by: Anoop C S <anoopcs@redhat.com>
Diffstat (limited to 'api')
-rw-r--r--api/src/gfapi-messages.h4
-rw-r--r--api/src/gfapi.aliases1
-rw-r--r--api/src/gfapi.map2
-rw-r--r--api/src/glfs-fops.c128
-rw-r--r--api/src/glfs.h44
5 files changed, 147 insertions, 32 deletions
diff --git a/api/src/gfapi-messages.h b/api/src/gfapi-messages.h
index 3eedfa7d071..f231ce99a47 100644
--- a/api/src/gfapi-messages.h
+++ b/api/src/gfapi-messages.h
@@ -73,7 +73,9 @@ GLFS_MSGID(API,
API_MSG_CREATE_HANDLE_FAILED,
API_MSG_INODE_LINK_FAILED,
API_MSG_STATEDUMP_FAILED,
- API_MSG_XREADDIRP_R_FAILED
+ API_MSG_XREADDIRP_R_FAILED,
+ API_MSG_LOCK_INSERT_MERGE_FAILED,
+ API_MSG_SETTING_LOCK_TYPE_FAILED
);
#endif /* !_GFAPI_MESSAGES_H__ */
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases
index 41a01f842fd..88d361dc329 100644
--- a/api/src/gfapi.aliases
+++ b/api/src/gfapi.aliases
@@ -169,3 +169,4 @@ _pub_glfs_upcall_register _glfs_upcall_register$GFAPI_3.13.0
_pub_glfs_upcall_unregister _glfs_upcall_unregister$GFAPI_3.13.0
_pub_glfs_setfsleaseid _glfs_setfsleaseid$GFAPI_4.0.0
+_pub_glfs_file_lock _glfs_file_lock$GFAPI_4.0.0
diff --git a/api/src/gfapi.map b/api/src/gfapi.map
index aa30286c01b..fc47a3b8f42 100644
--- a/api/src/gfapi.map
+++ b/api/src/gfapi.map
@@ -222,5 +222,7 @@ GFAPI_3.13.0 {
} GFAPI_PRIVATE_3.12.0;
GFAPI_4.0.0 {
+ global:
glfs_setfsleaseid;
+ glfs_file_lock;
} GFAPI_3.13.0;
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
index 287326c4e4a..833ff336634 100644
--- a/api/src/glfs-fops.c
+++ b/api/src/glfs-fops.c
@@ -4250,36 +4250,46 @@ gf_flock_from_flock (struct gf_flock *gf_flock, struct flock *flock)
gf_flock->l_pid = flock->l_pid;
}
-
-int
-pub_glfs_posix_lock (struct glfs_fd *glfd, int cmd, struct flock *flock)
+static int
+glfs_lock_common (struct glfs_fd *glfd, int cmd, struct flock *flock,
+ dict_t *xdata)
{
- int ret = -1;
- xlator_t *subvol = NULL;
- struct gf_flock gf_flock = {0, };
- struct gf_flock saved_flock = {0, };
- fd_t *fd = NULL;
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ struct gf_flock gf_flock = {0, };
+ struct gf_flock saved_flock = {0, };
+ fd_t *fd = NULL;
DECLARE_OLD_THIS;
- __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+
+ if (!flock) {
+ errno = EINVAL;
+ goto out;
+ }
GF_REF_GET (glfd);
- subvol = glfs_active_subvol (glfd->fs);
- if (!subvol) {
- ret = -1;
- errno = EIO;
- goto out;
- }
+ subvol = glfs_active_subvol (glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
- fd = glfs_resolve_fd (glfd->fs, subvol, glfd);
- if (!fd) {
- ret = -1;
- errno = EBADFD;
- goto out;
- }
+ fd = glfs_resolve_fd (glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ /* Generate glusterfs flock structure from client flock
+ * structure to be processed by server */
+ gf_flock_from_flock (&gf_flock, flock);
- gf_flock_from_flock (&gf_flock, flock);
- gf_flock_from_flock (&saved_flock, flock);
+ /* Keep another copy of flock for split/merge of locks
+ * at client side */
+ gf_flock_from_flock (&saved_flock, flock);
if (glfd->lk_owner.len != 0) {
ret = syncopctx_setfslkowner (&glfd->lk_owner);
@@ -4288,24 +4298,80 @@ pub_glfs_posix_lock (struct glfs_fd *glfd, int cmd, struct flock *flock)
goto out;
}
- ret = syncop_lk (subvol, fd, cmd, &gf_flock, NULL, NULL);
+ ret = syncop_lk (subvol, fd, cmd, &gf_flock, xdata, NULL);
DECODE_SYNCOP_ERR (ret);
- gf_flock_to_flock (&gf_flock, flock);
- if (ret == 0 && (cmd == F_SETLK || cmd == F_SETLKW))
- fd_lk_insert_and_merge (fd, cmd, &saved_flock);
+ /* Convert back from gf_flock to flock as expected by application */
+ gf_flock_to_flock (&gf_flock, flock);
+
+ if (ret == 0 && (cmd == F_SETLK || cmd == F_SETLKW)) {
+ ret = fd_lk_insert_and_merge (fd, cmd, &saved_flock);
+ if (ret) {
+ gf_msg (THIS->name, GF_LOG_ERROR, 0,
+ API_MSG_LOCK_INSERT_MERGE_FAILED,
+ "Lock insertion and splitting/merging failed "
+ "on gfid %s", uuid_utoa (fd->inode->gfid));
+ ret = 0;
+ }
+ }
+
out:
- if (fd)
- fd_unref (fd);
+ if (fd)
+ fd_unref (fd);
if (glfd)
GF_REF_PUT (glfd);
- glfs_subvol_done (glfd->fs, subvol);
+ glfs_subvol_done (glfd->fs, subvol);
__GLFS_EXIT_FS;
invalid_fs:
- return ret;
+ return ret;
+}
+
+int
+pub_glfs_file_lock (struct glfs_fd *glfd, int cmd, struct flock *flock,
+ enum glfs_lock_mode_t lk_mode)
+{
+ int ret = -1;
+ dict_t *xdata_in = NULL;
+
+ if (lk_mode == GLFS_LK_MANDATORY) {
+ /* Create a new dictionary */
+ xdata_in = dict_new ();
+ if (xdata_in == NULL) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ /* Set GF_LK_MANDATORY internally within dictionary to map
+ * GLFS_LK_MANDATORY */
+ ret = dict_set_uint32 (xdata_in, GF_LOCK_MODE, GF_LK_MANDATORY);
+ if (ret) {
+ gf_msg (THIS->name, GF_LOG_ERROR, 0,
+ API_MSG_SETTING_LOCK_TYPE_FAILED,
+ "Setting lock type failed");
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ }
+
+ ret = glfs_lock_common (glfd, cmd, flock, xdata_in);
+out:
+ if (xdata_in)
+ dict_unref (xdata_in);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_file_lock, 4.0.0);
+
+int
+pub_glfs_posix_lock (struct glfs_fd *glfd, int cmd, struct flock *flock)
+{
+ return glfs_lock_common (glfd, cmd, flock, NULL);
}
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_posix_lock, 3.4.0);
diff --git a/api/src/glfs.h b/api/src/glfs.h
index 42cbfe7ab6c..5ffed1e0853 100644
--- a/api/src/glfs.h
+++ b/api/src/glfs.h
@@ -774,6 +774,50 @@ char *glfs_realpath (glfs_t *fs, const char *path, char *resolved_path) __THROW
int glfs_posix_lock (glfs_fd_t *fd, int cmd, struct flock *flock) __THROW
GFAPI_PUBLIC(glfs_posix_lock, 3.4.0);
+/*
+ SYNOPSIS
+
+ glfs_file_lock: Request extended byte range lock on a file
+
+ DESCRIPTION
+
+ This function is capable of requesting either advisory or mandatory type
+ byte range locks on a file.
+
+ Note: To set a unique owner key for locks based on a particular file
+ descriptor, make use of glfs_fd_set_lkowner() api to do so before
+ requesting lock via this api. This owner key will be further consumed
+ by other incoming data modifying file operations via the same file
+ descriptor.
+
+ PARAMETERS
+
+ @fd: File descriptor
+
+ @cmd: As specified in man fcntl(2).
+
+ @flock: As specified in man fcntl(2).
+
+ @lk_mode: Required lock type from options available with the
+ enum glfs_lock_mode_t defined below.
+
+ RETURN VALUES
+
+ 0 : Success. Lock has been granted.
+ -1 : Failure. @errno will be set indicating the type of failure.
+
+ */
+
+/* Lock modes used by glfs_file_lock() */
+enum glfs_lock_mode_t {
+ GLFS_LK_ADVISORY = 0,
+ GLFS_LK_MANDATORY
+};
+
+int glfs_file_lock (glfs_fd_t *fd, int cmd, struct flock *flock,
+ enum glfs_lock_mode_t lk_mode) __THROW
+ GFAPI_PUBLIC(glfs_file_lock, 3.13.0);
+
glfs_fd_t *glfs_dup (glfs_fd_t *fd) __THROW
GFAPI_PUBLIC(glfs_dup, 3.4.0);