diff options
Diffstat (limited to 'tests/features/glfs-lease.c')
| -rw-r--r-- | tests/features/glfs-lease.c | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/tests/features/glfs-lease.c b/tests/features/glfs-lease.c new file mode 100644 index 00000000000..e82cd875b38 --- /dev/null +++ b/tests/features/glfs-lease.c @@ -0,0 +1,717 @@ +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> + +/* Few rules: + * 1. A client may have multiple lease keys, but a lease key cannot be shared by + * multiple clients. + * 2. Lease key can be set before open, or in glfs_lease request. A lease key + * set like this is valid for the lifetime of the fd, i.e. a fd cannot have + * multiple lease key. But a lease key can be shared across multiple fds. + */ +glfs_t *client1 = NULL, *client2 = NULL, *client3 = NULL, *client4 = NULL; +glfs_fd_t *fd1 = NULL, *fd2 = NULL, *fd3 = NULL, *fd4 = NULL; +FILE *log_file = NULL; +char lid1[GLFS_LEASE_ID_SIZE] = "lid1-clnt1", + lid2[GLFS_LEASE_ID_SIZE] = "lid2-clnt2"; +char lid3[GLFS_LEASE_ID_SIZE] = "lid3-clnt2", lid4[GLFS_LEASE_ID_SIZE] = { + 0, +}; +char *volname = NULL, *glfs_log_file = NULL; + +#define MAX_CLIENTS 4 +#define MAX_FDS 4 +#define TEST_FILE "/test/lease" +#define SHUD_PASS 0 +#define SHUD_FAIL -1 +#define NONE 0 + +static void +recall_cbk(struct glfs_lease lease, void *data); + +static int +set_read_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, fd); + if (ret < 0) { + fprintf(log_file, "\n RD_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Took RD_LEASE"); + return ret; +} + +static int +set_write_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RW_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n RW_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Took RW_LEASE"); + return ret; +} + +static int +get_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_GET_LEASE; + lease.lease_type = -1; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n GET_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + if (lease.lease_type == GLFS_RD_LEASE) + fprintf(log_file, "\n Esisting Lease: RD_LEASE"); + else if (lease.lease_type == GLFS_RW_LEASE) + fprintf(log_file, "\n Esisting Lease: RW_LEASE"); + else if (lease.lease_type == 3) + fprintf(log_file, "\n Esisting Lease: RD_LEASE|RW_LEASE"); + else if (lease.lease_type == 0) + fprintf(log_file, "\n Esisting Lease: NONE"); + else + fprintf(log_file, "\n Existing lease type:%d", lease.lease_type); + return lease.lease_type; +} + +static int +unlk_write_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_UNLK_LEASE; + lease.lease_type = GLFS_RW_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n Unlock RW_LESAE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Unlocked RW_LEASE"); + return ret; +} + +static int +unlk_read_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_UNLK_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n Unlock RD_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Unlocked RD_LEASE"); + return ret; +} + +glfs_t * +setup_new_client(char *volname, char *log_fileile) +{ + int ret = 0; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + fprintf(log_file, "\nglfs_new: returned NULL (%s)\n", strerror(errno)); + goto error; + } + + ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + if (ret < 0) { + fprintf(log_file, "\nglfs_set_volfile_server failed ret:%d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_set_logging(fs, log_fileile, 7); + if (ret < 0) { + fprintf(log_file, "\nglfs_set_logging failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(log_file, "\nglfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + return fs; +error: + return NULL; +} + +#define OPEN(client, flags, fd, lease_id) \ + do { \ + int ret_val = 0; \ + ret_val = glfs_setfsleaseid(lease_id); \ + if (ret_val) { \ + fprintf(log_file, \ + "\nglfs_setfsleaseid failed with ret: %d (%s)\n", ret, \ + strerror(errno)); \ + return -1; \ + } \ + fd = glfs_open(client, TEST_FILE, flags); \ + if (fd == NULL) { \ + fprintf(log_file, "\nglfs_open failed with ret: %d (%s)\n", ret, \ + strerror(errno)); \ + return -1; \ + } \ + } while (0) + +#define VERIFY_RESULT(test_case, ret, value) \ + do { \ + if (ret != value) { \ + fprintf(log_file, \ + "\n Testcase %d failed, ret = %d, value=%d\n", \ + test_case, ret, value); \ + goto error; /*test unsuccessful*/ \ + } \ + fprintf(log_file, "\n Testcase %d Succeeded\n", test_case); \ + } while (0) + +static void +recall_cbk(struct glfs_lease lease, void *data) +{ + int ret = -1; + char ld[GLFS_LEASE_ID_SIZE] = ""; + + fprintf(log_file, "\nRECALL received on lease_id:(%s)", lease.lease_id); + memcpy(ld, lease.lease_id, GLFS_LEASE_ID_SIZE); + ret = unlk_write_lease((glfs_fd_t *)data, ld); + VERIFY_RESULT(500, ret, SHUD_PASS); +error: + return; +} + +static int +testcase1_rd_lease() +{ + glfs_fd_t *fd1 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for Read lease:"); + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDONLY, fd1, lid1); + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_FAIL); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(3, ret, GLFS_RD_LEASE); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(4, ret, SHUD_FAIL); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(6, ret, NONE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(7, ret, SHUD_PASS); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase2_wr_lease() +{ + glfs_fd_t *fd1 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for Write lease:"); + /* Open fd on client 1 in WRonly mode */ + OPEN(client1, O_WRONLY, fd1, lid1); + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_FAIL); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(3, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(4, ret, GLFS_RW_LEASE); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(6, ret, NONE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(7, ret, SHUD_FAIL); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase3_rd_wr_lease() +{ + glfs_fd_t *fd1 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for Read Write lease:"); + /* Open fd on client 1 in WRonly mode */ + OPEN(client1, O_RDWR, fd1, lid1); + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(3, ret, (GLFS_RW_LEASE | GLFS_RD_LEASE)); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(5, ret, GLFS_RD_LEASE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(6, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(7, ret, NONE); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase4_rd_lease_multi_clnt() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for multi client Read lease:"); + + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDONLY, fd1, lid1); + + /* Open fd on client 2 in RW mode */ + OPEN(client2, O_RDONLY, fd2, lid2); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = set_read_lease(fd2, lid2); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(3, ret, GLFS_RD_LEASE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_read_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(6, ret, NONE); + + ret = get_lease(fd2, lid2); + VERIFY_RESULT(7, ret, NONE); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(9, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase5_openfd_multi_lid() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd3 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for multi lid openfd check:"); + + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDONLY, fd1, lid1); + + /* Open fd on client 2 in RW mode */ + OPEN(client2, O_RDWR, fd2, lid2); + OPEN(client2, O_RDWR, fd3, lid2); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT( + 1, ret, + SHUD_FAIL); /*As there are other openfds in WR mode from diff lid*/ + + ret = set_write_lease(fd2, lid2); + VERIFY_RESULT( + 2, ret, SHUD_FAIL); /*As thers is another fd in RD mode from diff lid */ + + ret = glfs_close(fd1); + VERIFY_RESULT(3, ret, SHUD_PASS); + + ret = set_write_lease(fd2, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_write_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(6, ret, SHUD_PASS); + + ret = glfs_close(fd3); + VERIFY_RESULT(7, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase6_openfd_same_lid() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd3 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for same lid openfd check:"); + + /* Open fd on client 2 in RW mode */ + OPEN(client1, O_RDWR, fd1, lid2); + OPEN(client1, O_RDWR, fd2, lid2); + + ret = set_write_lease(fd1, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = set_write_lease(fd2, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = set_read_lease(fd2, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_write_lease(fd1, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = unlk_read_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = unlk_write_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = glfs_close(fd1); + VERIFY_RESULT(6, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(7, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase7_rd_multi_lid() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for multi lease id Read lease:"); + + /* Open fd on client 1 in RD mode */ + OPEN(client2, O_RDONLY, fd1, lid2); + + /* Open fd on client 2 in RD mode */ + OPEN(client2, O_RDONLY, fd2, lid3); + + ret = set_read_lease(fd1, lid2); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = set_read_lease(fd2, lid3); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid2); + VERIFY_RESULT(3, ret, GLFS_RD_LEASE); + + ret = unlk_read_lease(fd1, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_read_lease(fd2, lid3); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid2); + VERIFY_RESULT(6, ret, NONE); + + ret = get_lease(fd2, lid3); + VERIFY_RESULT(7, ret, NONE); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(9, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase8_client_disconnect() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for client disconnect cleanup"); + + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDWR, fd1, lid1); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(2, ret, GLFS_RD_LEASE); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(3, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(4, ret, (GLFS_RD_LEASE | GLFS_RW_LEASE)); + + ret = glfs_fini(client1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + /* Open fd on client 2 in RD mode */ + OPEN(client2, O_RDONLY, fd2, lid3); + + ret = get_lease(fd2, lid3); + VERIFY_RESULT(6, ret, NONE); + + ret = glfs_close(fd2); + VERIFY_RESULT(7, ret, SHUD_PASS); + + client1 = setup_new_client(volname, glfs_log_file); + + return 0; +error: + return -1; +} + +static int +testcase9_recall_conflict_lease() +{ + struct glfs_object *obj = NULL; + glfs_fd_t *fd1 = NULL; + int ret = 0; + struct glfs_lease lease = { + 0, + }; + + fprintf(log_file, + "\n Basic test case for conflicting lease causing recall"); + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, lid2, GLFS_LEASE_ID_SIZE); + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDWR, fd1, lid1); + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + obj = glfs_h_lookupat(client2, NULL, TEST_FILE, NULL, 0); + ret = glfs_h_lease(client2, obj, &lease); + VERIFY_RESULT(2, ret, SHUD_FAIL); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + sleep(3); + ret = glfs_h_close(obj); + VERIFY_RESULT(3, ret, SHUD_PASS); + ret = glfs_close(fd1); + VERIFY_RESULT(4, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase10_recall_open_conflict() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for conflicting open causing recall"); + + /* Open fd on client 1 in RW mode */ + OPEN(client1, O_RDWR, fd1, lid1); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + /* Open fd on client 1 in RW mode */ + OPEN(client2, O_RDWR, fd2, lid2); + + /* TODO: Check for recall cbk functionality */ + ret = glfs_close(fd1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(3, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + int i = 0; + glfs_fd_t *fd = NULL; + glfs_fd_t *fd1 = NULL; + char *topdir = "topdir", *filename = "file1"; + char *buf = NULL; + int x = 0; + ssize_t xattr_size = -1; + + if (argc != 4) { + fprintf(stderr, + "Expect following args %s <Vol> <glfs client log file> " + "<testcase log file>\n", + argv[0]); + return -1; + } + + log_file = fopen(argv[3], "w"); + if (!log_file) + goto error; + + volname = argv[1]; + glfs_log_file = argv[2]; + + /* Setup 3 clients */ + client1 = setup_new_client(volname, glfs_log_file); + client2 = setup_new_client(volname, glfs_log_file); + client3 = setup_new_client(volname, glfs_log_file); + + ret = testcase1_rd_lease(); + VERIFY_RESULT(101, ret, SHUD_PASS); + + ret = testcase2_wr_lease(); + VERIFY_RESULT(102, ret, SHUD_PASS); + + ret = testcase3_rd_wr_lease(); + VERIFY_RESULT(103, ret, SHUD_PASS); + + ret = testcase4_rd_lease_multi_clnt(); + VERIFY_RESULT(104, ret, SHUD_PASS); + + ret = testcase5_openfd_multi_lid(); + VERIFY_RESULT(105, ret, SHUD_PASS); + + ret = testcase6_openfd_same_lid(); + VERIFY_RESULT(106, ret, SHUD_PASS); + + ret = testcase7_rd_multi_lid(); + VERIFY_RESULT(107, ret, SHUD_PASS); + + ret = testcase8_client_disconnect(); + VERIFY_RESULT(108, ret, SHUD_PASS); + + ret = testcase9_recall_conflict_lease(); + VERIFY_RESULT(109, ret, SHUD_PASS); + + ret = testcase10_recall_open_conflict(); + VERIFY_RESULT(110, ret, SHUD_PASS); + + glfs_fini(client1); + glfs_fini(client2); + glfs_fini(client3); + + fclose(log_file); + return 0; +error: + return -1; +} |
