fixes for Power64
[tridge/junkcode.git] / locktest.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/fcntl.h>
5 #include <sys/stat.h>
6 #include <signal.h>
7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <sys/wait.h>
10
11 #define FNAME "locktest.dat"
12
13 #ifdef GLIBC_HACK_FCNTL64
14 /* this is a gross hack. 64 bit locking is completely screwed up on
15    i386 Linux in glibc 2.1.95 (which ships with RedHat 7.0). This hack
16    "fixes" the problem with the current 2.4.0test kernels 
17 */
18
19 #define fcntl fcntl64
20 #undef F_SETLKW 
21 #undef F_SETLK 
22 #define F_SETLK 13
23 #define F_SETLKW 14
24
25 #include <asm/unistd.h>
26 int fcntl64(int fd, int cmd, struct flock * lock)
27 {
28         return syscall(__NR_fcntl64, fd, cmd, lock);
29 }
30 #endif /* HACK_FCNTL64 */
31
32
33 static pid_t child_pid;
34
35 typedef unsigned long long ull;
36
37 static int brlock(int fd, off_t offset, size_t len, int set, int rw_type, int lck_type)
38 {
39         struct flock fl;
40
41         fl.l_type = set?rw_type:F_UNLCK;
42         fl.l_whence = SEEK_SET;
43         fl.l_start = offset;
44         fl.l_len = len;
45         fl.l_pid = 0;
46
47         if (fcntl(fd, lck_type, &fl) != 0) {
48                 return -1;
49         }
50         return 0;
51 }
52
53 static void child_main(int pfd)
54 {
55         int fd;
56         off_t ofs;
57         size_t len;
58         int ret;
59         char line[1000];
60         struct stat st;
61
62         while ((fd = open(FNAME,O_RDWR)) == -1) sleep(1);
63
64         while (1) {
65                 read(pfd, &ofs, sizeof(ofs));
66                 read(pfd, &len, sizeof(len));
67
68                 /* check that we can't lock that range */
69                 if (brlock(fd, ofs, len, 1, F_WRLCK, F_SETLK) == 0) {
70                         printf("ERROR: able to lock range %lld:%lld\n", (ull)ofs, (ull)len);
71                         goto failed;
72                 }
73                 
74                 /* but we should be able to lock just before and after it */
75                 if (brlock(fd, ofs+len, 1, 1, F_WRLCK, F_SETLK) == -1) {
76                         printf("ERROR: unable to lock range %lld:%lld\n", (ull)ofs+len, (ull)1);
77                         goto failed;
78                 }
79                 if (brlock(fd, ofs-1, 1, 1, F_WRLCK, F_SETLK) == -1) {
80                         printf("ERROR: unable to lock range %lld:%lld\n", (ull)ofs-1, (ull)1);
81                         goto failed;
82                 }
83
84                 /* and remove them again */
85                 if (brlock(fd, ofs+len, 1, 0, F_WRLCK, F_SETLK) == -1) {
86                         printf("ERROR: unable to unlock range %lld:%lld\n", (ull)ofs+len, (ull)1);
87                         goto failed;
88                 }
89                 if (brlock(fd, ofs-1, 1, 0, F_WRLCK, F_SETLK) == -1) {
90                         printf("ERROR: unable to unlock range %lld:%lld\n", (ull)ofs-1, (ull)1);
91                         goto failed;
92                 }
93                 
94                 /* seems OK */
95                 ret = 0;
96                 write(pfd, &ret, sizeof(ret));
97         }
98
99  failed:
100
101         fstat(fd, &st);
102         snprintf(line, sizeof(line), "egrep POSIX.*%u /proc/locks", (int)st.st_ino);
103         system(line);
104
105         ret = -1;
106         write(pfd, &ret, sizeof(ret));
107         sleep(10);
108         exit(1);
109 }
110
111 static void parent_main(int pfd)
112 {
113         int fd = open(FNAME,O_RDWR|O_CREAT|O_TRUNC, 0600);
114         off_t ofs;
115         size_t len;
116         int ret, i;
117         struct {
118                 off_t ofs;
119                 size_t len;
120         } tests[] = {
121                 {7, 1},
122                 {1<<30, 1<<25},
123 #if (_FILE_OFFSET_BITS == 64)
124                 {1LL<<40, 1<<10},
125                 {1LL<<61, 1<<30},
126                 {(1LL<<62) - 10, 1},
127 #endif
128         };
129
130
131         if (fd == -1) {
132                 perror(FNAME);
133                 goto failed;
134         }
135
136         for (i=0;i<sizeof(tests)/sizeof(tests[0]); i++) {
137                 ofs = tests[i].ofs;
138                 len = tests[i].len;
139
140                 if (brlock(fd, ofs, len, 1, F_WRLCK, F_SETLK) == -1) {
141                         printf("lock 1 failed\n");
142                         goto failed;
143                 }
144
145                 write(pfd, &ofs, sizeof(ofs));
146                 write(pfd, &len, sizeof(len));
147
148                 read(pfd, &ret, sizeof(ret));
149                 if (ret != 0) {
150                         printf("child reported failure\n");
151                         goto failed;
152                 }
153
154                 printf("test %d OK\n", i);
155         }
156         printf("all tests OK\n");
157         kill(child_pid, SIGKILL);
158         waitpid(child_pid, NULL, 0);
159         return;
160
161  failed:
162         kill(child_pid, SIGKILL);
163         waitpid(child_pid, NULL, 0);
164         exit(1);
165 }
166
167
168 int main(int argc, char *argv[])
169 {
170         int pfd[2];
171         struct flock fl;
172
173         socketpair(AF_UNIX, SOCK_STREAM, 0, pfd);
174
175         printf("sizeof(off_t) : %d\n", sizeof(off_t));
176         printf("sizeof(size_t) : %d\n", sizeof(size_t));
177         printf("sizeof(l_start) : %d\n", sizeof(fl.l_start));
178
179         if ((child_pid=fork()) == 0) {
180                 close(pfd[0]);
181                 child_main(pfd[1]);
182         } else {
183                 close(pfd[1]);
184                 parent_main(pfd[0]);
185         }
186
187         return 0;
188 }