diff options
author | Soumya Koduri <skoduri@redhat.com> | 2017-10-04 14:34:48 +0530 |
---|---|---|
committer | Soumya Koduri <skoduri@redhat.com> | 2017-10-12 16:12:36 +0530 |
commit | c22cec3928be6924fb1026ef969cae897efbd76d (patch) | |
tree | 60a10e937bab57ed285eda10a122dcffef99e2e7 | |
parent | a3767c4ceb527cb0f52b95650c841964cf7faec9 (diff) |
gfapi: set lkowner in glfd
We need a provision to be able to set lkowner (which is
used to distinguish locks maintained by server) in gfapi.
Since the same lk_owner need to be used to be able to
flush the lock while closing the fd, store the lkowner
in the glfd structure itself.
A new API has been added to be able to set lkowner in glfd.
Change-Id: I67591d6b9a89c20b9617d52616513ff9e6c06b47
BUG: 1499641
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
-rw-r--r-- | api/src/gfapi.aliases | 2 | ||||
-rw-r--r-- | api/src/gfapi.map | 5 | ||||
-rw-r--r-- | api/src/glfs-fops.c | 51 | ||||
-rw-r--r-- | api/src/glfs-internal.h | 1 | ||||
-rw-r--r-- | api/src/glfs.h | 28 | ||||
-rw-r--r-- | tests/basic/gfapi/glfd-lkowner.c | 212 | ||||
-rwxr-xr-x | tests/basic/gfapi/glfd-lkowner.t | 27 |
7 files changed, 326 insertions, 0 deletions
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases index b0facb717b3..00a9e3753af 100644 --- a/api/src/gfapi.aliases +++ b/api/src/gfapi.aliases @@ -163,3 +163,5 @@ _pub_glfs_xreaddirplus_r_get_object _glfs_xreaddirplus_r_get_object$GFAPI_3.11.0 _pub_glfs_object_copy _glfs_object_copy$GFAPI_3.11.0 _priv_glfs_ipc _glfs_ipc$GFAPI_3.12.0 + +_pub_glfd_set_lk_owner _glfd_set_lk_owner$GFAPI_3.13.0 diff --git a/api/src/gfapi.map b/api/src/gfapi.map index 7f19e1ee4f9..c9ce4d82235 100644 --- a/api/src/gfapi.map +++ b/api/src/gfapi.map @@ -209,3 +209,8 @@ GFAPI_PRIVATE_3.12.0 { global: glfs_ipc; } GFAPI_3.11.0; + +GFAPI_3.13.0 { + global: + glfd_set_lk_owner; +} GFAPI_PRIVATE_3.12.0; diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index e6ed07a68a9..f47ef625613 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -267,6 +267,12 @@ pub_glfs_close (struct glfs_fd *glfd) goto out; } + if (glfd->lk_owner.len != 0) { + ret = syncopctx_setfslkowner (&glfd->lk_owner); + if (ret) + goto out; + } + ret = syncop_flush (subvol, fd, NULL, NULL); DECODE_SYNCOP_ERR (ret); out: @@ -4272,6 +4278,14 @@ pub_glfs_posix_lock (struct glfs_fd *glfd, int cmd, struct flock *flock) gf_flock_from_flock (&gf_flock, flock); gf_flock_from_flock (&saved_flock, flock); + + if (glfd->lk_owner.len != 0) { + ret = syncopctx_setfslkowner (&glfd->lk_owner); + + if (ret) + goto out; + } + ret = syncop_lk (subvol, fd, cmd, &gf_flock, NULL, NULL); DECODE_SYNCOP_ERR (ret); gf_flock_to_flock (&gf_flock, flock); @@ -4294,6 +4308,43 @@ invalid_fs: GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_posix_lock, 3.4.0); +int +pub_glfd_set_lk_owner (glfs_fd_t *glfd, void *data, int len) +{ + int ret = -1; + + DECLARE_OLD_THIS; + __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs); + + if (!GF_REF_GET (glfd)) { + goto invalid_fs; + } + + GF_VALIDATE_OR_GOTO (THIS->name, data, out); + + if ((len <= 0) || (len > GFAPI_MAX_LOCK_OWNER_LEN)) { + errno = EINVAL; + gf_msg (THIS->name, GF_LOG_ERROR, errno, + LG_MSG_INVALID_ARG, + "Invalid lk_owner len (%d)", len); + goto out; + } + + glfd->lk_owner.len = len; + + memcpy (glfd->lk_owner.data, data, len); + + ret = 0; +out: + if (glfd) + GF_REF_PUT (glfd); + + __GLFS_EXIT_FS; + +invalid_fs: + return ret; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfd_set_lk_owner, 3.13.0); struct glfs_fd * pub_glfs_dup (struct glfs_fd *glfd) diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index be2d60a38e0..757bc18eb1d 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -215,6 +215,7 @@ struct glfs_fd { struct list_head entries; gf_dirent_t *next; struct dirent *readdirbuf; + gf_lkowner_t lk_owner; }; /* glfs object handle introduced for the alternate gfapi implementation based diff --git a/api/src/glfs.h b/api/src/glfs.h index 5420a1dde66..acf63c32655 100644 --- a/api/src/glfs.h +++ b/api/src/glfs.h @@ -855,6 +855,34 @@ glfs_xreaddirplus_r (struct glfs_fd *glfd, uint32_t flags, struct dirent *ext, struct dirent **res); GFAPI_PUBLIC(glfs_xreaddirplus_r, 3.11.0); +#define GFAPI_MAX_LOCK_OWNER_LEN 255 + +/* + * + * DESCRIPTION + * + * This API allows application to set lk_owner on a fd. + * A glfd can be associated with only single lk_owner. In case if there + * is need to set another lk_owner, applications can make use of + * 'glfs_dup' to get duplicate glfd and set new lk_owner on that second + * glfd. + * + * Also its not recommended to override or clear lk_owner value as the + * same shall be used to flush any outstanding locks while closing the fd. + * + * PARAMETERS + * + * INPUT: + * @glfd: GFAPI file descriptor + * @len: Size of lk_owner buffer. Max value can be GFAPI_MAX_LOCK_OWNER_LEN + * @data: lk_owner data buffer. + * + * OUTPUT: + * 0: SUCCESS + * -1: FAILURE + */ +int glfd_set_lk_owner (glfs_fd_t *glfd, void *data, int len); + GFAPI_PUBLIC(glfd_set_lk_owner, 3.13.0); __END_DECLS #endif /* !_GLFS_H */ diff --git a/tests/basic/gfapi/glfd-lkowner.c b/tests/basic/gfapi/glfd-lkowner.c new file mode 100644 index 00000000000..4f2b0fc0650 --- /dev/null +++ b/tests/basic/gfapi/glfd-lkowner.c @@ -0,0 +1,212 @@ +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <limits.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <sys/wait.h> +#include <stdbool.h> + +int gfapi = 1; + +#define LOG_ERR(func, ret) do { \ + if (ret != 0) { \ + fprintf (stderr, "%s : returned error %d (%s)\n", \ + func, ret, strerror (errno)); \ + goto out; \ + } else { \ + fprintf (stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) + +char lownera[8] = "lownera", lownerb[8] = "lownerb"; +char lownerc[8] = "lownerc"; + +int lock_test (glfs_fd_t *glfd1, glfs_fd_t *glfd2, bool should_fail, + int l1_start, int l1_len, char *l1_owner, int lo1_len, + int l2_start, int l2_len, char *l2_owner, int lo2_len) +{ + int ret = -1, f_ret = -1; + struct flock lock1 = {0, }, lock2 = {0, }; + +lock1: + if (!glfd1) + goto lock2; + + /* lock on glfd1 */ + lock1.l_type = F_WRLCK; + lock1.l_whence = SEEK_SET; + lock1.l_start = l1_start; + lock1.l_len = l1_len; + + ret = glfd_set_lk_owner (glfd1, l1_owner, lo1_len); + LOG_ERR ("glfd_set_lk_owner on glfd1", ret); + + ret = glfs_posix_lock (glfd1, F_SETLK, &lock1); + LOG_ERR ("glfs_posix_lock on glfd1", ret); + +lock2: + if (!glfd2) + goto out; + + /* lock on glfd2 */ + lock2.l_type = F_WRLCK; + lock2.l_whence = SEEK_SET; + lock2.l_start = l2_start; + lock2.l_len = l2_len; + + ret = glfd_set_lk_owner (glfd2, l2_owner, lo2_len); + LOG_ERR ("glfd_set_lk_owner on glfd2", ret); + + ret = glfs_posix_lock (glfd2, F_SETLK, &lock2); + + if (should_fail && ret) { + f_ret = 0; + } else if (!ret && !should_fail) { + f_ret = 0; + } else { + f_ret = -1; + } +out: + fprintf (stderr, "Lock test on glfd1 (start(%d), len(%d)," + " lk_owner(%s)) and glfd2 (start(%d), len(%d), " + "lk_owner(%s)) - expected(%s) - result(%s)\n", + l1_start, l1_len, l1_owner, l2_start, l2_len, l2_owner, + (should_fail ? "FAIL" : "SUCCESS"), + (ret ? "FAIL" : "SUCCESS")); + return f_ret; +} + +int +main (int argc, char *argv[]) +{ + glfs_t *fs = NULL; + int ret = 0, i, status = 0; + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd3 = NULL; + char *filename = "file_tmp"; + char *volname = NULL; + char *logfile = NULL; + char *hostname = NULL; + + if (argc != 4) { + fprintf (stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new (volname); + if (!fs) { + fprintf (stderr, "glfs_new: returned NULL\n"); + return -1; + } + + ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging (fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init (fs); + LOG_ERR("glfs_init", ret); + + fd1 = glfs_creat(fs, filename, O_RDWR|O_SYNC, 0644); + if (fd1 <= 0) { + ret = -1; + LOG_ERR ("glfs_creat", ret); + } + fprintf (stderr, "glfs-create fd1 - %d\n", fd1); + + fd2 = glfs_dup(fd1); + fprintf (stderr, "glfs-dup fd2 - %d\n", fd2); + + fd3 = glfs_open(fs, filename, O_RDWR|O_SYNC); + if (fd2 <= 0) { + ret = -1; + LOG_ERR ("glfs_open", ret); + } + fprintf (stderr, "glfs-open fd3 - %d\n", fd3); + + /* TEST 1: Conflicting ranges, same lk_owner + * lock1 (0, 10, lownera) + * lock2 (5, 10, lownera) + * Expected: should not fail but get merged + */ + ret = lock_test (fd1, fd2, false, 0, 10, lownera, 8, + 5, 10, lownera, 8); + LOG_ERR ("==== glfs_lock_test_1", ret); + + /* TEST 2: Conflicting ranges, different lk_owner + * lock1 (0, 10, lownera) - already taken + * lock2 (5, 10, lownerb) + * Expected: should fail and not get merged + */ + ret = lock_test (NULL, fd2, true, 0, 10, lownera, 8, + 5, 10, lownerb, 8); + LOG_ERR ("==== glfs_lock_test_2", ret); + + /* TEST 3: Different ranges, same lk_owner + * lock1 (0, 10, lownera) - already taken + * lock2 (30, 10, lownera) + * Expected: should not fail + */ + ret = lock_test (NULL, fd2, false, 0, 10, lownera, 8, + 30, 10, lownera, 8); + LOG_ERR ("==== glfs_lock_test_3", ret); + + /* TEST 4: Conflicting ranges, different lk_owner + * lock1 (0, 10, lownera) - already taken + * lock2 (50, 10, lownerb) + * Expected: should not fail + */ + ret = lock_test (NULL, fd2, false, 0, 10, lownera, 8, + 50, 10, lownerb, 8); + LOG_ERR ("==== glfs_lock_test_4", ret); + + /* TEST 5: Close fd1 & retry TEST2 + * lock1 (not applicable) + * lock2 (5, 10, lownerb) + * Expected: should succeed now + */ + ret = glfs_close(fd1); + LOG_ERR ("glfs_close", ret); + + ret = lock_test (NULL, fd2, false, 0, 10, lownera, 8, + 5, 10, lownerb, 8); + LOG_ERR ("==== glfs_lock_test_5", ret); + + /* TEST 6: Check closing fd1 doesn't flush fd2 locks + * retry TEST 4 but with fd2 and fd3. + * lock1 (50, 10, lownerb) - already taken + * lock2 (55, 10, lownerc) + * Expected: should fail + */ + ret = lock_test (NULL, fd3, true, 50, 10, lownerb, 8, + 55, 10, lownerc, 8); + LOG_ERR ("==== glfs_lock_test_6", ret); + +err: + ret = glfs_close(fd2); + LOG_ERR ("glfs_close", ret); + + ret = glfs_close(fd3); + LOG_ERR ("glfs_close", ret); + +out: + if (fs) { + ret = glfs_fini(fs); + fprintf (stderr, "glfs_fini(fs) returned %d\n", ret); + } + + if (ret) + exit(1); + exit(0); +} diff --git a/tests/basic/gfapi/glfd-lkowner.t b/tests/basic/gfapi/glfd-lkowner.t new file mode 100755 index 00000000000..ad7b0260a14 --- /dev/null +++ b/tests/basic/gfapi/glfd-lkowner.t @@ -0,0 +1,27 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 $H0:$B0/brick1; +EXPECT 'Created' volinfo_field $V0 'Status'; + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/glfd-lkowner.c -lgfapi + +TEST ./$(dirname $0)/glfd-lkowner $H0 $V0 $logdir/glfd-lkowner.log + +cleanup_tester $(dirname $0)/glfd-lkowner + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; |