]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskDaemon/diskd.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / DiskIO / DiskDaemon / diskd.cc
1 /*
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section -- External DISKD process implementation. */
10
11 #include "squid.h"
12 #include "DiskIO/DiskDaemon/diomsg.h"
13 #include "hash.h"
14
15 #include <cerrno>
16 #include <iostream>
17 #if HAVE_SYS_IPC_H
18 #include <sys/ipc.h>
19 #endif
20 #if HAVE_SYS_MSG_H
21 #include <sys/msg.h>
22 #endif
23 #if HAVE_SYS_SHM_H
24 #include <sys/shm.h>
25 #endif
26
27 void
28 xassert(const char *msg, const char *file, int line)
29 {
30 fprintf(stderr,"assertion failed: %s:%d: \"%s\"\n", file, line, msg);
31
32 abort();
33 }
34
35 const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
36 #define DEBUG(LEVEL) if ((LEVEL) <= DebugLevel)
37
38 typedef struct _file_state file_state;
39
40 struct _file_state {
41 void *key;
42 file_state *next;
43 int id;
44 int fd;
45 off_t offset;
46 };
47
48 static hash_table *hash = NULL;
49 static pid_t mypid;
50 static char *shmbuf;
51 static int DebugLevel = 0;
52
53 static int
54 do_open(diomsg * r, int len, const char *buf)
55 {
56 int fd;
57 file_state *fs;
58 /*
59 * note r->offset holds open() flags
60 */
61 fd = open(buf, r->offset, 0600);
62
63 if (fd < 0) {
64 DEBUG(1) {
65 fprintf(stderr, "%d %s: ", (int) mypid, buf);
66 perror("open");
67 }
68
69 return -errno;
70 }
71
72 fs = (file_state *)xcalloc(1, sizeof(*fs));
73 fs->id = r->id;
74 fs->key = &fs->id; /* gack */
75 fs->fd = fd;
76 hash_join(hash, (hash_link *) fs);
77 DEBUG(2) {
78 fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
79 (int) mypid,
80 fs->id,
81 fs->fd,
82 fs);
83 }
84 return fd;
85 }
86
87 static int
88 do_close(diomsg * r, int len)
89 {
90 int fd;
91 file_state *fs;
92 fs = (file_state *) hash_lookup(hash, &r->id);
93
94 if (NULL == fs) {
95 errno = EBADF;
96 DEBUG(1) {
97 fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id);
98 perror("do_close");
99 }
100
101 return -errno;
102 }
103
104 fd = fs->fd;
105 hash_remove_link(hash, (hash_link *) fs);
106 DEBUG(2) {
107 fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
108 (int) mypid,
109 r->id,
110 fs->fd,
111 fs);
112 }
113 xfree(fs);
114 return close(fd);
115 }
116
117 static int
118 do_read(diomsg * r, int len, char *buf)
119 {
120 int x;
121 int readlen = r->size;
122 file_state *fs;
123 fs = (file_state *) hash_lookup(hash, &r->id);
124
125 if (NULL == fs) {
126 errno = EBADF;
127 DEBUG(1) {
128 fprintf(stderr, "%d READ id %d: ", (int) mypid, r->id);
129 perror("do_read");
130 }
131
132 return -errno;
133 }
134
135 if (r->offset > -1 && r->offset != fs->offset) {
136 DEBUG(2) {
137 fprintf(stderr, "seeking to %" PRId64 "\n", (int64_t)r->offset);
138 }
139
140 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
141 DEBUG(1) {
142 fprintf(stderr, "%d FD %d, offset %" PRId64 ": ", (int) mypid, fs->fd, (int64_t)r->offset);
143 perror("lseek");
144 }
145 }
146 }
147
148 x = read(fs->fd, buf, readlen);
149 DEBUG(2) {
150 fprintf(stderr, "%d READ %d,%d,%" PRId64 " ret %d\n", (int) mypid,
151 fs->fd, readlen, (int64_t)r->offset, x);
152 }
153
154 if (x < 0) {
155 DEBUG(1) {
156 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
157 perror("read");
158 }
159
160 return -errno;
161 }
162
163 fs->offset = r->offset + x;
164 return x;
165 }
166
167 static int
168 do_write(diomsg * r, int len, const char *buf)
169 {
170 int wrtlen = r->size;
171 int x;
172 file_state *fs;
173 fs = (file_state *) hash_lookup(hash, &r->id);
174
175 if (NULL == fs) {
176 errno = EBADF;
177 DEBUG(1) {
178 fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id);
179 perror("do_write");
180 }
181
182 return -errno;
183 }
184
185 if (r->offset > -1 && r->offset != fs->offset) {
186 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
187 DEBUG(1) {
188 fprintf(stderr, "%d FD %d, offset %" PRId64 ": ", (int) mypid, fs->fd, (int64_t)r->offset);
189 perror("lseek");
190 }
191 }
192 }
193
194 DEBUG(2) {
195 fprintf(stderr, "%d WRITE %d,%d,%" PRId64 "\n", (int) mypid,
196 fs->fd, wrtlen, (int64_t)r->offset);
197 }
198 x = write(fs->fd, buf, wrtlen);
199
200 if (x < 0) {
201 DEBUG(1) {
202 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
203 perror("write");
204 }
205
206 return -errno;
207 }
208
209 fs->offset = r->offset + x;
210 return x;
211 }
212
213 static int
214 do_unlink(diomsg * r, int len, const char *buf)
215 {
216 if (unlink(buf) < 0) {
217 DEBUG(1) {
218 fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf);
219 perror("unlink");
220 }
221
222 return -errno;
223 }
224
225 DEBUG(2) {
226 fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
227 }
228 return 0;
229 }
230
231 static void
232 msg_handle(diomsg * r, int rl, diomsg * s)
233 {
234 char *buf = NULL;
235 s->mtype = r->mtype;
236 s->id = r->id;
237 s->seq_no = r->seq_no; /* optional, debugging */
238 s->callback_data = r->callback_data;
239 s->requestor = r->requestor;
240 s->size = 0; /* optional, debugging */
241 s->offset = 0; /* optional, debugging */
242 s->shm_offset = r->shm_offset;
243 s->newstyle = r->newstyle;
244
245 if (s->shm_offset > -1)
246 buf = shmbuf + s->shm_offset;
247 else if (r->mtype != _MQD_CLOSE) {
248 fprintf(stderr, "%d UNLNK id(%u) Error: no filename in shm buffer\n", (int) mypid, s->id);
249 return;
250 }
251
252 switch (r->mtype) {
253
254 case _MQD_OPEN:
255
256 case _MQD_CREATE:
257 s->status = do_open(r, rl, buf);
258 break;
259
260 case _MQD_CLOSE:
261 s->status = do_close(r, rl);
262 break;
263
264 case _MQD_READ:
265 s->status = do_read(r, rl, buf);
266 break;
267
268 case _MQD_WRITE:
269 s->status = do_write(r, rl, buf);
270 break;
271
272 case _MQD_UNLINK:
273 s->status = do_unlink(r, rl, buf);
274 break;
275
276 default:
277 assert(0);
278 break;
279 }
280 }
281
282 static int
283 fsCmp(const void *a, const void *b)
284 {
285 const int *A = (const int *)a;
286 const int *B = (const int *)b;
287 return *A != *B;
288 }
289
290 static unsigned int
291 fsHash(const void *key, unsigned int n)
292 {
293 /* note, n must be a power of 2! */
294 const int *k = (const int *)key;
295 return (*k & (--n));
296 }
297
298 SQUIDCEXTERN {
299 static void
300 alarm_handler(int sig) {
301 (void) 0;
302 }
303 };
304
305 int
306 main(int argc, char *argv[])
307 {
308 int key;
309 int rmsgid;
310 int smsgid;
311 int shmid;
312 diomsg rmsg;
313 diomsg smsg;
314 int rlen;
315 char rbuf[512];
316
317 struct sigaction sa;
318 setbuf(stdout, NULL);
319 setbuf(stderr, NULL);
320 mypid = getpid();
321 assert(4 == argc);
322 key = atoi(argv[1]);
323 rmsgid = msgget(key, 0600);
324
325 if (rmsgid < 0) {
326 perror("msgget");
327 return 1;
328 }
329
330 key = atoi(argv[2]);
331 smsgid = msgget(key, 0600);
332
333 if (smsgid < 0) {
334 perror("msgget");
335 return 1;
336 }
337
338 key = atoi(argv[3]);
339 shmid = shmget(key, 0, 0600);
340
341 if (shmid < 0) {
342 perror("shmget");
343 return 1;
344 }
345
346 shmbuf = (char *)shmat(shmid, NULL, 0);
347
348 if (shmbuf == (void *) -1) {
349 perror("shmat");
350 return 1;
351 }
352
353 hash = hash_create(fsCmp, 1 << 4, fsHash);
354 assert(hash);
355 if (fcntl(0, F_SETFL, SQUID_NONBLOCK) < 0) {
356 perror(xstrerror());
357 return 1;
358 }
359 memset(&sa, '\0', sizeof(sa));
360 sa.sa_handler = alarm_handler;
361 sa.sa_flags = SA_RESTART;
362 sigaction(SIGALRM, &sa, NULL);
363
364 for (;;) {
365 alarm(1);
366 memset(&rmsg, '\0', sizeof(rmsg));
367 DEBUG(2) {
368 std::cerr << "msgrcv: " << rmsgid << ", "
369 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
370 << ", " << 0 << ", " << 0 << std::endl;
371 }
372 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
373
374 if (rlen < 0) {
375 if (EINTR == errno) {
376 if (read(0, rbuf, 512) <= 0) {
377 if (EWOULDBLOCK == errno)
378 (void) 0;
379 else if (EAGAIN == errno)
380 (void) 0;
381 else
382 break;
383 }
384 }
385
386 if (EAGAIN == errno) {
387 continue;
388 }
389
390 perror("msgrcv");
391 break;
392 }
393
394 alarm(0);
395 msg_handle(&rmsg, rlen, &smsg);
396
397 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
398 perror("msgsnd");
399 break;
400 }
401 }
402
403 DEBUG(2) {
404 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
405 }
406
407 if (msgctl(rmsgid, IPC_RMID, 0) < 0)
408 perror("msgctl IPC_RMID");
409
410 if (msgctl(smsgid, IPC_RMID, 0) < 0)
411 perror("msgctl IPC_RMID");
412
413 if (shmdt(shmbuf) < 0)
414 perror("shmdt");
415
416 if (shmctl(shmid, IPC_RMID, 0) < 0)
417 perror("shmctl IPC_RMID");
418
419 return 0;
420 }
421