projects/linux·blob master · refs

120 lines · 2.8 KiB

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
11static 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 ksft_perror("fcntl()");
20 return ret;
21}
22
23static 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 ksft_perror("fcntl()");
32 return ret;
33}
34
35int 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 ksft_print_header();
43 ksft_set_plan(4);
44
45 unlink("/tmp/aa");
46 assert(fd != -1);
47 assert(fd2 != -1);
48 ksft_print_msg("opened fds %i %i\n", fd, fd2);
49
50 /* Set some read lock */
51 fl.l_type = F_RDLCK;
52 fl.l_start = 5;
53 fl.l_len = 3;
54 rc = lock_set(fd, &fl);
55 ksft_test_result(rc == 0, "set OFD read lock on first fd\n");
56 if (rc != 0)
57 ksft_finished();
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 ksft_finished();
66 if (fl.l_type != F_UNLCK)
67 ksft_exit_fail_msg("read locks conflicted\n");
68
69 /* Make sure read/write locks do conflict on different fds. */
70 fl.l_type = F_WRLCK;
71 fl.l_start = 5;
72 fl.l_len = 1;
73 rc = lock_get(fd2, &fl);
74 if (rc != 0)
75 ksft_finished();
76 ksft_test_result(fl.l_type != F_UNLCK,
77 "read and write locks conflicted\n");
78 if (fl.l_type == F_UNLCK)
79 ksft_finished();
80
81 /* Get info about the lock on first fd. */
82 fl.l_type = F_UNLCK;
83 fl.l_start = 5;
84 fl.l_len = 1;
85 rc = lock_get(fd, &fl);
86 if (rc != 0)
87 ksft_exit_fail_msg("F_OFD_GETLK with F_UNLCK not supported\n");
88 ksft_test_result(fl.l_type != F_UNLCK,
89 "F_OFD_GETLK with F_UNLCK returned lock info\n");
90 if (fl.l_type == F_UNLCK)
91 ksft_exit_fail();
92 ksft_print_msg("F_UNLCK test returns: locked, type %i pid %i len %zi\n",
93 fl.l_type, fl.l_pid, fl.l_len);
94
95 /* Try the same but by locking everything by len==0. */
96 fl2.l_type = F_UNLCK;
97 fl2.l_start = 0;
98 fl2.l_len = 0;
99 rc = lock_get(fd, &fl2);
100 if (rc != 0)
101 ksft_exit_fail_msg
102 ("F_OFD_GETLK with F_UNLCK not supported\n");
103 ksft_test_result(memcmp(&fl, &fl2, sizeof(fl)) == 0,
104 "F_UNLCK with len==0 returned the same\n");
105 if (memcmp(&fl, &fl2, sizeof(fl))) {
106 ksft_exit_fail_msg
107 ("F_UNLCK test returns: locked, type %i pid %i len %zi\n",
108 fl.l_type, fl.l_pid, fl.l_len);
109 }
110
111 /* Get info about the lock on second fd - no locks on it. */
112 fl.l_type = F_UNLCK;
113 fl.l_start = 0;
114 fl.l_len = 0;
115 lock_get(fd2, &fl);
116 ksft_test_result(fl.l_type == F_UNLCK,
117 "F_OFD_GETLK with F_UNLCK return lock info from another fd\n");
118
119 ksft_finished();
120}