/* Pre-requisites:- * * 1. Make sure that performance translators are switched off while running this test. * 2. Perform the following volume set operation: * # gluster volume set locks.mandatory-locking optimal * 3. For installation under non-standard paths, export LD_LIBRARY_PATH to * automatically load exact libgfapi.so and compile this C file as follows: * $ gcc mandatory-lock-optimal.c -lgfapi -I -L */ #include #include #include #include #include #include #include #define TOTAL_TEST_COUNT 8 /* C1 = Client 1 : C2 = Client 2 : C3 = Client 3 : * fs1, fd1 are associated with C1. Similarly fs2, fd2 for C2 * and fs3, fd3 for C3 */ FILE *fp; glfs_t *fs1, *fs2, *fs3; glfs_fd_t *fd, *fd1, *fd2, *fd3; struct flock lock; char buf1[10], *buf2 = "ten bytes!", *fname = "/mand.lock"; int ret, test_count; off_t offset; /* run_test_1 () : C1 takes byte range mandatory read lock. C2 attempts to read from a conflicting range. Expected result : Read from C2 should pass. * run_test_2 () : C1 takes byte range mandatory read lock. C2 attempts write to a conflicting range. Expected result : Write from C2 should fail with EAGAIN. * run_test_3 () : C1 takes byte range advisory write lock. C2 attempts to read from a conflicting range. Expected result : Read from C2 should pass. * run_test_4 () : C1 takes byte range advisory write lock. C2 attempts write to a conflicting range. Expected result : Write from C2 should pass. * run_test_5 () : C1 takes byte range advisory read lock. C2 attempts to open the same file with O_TRUNC. Expected result : Open from C2 should pass. * run_test_6 () : C1 takes byte range mandatory read lock. C2 attempts to open the same file with O_TRUNC. Expected result : Open from C2 should fail with EAGAIN. * run_test_7 () : C1 takes byte range mandatory read lock. C2 attempts ftruncate on a conflicting range. Expected result : Write from C2 should fail with EAGAIN. * run_test_8 () : C1 takes byte range advisory read lock. C2 takes byte range mandatory read lock within the byte range for which C1 already holds an advisory lock so as to perform a basic split/merge. C3 repositions fd3 to start of C2's byte range mandatory lock offset and attempts a write. Then it again repositions fd3 to one byte past C2's byte range mandatoy lock and again attempts a write. Expected result : First write should fail with EAGAIN. Second write should pass. */ #define LOG_ERR(func, err) do { \ if (!fp) \ fprintf (stderr, "\n%s : returned error (%s)\n", func, strerror (err)); \ else \ fprintf (fp, "\n%s : returned error (%s)\n", func, strerror (err)); \ cleanup_and_exit (err); \ } while (0) void cleanup_and_exit (int exit_status) { if (exit_status || test_count != TOTAL_TEST_COUNT) { fprintf (fp, "\nAborting due to some test failures.\n"); exit_status = 1; } else fprintf (fp, "\nAll tests ran successfully.\n"); if (fp) fclose (fp); if (fd) glfs_close (fd); if (fd1) glfs_close (fd1); if (fd2) glfs_close (fd2); glfs_unlink (fs1, fname); if (fs1) glfs_fini (fs1); if (fs2) glfs_fini (fs2); exit (exit_status); } glfs_t *new_client_create (char *hostname, char *volname, char *logfile_name) { glfs_t *fs = NULL; fs = glfs_new (volname); if (!fs) LOG_ERR ("glfs_new", errno); ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); if (ret) LOG_ERR ("glfs_set_volfile_server", errno); ret = glfs_set_logging (fs, logfile_name, 7); if (ret) LOG_ERR ("glfs_set_logging", errno); ret = glfs_init (fs); if (ret) LOG_ERR ("glfs_init", errno); return fs; } void run_test_1 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_RDONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 5L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_RDONLY | O_NONBLOCK); if (!fd2) LOG_ERR ("glfs_open", errno); /* On successful read, 0 is returned as there is no content inside the * file */ ret = glfs_read (fd2, buf1, 10, 0); if (ret) LOG_ERR ("glfs_read", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; ret = glfs_close (fd2); if (ret) LOG_ERR ("glfs_close", errno); fd2 = NULL; test_count++; fprintf (fp, "OK\n", i); } void run_test_2 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_RDONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 5L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_WRONLY | O_NONBLOCK); if (!fd2) LOG_ERR ("glfs_open", errno); ret = glfs_write (fd2, buf2, 10, 0); if (ret == 10 || errno != EAGAIN) LOG_ERR ("glfs_write", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; ret = glfs_close (fd2); if (ret) LOG_ERR ("glfs_close", errno); fd2 = NULL; test_count++; fprintf (fp, "OK\n", i); } void run_test_3 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_WRONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 5L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_RDONLY | O_NONBLOCK); if (!fd2) LOG_ERR ("glfs_open", errno); /* Still there is no content inside file. So following read should * return 0 */ ret = glfs_read (fd2, buf1, 10, 0); if (ret) LOG_ERR ("glfs_read", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; ret = glfs_close (fd2); if (ret) LOG_ERR ("glfs_close", errno); fd2 = NULL; test_count++; fprintf (fp, "OK\n", i); } void run_test_4 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_WRONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 5L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_WRONLY | O_NONBLOCK); if (!fd2) LOG_ERR ("glfs_open", errno); ret = glfs_write (fd2, buf2, 10, 0); if (ret != 10) LOG_ERR ("glfs_write", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; ret = glfs_close (fd2); if (ret) LOG_ERR ("glfs_close", errno); fd2 = NULL; test_count++; fprintf (fp, "OK\n", i); } void run_test_5 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_RDONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 5L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_RDONLY | O_NONBLOCK | O_TRUNC); if (!fd2) LOG_ERR ("glfs_open", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; ret = glfs_close (fd2); if (ret) LOG_ERR ("glfs_close", errno); fd2 = NULL; test_count++; fprintf (fp, "OK\n", i); } void run_test_6 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_RDONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 5L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_RDONLY | O_NONBLOCK | O_TRUNC); if (fd2) LOG_ERR ("glfs_open", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; test_count++; fprintf (fp, "OK\n", i); } void run_test_7 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_RDONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 5L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_RDWR | O_NONBLOCK); if (!fd2) LOG_ERR ("glfs_open", errno); ret = glfs_ftruncate (fd2, 4, NULL, NULL); if (ret == 0 || errno != EAGAIN) LOG_ERR ("glfs_ftruncate", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; ret = glfs_close (fd2); if (ret) LOG_ERR ("glfs_close", errno); fd2 = NULL; test_count++; fprintf (fp, "OK\n", i); } void run_test_8 (int i) { fprintf (fp, "\nRunning Test-%d . . . ", i); fd1 = glfs_open (fs1, fname, O_RDONLY | O_NONBLOCK); if (!fd1) LOG_ERR ("glfs_open", errno); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0L; lock.l_len = 10L; ret = glfs_file_lock (fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd2 = glfs_open (fs2, fname, O_RDONLY | O_NONBLOCK); if (!fd2) LOG_ERR ("glfs_open", errno); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 5L; lock.l_len = 2L; ret = glfs_file_lock (fd2, F_SETLK, &lock, GLFS_LK_MANDATORY); if (ret) LOG_ERR ("glfs_file_lock", errno); fd3 = glfs_open (fs3, fname, O_RDWR | O_NONBLOCK); if (!fd3) LOG_ERR ("glfs_open", errno); offset = glfs_lseek (fd3, 5L, SEEK_SET); if (offset != 5) LOG_ERR ("glfs_lseek", errno); ret = glfs_write (fd3, buf2, 10, 0); if (ret == 10 || errno != EAGAIN) LOG_ERR ("glfs_write", errno); offset = glfs_lseek (fd3, 8L, SEEK_SET); if (offset != 8) LOG_ERR ("glfs_lseek", errno); ret = glfs_write (fd3, buf2, 10, 0); if (ret != 10) LOG_ERR ("glfs_write", errno); ret = glfs_close (fd1); if (ret) LOG_ERR ("glfs_close", errno); fd1 = NULL; ret = glfs_close (fd2); if (ret) LOG_ERR ("glfs_close", errno); fd2 = NULL; ret = glfs_close (fd3); if (ret) LOG_ERR ("glfs_close", errno); fd3 = NULL; test_count++; fprintf (fp, "OK\n", i); } int main (int argc, char *argv[]) { char logfile[50]; if (argc != 4) { fprintf (stderr, "Usage: %s \n", argv[0]); return 0; } sprintf (logfile, "%s/%s", argv[3], "mandatory-lock-optimal-test.log"); fp = fopen (logfile, "w"); if (!fp) { fprintf (stderr, "\n%s\n", logfile); LOG_ERR ("Log file creation", errno); } sprintf (logfile, "%s/%s", argv[3], "glfs-client-1.log"); fs1 = new_client_create (argv[1], argv[2], logfile); if (!fs1) LOG_ERR ("client-1 creation", EINVAL); sprintf (logfile, "%s/%s", argv[3], "glfs-client-2.log"); fs2 = new_client_create (argv[1], argv[2], logfile); if (!fs2) LOG_ERR ("client-2 creation", EINVAL); sprintf (logfile, "%s/%s", argv[3], "glfs-client-3.log"); fs3 = new_client_create (argv[1], argv[2], logfile); if (!fs3) LOG_ERR ("client-3 creation", EINVAL); fd = glfs_creat (fs1, fname, O_RDWR, 0644); if (!fd) LOG_ERR ("glfs_creat", errno); test_count = 0; run_test_1 (1); run_test_2 (2); run_test_3 (3); run_test_4 (4); run_test_5 (5); run_test_6 (6); run_test_7 (7); run_test_8 (8); cleanup_and_exit (0); return 0; }