#include #include #include #include #include #include #include #include /* 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_FAIL); 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_FAIL); 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 \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; }