From ec3df9e65a3a2e1005cd4d50d06a8819fd3ab5f6 Mon Sep 17 00:00:00 2001 From: Anoop C S Date: Tue, 19 Jan 2016 14:35:18 +0530 Subject: 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 --- api/src/gfapi-messages.h | 4 +- api/src/gfapi.aliases | 1 + api/src/gfapi.map | 2 + api/src/glfs-fops.c | 128 +++++++++++++++++++++++++++++++++++------------ api/src/glfs.h | 44 ++++++++++++++++ 5 files changed, 147 insertions(+), 32 deletions(-) (limited to 'api/src') diff --git a/api/src/gfapi-messages.h b/api/src/gfapi-messages.h index 3eedfa7d07..f231ce99a4 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 41a01f842f..88d361dc32 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 aa30286c01..fc47a3b8f4 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 287326c4e4..833ff33663 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 42cbfe7ab6..5ffed1e085 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); -- cgit