Skip to content

Commit bfe2e8f

Browse files
stspjtlayton
authored andcommitted
selftests: add OFD lock tests
Test the basic locking stuff on 2 fds: multiple read locks, conflicts between read and write locks, use of len==0 for queries. Also tests for F_UNLCK F_OFD_GETLK extension. [ jlayton: fix unlink() pathname in selftest ] Cc: Jeff Layton <[email protected]> Cc: Chuck Lever <[email protected]> Cc: Alexander Viro <[email protected]> Cc: Christian Brauner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: Shuah Khan <[email protected]> Cc: [email protected] Cc: [email protected] Signed-off-by: Stas Sergeev <[email protected]> Signed-off-by: Jeff Layton <[email protected]>
1 parent 6c9007f commit bfe2e8f

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
TEST_GEN_PROGS := ofdlocks
4+
5+
include ../lib.mk
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#define _GNU_SOURCE
4+
#include <fcntl.h>
5+
#include <assert.h>
6+
#include <stdio.h>
7+
#include <unistd.h>
8+
#include <string.h>
9+
#include "../kselftest.h"
10+
11+
static int lock_set(int fd, struct flock *fl)
12+
{
13+
int ret;
14+
15+
fl->l_pid = 0; // needed for OFD locks
16+
fl->l_whence = SEEK_SET;
17+
ret = fcntl(fd, F_OFD_SETLK, fl);
18+
if (ret)
19+
perror("fcntl()");
20+
return ret;
21+
}
22+
23+
static int lock_get(int fd, struct flock *fl)
24+
{
25+
int ret;
26+
27+
fl->l_pid = 0; // needed for OFD locks
28+
fl->l_whence = SEEK_SET;
29+
ret = fcntl(fd, F_OFD_GETLK, fl);
30+
if (ret)
31+
perror("fcntl()");
32+
return ret;
33+
}
34+
35+
int main(void)
36+
{
37+
int rc;
38+
struct flock fl, fl2;
39+
int fd = open("/tmp/aa", O_RDWR | O_CREAT | O_EXCL, 0600);
40+
int fd2 = open("/tmp/aa", O_RDONLY);
41+
42+
unlink("/tmp/aa");
43+
assert(fd != -1);
44+
assert(fd2 != -1);
45+
ksft_print_msg("[INFO] opened fds %i %i\n", fd, fd2);
46+
47+
/* Set some read lock */
48+
fl.l_type = F_RDLCK;
49+
fl.l_start = 5;
50+
fl.l_len = 3;
51+
rc = lock_set(fd, &fl);
52+
if (rc == 0) {
53+
ksft_print_msg
54+
("[SUCCESS] set OFD read lock on first fd\n");
55+
} else {
56+
ksft_print_msg("[FAIL] to set OFD read lock on first fd\n");
57+
return -1;
58+
}
59+
/* Make sure read locks do not conflict on different fds. */
60+
fl.l_type = F_RDLCK;
61+
fl.l_start = 5;
62+
fl.l_len = 1;
63+
rc = lock_get(fd2, &fl);
64+
if (rc != 0)
65+
return -1;
66+
if (fl.l_type != F_UNLCK) {
67+
ksft_print_msg("[FAIL] read locks conflicted\n");
68+
return -1;
69+
}
70+
/* Make sure read/write locks do conflict on different fds. */
71+
fl.l_type = F_WRLCK;
72+
fl.l_start = 5;
73+
fl.l_len = 1;
74+
rc = lock_get(fd2, &fl);
75+
if (rc != 0)
76+
return -1;
77+
if (fl.l_type != F_UNLCK) {
78+
ksft_print_msg
79+
("[SUCCESS] read and write locks conflicted\n");
80+
} else {
81+
ksft_print_msg
82+
("[SUCCESS] read and write locks not conflicted\n");
83+
return -1;
84+
}
85+
/* Get info about the lock on first fd. */
86+
fl.l_type = F_UNLCK;
87+
fl.l_start = 5;
88+
fl.l_len = 1;
89+
rc = lock_get(fd, &fl);
90+
if (rc != 0) {
91+
ksft_print_msg
92+
("[FAIL] F_OFD_GETLK with F_UNLCK not supported\n");
93+
return -1;
94+
}
95+
if (fl.l_type != F_UNLCK) {
96+
ksft_print_msg
97+
("[SUCCESS] F_UNLCK test returns: locked, type %i pid %i len %zi\n",
98+
fl.l_type, fl.l_pid, fl.l_len);
99+
} else {
100+
ksft_print_msg
101+
("[FAIL] F_OFD_GETLK with F_UNLCK did not return lock info\n");
102+
return -1;
103+
}
104+
/* Try the same but by locking everything by len==0. */
105+
fl2.l_type = F_UNLCK;
106+
fl2.l_start = 0;
107+
fl2.l_len = 0;
108+
rc = lock_get(fd, &fl2);
109+
if (rc != 0) {
110+
ksft_print_msg
111+
("[FAIL] F_OFD_GETLK with F_UNLCK not supported\n");
112+
return -1;
113+
}
114+
if (memcmp(&fl, &fl2, sizeof(fl))) {
115+
ksft_print_msg
116+
("[FAIL] F_UNLCK test returns: locked, type %i pid %i len %zi\n",
117+
fl.l_type, fl.l_pid, fl.l_len);
118+
return -1;
119+
}
120+
ksft_print_msg("[SUCCESS] F_UNLCK with len==0 returned the same\n");
121+
/* Get info about the lock on second fd - no locks on it. */
122+
fl.l_type = F_UNLCK;
123+
fl.l_start = 0;
124+
fl.l_len = 0;
125+
lock_get(fd2, &fl);
126+
if (fl.l_type != F_UNLCK) {
127+
ksft_print_msg
128+
("[FAIL] F_OFD_GETLK with F_UNLCK return lock info from another fd\n");
129+
return -1;
130+
}
131+
return 0;
132+
}

0 commit comments

Comments
 (0)