* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, Whamcloud, Inc.
+ * Copyright (c) 2011, 2014, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
va_end(ap);
rc = fcntl(fd, cmd);
if (rc == -1) {
+ rc = -errno;
fprintf(stderr, "fcntl GETFL failed: %s\n",
strerror(errno));
- return(1);
+ return rc;
}
break;
case F_SETFL:
va_end(ap);
rc = fcntl(fd, cmd, arg);
if (rc == -1) {
+ rc = -errno;
fprintf(stderr, "fcntl SETFL %ld failed: %s\n",
arg, strerror(errno));
- return(1);
+ return rc ;
}
break;
case F_GETLK:
va_end(ap);
rc = fcntl(fd, cmd, lock);
if (rc == -1) {
+ rc = -errno;
fprintf(stderr, "fcntl cmd %d failed: %s\n",
cmd, strerror(errno));
- return(1);
+ return rc ;
}
break;
case F_DUPFD:
va_end(ap);
rc = fcntl(fd, cmd, arg);
if (rc == -1) {
+ rc = -errno;
fprintf(stderr, "fcntl F_DUPFD %d failed: %s\n",
(int)arg, strerror(errno));
- return(1);
+ return rc;
}
break;
default:
va_end(ap);
fprintf(stderr, "fcntl cmd %d not supported\n", cmd);
- return(1);
+ return rc;
}
return rc;
}
int fd;
int mount_with_flock = 0;
int error = 0;
+ int rc = 0;
if (argc != 5) {
t1_usage();
}
if ((fd = open(argv[4], O_RDWR)) < 0) {
- fprintf(stderr, "Couldn't open file: %s\n", argv[3]);
+ fprintf(stderr, "Couldn't open file: %s\n", argv[4]);
return EXIT_FAILURE;
}
error = flock(fd, LOCK_EX);
} else {
t1_usage();
- return EXIT_FAILURE;
+ rc = EXIT_FAILURE;
+ goto out;
}
if (mount_with_flock)
- return((error == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
+ rc = ((error == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
else
- return((error == 0) ? EXIT_FAILURE : EXIT_SUCCESS);
+ rc = ((error == 0) ? EXIT_FAILURE : EXIT_SUCCESS);
+
+out:
+ if (fd >= 0)
+ close(fd);
+ return rc;
}
/** ===============================================================
t_fcntl(fd, F_SETFL, O_APPEND);
rc = t_fcntl(fd, F_GETFL);
- if ((rc & O_APPEND) == 0) {
+ if ((rc < 0) || (rc & O_APPEND) == 0) {
fprintf(stderr, "error get flag: ret %x\n", rc);
- return EXIT_FAILURE;
+ rc = EXIT_FAILURE;
+ goto out;
}
ta.lock = &lock;
}
if ((fd = open(argv[2], O_RDWR)) < 0) {
- fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ fprintf(stderr, "Couldn't open file: %s\n", argv[2]);
return EXIT_FAILURE;
}
if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
goto out;
}
if ((fd2 = open(argv[2], O_RDWR)) < 0) {
- fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ fprintf(stderr, "Couldn't open file: %s\n", argv[2]);
rc = EXIT_FAILURE;
goto out;
}
return rc;
}
+int t4(int argc, char *argv[])
+{
+ struct flock lock = {
+ .l_type = F_WRLCK,
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 10,
+ };
+
+ int fd, fd2;
+ pid_t child_pid;
+ int child_status;
+ int rc = EXIT_SUCCESS;
+
+ if (argc != 4) {
+ fprintf(stderr, "Usage: ./flocks_test 4 file1 file2\n");
+ return EXIT_FAILURE;
+ }
+
+ if ((fd = open(argv[2], O_RDWR)) < 0) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+ if ((fd2 = open(argv[3], O_RDWR)) < 0) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[3]);
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ child_pid = fork();
+ if (child_pid < 0) {
+ perror("fork");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ if (child_pid == 0) {
+ printf("%d: get lock1\n", getpid());
+ fflush(stdout);
+ if (t_fcntl(fd, F_SETLKW, &lock) < 0) {
+ fprintf(stderr, "%d: cannot get lock1: %s\n",
+ getpid(), strerror(errno));
+ rc = EXIT_FAILURE;
+ goto out_child;
+ }
+ printf("%d: done\n", getpid());
+ sleep(3);
+ printf("%d: get lock2\n", getpid());
+ fflush(stdout);
+ if (t_fcntl(fd2, F_SETLKW, &lock) < 0) {
+ fprintf(stderr, "%d: cannot get lock2: %s\n",
+ getpid(), strerror(errno));
+
+ if (errno == EDEADLK)
+ rc = EXIT_SUCCESS;
+ else
+ rc = EXIT_FAILURE;
+
+ goto out_child;
+ }
+ printf("%d: done\n", getpid());
+out_child:
+ printf("%d: exit rc=%d\n", getpid(), rc);
+ exit(rc);
+ } else {
+ printf("%d: get lock2\n", getpid());
+ fflush(stdout);
+ if (t_fcntl(fd2, F_SETLKW, &lock) < 0) {
+ fprintf(stderr, "%d: cannot get lock2: %s\n",
+ getpid(), strerror(errno));
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+ printf("%d: done\n", getpid());
+ sleep(3);
+ printf("%d: get lock1\n", getpid());
+ fflush(stdout);
+ if (t_fcntl(fd, F_SETLKW, &lock) < 0) {
+ fprintf(stderr, "%d: cannot get lock1: %s\n",
+ getpid(), strerror(errno));
+
+ if (errno != EDEADLK) {
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+ }
+ printf("%d: done\n", getpid());
+ }
+
+ sleep(1);
+
+ if (close(fd) < 0) {
+ fprintf(stderr, "%d: error closing file1: %s\n",
+ getpid(), strerror(errno));
+ rc = EXIT_FAILURE;
+ }
+
+ if (close(fd2) < 0) {
+ fprintf(stderr, "%d: error closing file2: %s\n",
+ getpid(), strerror(errno));
+ rc = EXIT_FAILURE;
+ }
+
+ if (waitpid(child_pid, &child_status, 0) < 0) {
+ fprintf(stderr, "%d: cannot get termination status of %d: %s\n",
+ getpid(), child_pid, strerror(errno));
+ rc = EXIT_FAILURE;
+ } else if (!WIFEXITED(child_status)) {
+ fprintf(stderr, "%d: child %d terminated with status %d\n",
+ getpid(), child_pid, child_status);
+ rc = EXIT_FAILURE;
+ } else {
+ rc = WEXITSTATUS(child_status);
+ }
+
+out:
+ printf("%d: exit rc=%d\n", getpid(), rc);
+ return rc;
+}
+
+#define T5_USAGE \
+ "Usage: ./flocks_test 5 set|get|unlock [read|write] [sleep N] file1\n"\
+" set: F_SETLKW F_WRLCK\n" \
+" get: F_GETLK F_WRLCK (conflict)\n" \
+" unlock: F_SETLKW F_UNLCK\n" \
+" read|write: lock mode, write by default\n" \
+" sleep N: sleep for N secs after fcntl\n" \
+" file1: fcntl is called for this file\n"
+
+int t5(int argc, char *argv[])
+{
+ struct flock lock = {
+ .l_type = F_WRLCK,
+ .l_whence = SEEK_SET,
+ };
+
+ int setlk = 0, getlk = 0, unlk = 0, secs = 0;
+ int pos;
+ int fd;
+ int rc = 0;
+
+ if (argc < 4 || argc > 7) {
+ fprintf(stderr, T5_USAGE);
+ return EXIT_FAILURE;
+ }
+
+ if (!strncmp(argv[2], "set", 4))
+ setlk = 1;
+ else if (!strncmp(argv[2], "get", 4))
+ getlk = 1;
+ else if (!strncmp(argv[2], "unlock", 7))
+ unlk = 1;
+ else {
+ fprintf(stderr, "Wrong 2nd argument: %s\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ pos = 3;
+
+ if (!strncmp(argv[pos], "read", 5)) {
+ lock.l_type = F_RDLCK;
+ pos++;
+ } else if (!strncmp(argv[pos], "write", 6)) {
+ lock.l_type = F_WRLCK;
+ pos++;
+ }
+
+ if (!strncmp(argv[pos], "sleep", 6)) {
+ secs = atoi(argv[pos + 1]);
+ if (secs < 0 || secs > 10) {
+ fprintf(stderr, "Sleep argument is wrong: %s\n",
+ argv[pos + 1]);
+ return EXIT_FAILURE;
+ }
+ pos += 2;
+ }
+
+ fd = open(argv[pos], O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[pos]);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(stderr, "\nFLOCKS_TEST 5: %s %s flock\n",
+ setlk ? "SET" : getlk ? "GET" : "UNLOCK",
+ lock.l_type == F_WRLCK ? "write" : "read");
+
+ if (setlk) {
+ rc = t_fcntl(fd, F_SETLKW, &lock);
+ } else if (getlk) {
+ rc = t_fcntl(fd, F_GETLK, &lock);
+ } else if (unlk) {
+ lock.l_type = F_UNLCK;
+ rc = t_fcntl(fd, F_SETLKW, &lock);
+ }
+
+ if (secs)
+ sleep(secs);
+
+ close(fd);
+ return rc < 0 ? -rc : 0;
+
+}
/** ==============================================================
* program entry
case 3:
rc = t3(argc, argv);
break;
- default:
+ case 4:
+ rc = t4(argc, argv);
+ break;
+ case 5:
+ rc = t5(argc, argv);
+ break;
+ default:
fprintf(stderr, "unknow test number %s\n", argv[1]);
break;
}