diff options
author | Susant Palai <spalai@redhat.com> | 2018-11-30 15:04:17 +0530 |
---|---|---|
committer | Amar Tumballi <amarts@redhat.com> | 2019-01-17 15:33:42 +0000 |
commit | ebaf09a2a329517936232510e117debc3795e80b (patch) | |
tree | a3ce4c023b7ffce538ac31e3b3829c2267bbc2d0 /tests/basic | |
parent | 11cf73bc4173c13a9de54ea8d816eb72d8b01f48 (diff) |
lock: Add fencing support
design reference: https://review.gluster.org/#/c/glusterfs-specs/+/21925/
This patch adds the lock preempt support.
Note: The current model stores lock enforcement information as separate
xattr on disk. There is another effort going in parallel to store this
in stat(x) of the file. This patch is self sufficient to add fencing
support. Based on the availability of the stat(x) support either I will
rebase this patch or we can modify the necessary bits post merging this
patch.
Change-Id: If4a42f3e0afaee1f66cdb0360ad4e0c005b5b017
updates: #466
Signed-off-by: Susant Palai <spalai@redhat.com>
Diffstat (limited to 'tests/basic')
-rw-r--r-- | tests/basic/fencing/fence-basic.c | 229 | ||||
-rwxr-xr-x | tests/basic/fencing/fence-basic.t | 29 | ||||
-rw-r--r-- | tests/basic/fencing/fencing-crash-conistency.t | 61 |
3 files changed, 319 insertions, 0 deletions
diff --git a/tests/basic/fencing/fence-basic.c b/tests/basic/fencing/fence-basic.c new file mode 100644 index 00000000000..4aa452e19b0 --- /dev/null +++ b/tests/basic/fencing/fence-basic.c @@ -0,0 +1,229 @@ +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define NO_INIT 1 +#define GF_ENFORCE_MANDATORY_LOCK "trusted.glusterfs.enforce-mandatory-lock" + +FILE *fp; +char *buf = "0123456789"; + +#define LOG_ERR(func, err) \ + do { \ + if (!fp) { \ + fprintf(stderr, "%\n%d %s : returned error (%s)\n", __LINE__, \ + func, strerror(err)); \ + fflush(stderr); \ + } else { \ + fprintf(fp, "\n%d %s : returned error (%s)\n", __LINE__, func, \ + strerror(err)); \ + fflush(fp); \ + } \ + } while (0) + +glfs_t * +setup_new_client(char *hostname, char *volname, char *log_file, int flag) +{ + int ret = 0; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + fprintf(fp, "\nglfs_new: returned NULL (%s)\n", strerror(errno)); + goto error; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + fprintf(fp, "\nglfs_set_volfile_server failed ret:%d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_set_logging(fs, log_file, 7); + if (ret < 0) { + fprintf(fp, "\nglfs_set_logging failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + + if (flag == NO_INIT) + goto out; + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(fp, "\nglfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + +out: + return fs; +error: + return NULL; +} + +/* test plan + * + * - take mandatory lock from client 1 + * - preempt mandatory lock from client 2 + * - write from client 1 which should fail + */ + +int +test(glfs_t *fs1, glfs_t *fs2, char *fname) +{ + struct flock lock; + int ret = 0; + glfs_fd_t *fd1, *fd2 = NULL; + + fd1 = glfs_creat(fs1, fname, O_RDWR, 0777); + if (ret) { + LOG_ERR("glfs_creat", errno); + ret = -1; + goto out; + } + + fd2 = glfs_open(fs2, fname, O_RDWR | O_NONBLOCK); + if (ret) { + LOG_ERR("glfs_open", errno); + ret = -1; + goto out; + } + + /* initialize lock */ + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 100; + + ret = glfs_fsetxattr(fd1, GF_ENFORCE_MANDATORY_LOCK, "set", 8, 0); + if (ret < 0) { + LOG_ERR("glfs_fsetxattr", errno); + ret = -1; + goto out; + } + + /* take a write mandatory lock */ + ret = glfs_file_lock(fd1, F_SETLKW, &lock, GLFS_LK_MANDATORY); + if (ret) { + LOG_ERR("glfs_file_lock", errno); + goto out; + } + + ret = glfs_write(fd1, buf, 10, 0); + if (ret != 10) { + LOG_ERR("glfs_write", errno); + ret = -1; + goto out; + } + + /* write should fail */ + ret = glfs_write(fd2, buf, 10, 0); + if (ret != -1) { + LOG_ERR("glfs_write", errno); + ret = -1; + goto out; + } + + /* preempt mandatory lock from client 1*/ + ret = glfs_file_lock(fd2, F_SETLKW, &lock, GLFS_LK_MANDATORY); + if (ret) { + LOG_ERR("glfs_file_lock", errno); + goto out; + } + + /* write should succeed from client 2 */ + ret = glfs_write(fd2, buf, 10, 0); + if (ret == -1) { + LOG_ERR("glfs_write", errno); + goto out; + } + + /* write should fail from client 1 */ + ret = glfs_write(fd1, buf, 10, 0); + if (ret == 10) { + LOG_ERR("glfs_write", errno); + ret = -1; + goto out; + } + + ret = 0; + +out: + if (fd1) { + glfs_close(fd1); + } + + if (fd2) { + glfs_close(fd2); + } + + return ret; +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + glfs_t *fs1 = NULL; + glfs_t *fs2 = NULL; + char *volname = NULL; + char log_file[100]; + char *hostname = NULL; + char *fname = "/file"; + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + + if (argc != 4) { + fprintf( + stderr, + "Expect following args %s <hostname> <Vol> <log file location>\n", + argv[0]); + return -1; + } + + hostname = argv[1]; + volname = argv[2]; + + sprintf(log_file, "%s/%s", argv[3], "fence-basic.log"); + fp = fopen(log_file, "w"); + if (!fp) { + fprintf(stderr, "\nfailed to open %s\n", log_file); + fflush(stderr); + return -1; + } + + sprintf(log_file, "%s/%s", argv[3], "glfs-client-1.log"); + fs1 = setup_new_client(hostname, volname, log_file, 0); + if (!fs1) { + LOG_ERR("setup_new_client", errno); + return -1; + } + + sprintf(log_file, "%s/%s", argv[3], "glfs-client-2.log"); + fs2 = setup_new_client(hostname, volname, log_file, 0); + if (!fs2) { + LOG_ERR("setup_new_client", errno); + ret = -1; + goto error; + } + + ret = test(fs1, fs2, fname); + +error: + if (fs1) { + glfs_fini(fs1); + } + + if (fs2) { + glfs_fini(fs2); + } + + fclose(fp); + + return ret; +} diff --git a/tests/basic/fencing/fence-basic.t b/tests/basic/fencing/fence-basic.t new file mode 100755 index 00000000000..080507c2ba5 --- /dev/null +++ b/tests/basic/fencing/fence-basic.t @@ -0,0 +1,29 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +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'; + +TEST $CLI volume set $V0 diagnostics.client-log-flush-timeout 30 +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 locks.mandatory-locking forced + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/fence-basic.c -lgfapi -ggdb +TEST $(dirname $0)/fence-basic $H0 $V0 $logdir + +cleanup_tester $(dirname $0)/fence-basic + +cleanup;
\ No newline at end of file diff --git a/tests/basic/fencing/fencing-crash-conistency.t b/tests/basic/fencing/fencing-crash-conistency.t new file mode 100644 index 00000000000..cca8ee7343f --- /dev/null +++ b/tests/basic/fencing/fencing-crash-conistency.t @@ -0,0 +1,61 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +# with lock enforcement flag write should fail with out lock + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 $H0:$B0/${V0}1 +EXPECT 'Created' volinfo_field $V0 'Status'; +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +TEST $CLI volume set $V0 performance.write-behind off +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +TEST touch $M0/file + +#write should pass +TEST "echo "test" > $M0/file" +TEST "truncate -s 0 $M0/file" + +#enable mandatory locking +TEST $CLI volume set $V0 locks.mandatory-locking forced + +#write should pass +TEST "echo "test" >> $M0/file" +TEST "truncate -s 0 $M0/file" + +#enforce lock on the file +TEST setfattr -n trusted.glusterfs.enforce-mandatory-lock -v 1 $M0/file + +#write should fail +TEST ! "echo "test" >> $M0/file" +TEST ! "truncate -s 0 $M0/file" + +#remove lock enforcement flag +TEST setfattr -x trusted.glusterfs.enforce-mandatory-lock $M0/file + +#write should pass +TEST "echo "test" >> $M0/file" +TEST "truncate -s 0 $M0/file" + +#enforce lock on the file +TEST setfattr -n trusted.glusterfs.enforce-mandatory-lock -v 1 $M0/file +#kill brick +TEST kill_brick $V0 $H0 $B0/${V0}1 + +TEST $CLI volume start $V0 force + +# wait one second for the brick to come online +sleep 2 +#write should fail (lock xlator gets lock enforcement info from disk) +TEST ! "echo "test" >> $M0/file" +TEST ! "truncate -s 0 $M0/file" + +cleanup;
\ No newline at end of file |