Squid Web Cache master
Loading...
Searching...
No Matches
diskd.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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 "compat/socket.h"
13#include "compat/unistd.h"
15#include "hash.h"
16
17#include <cerrno>
18#include <iostream>
19#if HAVE_SYS_IPC_H
20#include <sys/ipc.h>
21#endif
22#if HAVE_SYS_MSG_H
23#include <sys/msg.h>
24#endif
25#if HAVE_SYS_SHM_H
26#include <sys/shm.h>
27#endif
28
29void
30xassert(const char *msg, const char *file, int line)
31{
32 fprintf(stderr,"assertion failed: %s:%d: \"%s\"\n", file, line, msg);
33
34 abort();
35}
36
37const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
38#define DEBUG(LEVEL) if ((LEVEL) <= DebugLevel)
39
40typedef struct _file_state file_state;
41
43 void *key;
45 int id;
46 int fd;
47 off_t offset;
48};
49
50static hash_table *hash = nullptr;
51static pid_t mypid;
52static char *shmbuf;
53static int DebugLevel = 0;
54
55static int
56do_open(diomsg * r, int, const char *buf)
57{
58 file_state *fs;
59 /*
60 * note r->offset holds open() flags
61 */
62 const auto fd = xopen(buf, r->offset, 0600);
63
64 if (fd < 0) {
65 DEBUG(1) {
66 fprintf(stderr, "%d %s: ", (int) mypid, buf);
67 perror("open");
68 }
69
70 return -errno;
71 }
72
73 fs = (file_state *)xcalloc(1, sizeof(*fs));
74 fs->id = r->id;
75 fs->key = &fs->id; /* gack */
76 fs->fd = fd;
77 hash_join(hash, (hash_link *) fs);
78 DEBUG(2) {
79 fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
80 (int) mypid,
81 fs->id,
82 fs->fd,
83 fs);
84 }
85 return fd;
86}
87
88static int
90{
91 int fd;
92 file_state *fs;
93 fs = (file_state *) hash_lookup(hash, &r->id);
94
95 if (nullptr == fs) {
96 errno = EBADF;
97 DEBUG(1) {
98 fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id);
99 perror("do_close");
100 }
101
102 return -errno;
103 }
104
105 fd = fs->fd;
107 DEBUG(2) {
108 fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
109 (int) mypid,
110 r->id,
111 fs->fd,
112 fs);
113 }
114 xfree(fs);
115 return xclose(fd);
116}
117
118static int
119do_read(diomsg * r, int, char *buf)
120{
121 int readlen = r->size;
122 file_state *fs;
123 fs = (file_state *) hash_lookup(hash, &r->id);
124
125 if (nullptr == 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 const auto x = xread(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
167static int
168do_write(diomsg * r, int, const char *buf)
169{
170 int wrtlen = r->size;
171 file_state *fs;
172 fs = (file_state *) hash_lookup(hash, &r->id);
173
174 if (nullptr == fs) {
175 errno = EBADF;
176 DEBUG(1) {
177 fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id);
178 perror("do_write");
179 }
180
181 return -errno;
182 }
183
184 if (r->offset > -1 && r->offset != fs->offset) {
185 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
186 DEBUG(1) {
187 fprintf(stderr, "%d FD %d, offset %" PRId64 ": ", (int) mypid, fs->fd, (int64_t)r->offset);
188 perror("lseek");
189 }
190 }
191 }
192
193 DEBUG(2) {
194 fprintf(stderr, "%d WRITE %d,%d,%" PRId64 "\n", (int) mypid,
195 fs->fd, wrtlen, (int64_t)r->offset);
196 }
197 const auto x = xwrite(fs->fd, buf, wrtlen);
198
199 if (x < 0) {
200 DEBUG(1) {
201 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
202 perror("write");
203 }
204
205 return -errno;
206 }
207
208 fs->offset = r->offset + x;
209 return x;
210}
211
212static int
213do_unlink(diomsg * r, int, const char *buf)
214{
215 if (unlink(buf) < 0) {
216 DEBUG(1) {
217 fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf);
218 perror("unlink");
219 }
220
221 return -errno;
222 }
223
224 DEBUG(2) {
225 fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
226 }
227 return 0;
228}
229
230static void
231msg_handle(diomsg * r, int rl, diomsg * s)
232{
233 char *buf = nullptr;
234 s->mtype = r->mtype;
235 s->id = r->id;
236 s->seq_no = r->seq_no; /* optional, debugging */
238 s->requestor = r->requestor;
239 s->size = 0; /* optional, debugging */
240 s->offset = 0; /* optional, debugging */
241 s->shm_offset = r->shm_offset;
242 s->newstyle = r->newstyle;
243
244 if (s->shm_offset > -1)
245 buf = shmbuf + s->shm_offset;
246 else if (r->mtype != _MQD_CLOSE) {
247 fprintf(stderr, "%d UNLNK id(%u) Error: no filename in shm buffer\n", (int) mypid, s->id);
248 return;
249 }
250
251 switch (r->mtype) {
252
253 case _MQD_OPEN:
254
255 case _MQD_CREATE:
256 s->status = do_open(r, rl, buf);
257 break;
258
259 case _MQD_CLOSE:
260 s->status = do_close(r, rl);
261 break;
262
263 case _MQD_READ:
264 s->status = do_read(r, rl, buf);
265 break;
266
267 case _MQD_WRITE:
268 s->status = do_write(r, rl, buf);
269 break;
270
271 case _MQD_UNLINK:
272 s->status = do_unlink(r, rl, buf);
273 break;
274
275 default:
276 assert(0);
277 break;
278 }
279}
280
281static int
282fsCmp(const void *a, const void *b)
283{
284 const int *A = (const int *)a;
285 const int *B = (const int *)b;
286 return *A != *B;
287}
288
289static unsigned int
290fsHash(const void *key, unsigned int n)
291{
292 /* note, n must be a power of 2! */
293 const int *k = (const int *)key;
294 return (*k & (--n));
295}
296
297extern "C" {
298 static void alarm_handler(int) {}
299};
300
301int
302main(int argc, char *argv[])
303{
304 int key;
305 int rmsgid;
306 int smsgid;
307 int shmid;
308 diomsg rmsg;
309 diomsg smsg;
310 int rlen;
311 char rbuf[512];
312
313 struct sigaction sa;
314 setbuf(stdout, nullptr);
315 setbuf(stderr, nullptr);
316 mypid = getpid();
317 assert(4 == argc);
318 key = atoi(argv[1]);
319 rmsgid = msgget(key, 0600);
320
321 if (rmsgid < 0) {
322 perror("msgget");
323 exit(EXIT_FAILURE);
324 }
325
326 key = atoi(argv[2]);
327 smsgid = msgget(key, 0600);
328
329 if (smsgid < 0) {
330 perror("msgget");
331 exit(EXIT_FAILURE);
332 }
333
334 key = atoi(argv[3]);
335 shmid = shmget(key, 0, 0600);
336
337 if (shmid < 0) {
338 perror("shmget");
339 exit(EXIT_FAILURE);
340 }
341
342 shmbuf = (char *)shmat(shmid, nullptr, 0);
343
344 if (shmbuf == (void *) -1) {
345 perror("shmat");
346 exit(EXIT_FAILURE);
347 }
348
349 hash = hash_create(fsCmp, 1 << 4, fsHash);
350 assert(hash);
351 if (fcntl(0, F_SETFL, SQUID_NONBLOCK) < 0) {
352 perror(xstrerr(errno));
353 exit(EXIT_FAILURE);
354 }
355 memset(&sa, '\0', sizeof(sa));
356 sa.sa_handler = alarm_handler;
357 sa.sa_flags = SA_RESTART;
358 sigaction(SIGALRM, &sa, nullptr);
359
360 for (;;) {
361 alarm(1);
362 memset(&rmsg, '\0', sizeof(rmsg));
363 DEBUG(2) {
364 std::cerr << "msgrcv: " << rmsgid << ", "
365 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
366 << ", " << 0 << ", " << 0 << std::endl;
367 }
368 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
369
370 if (rlen < 0) {
371 if (EINTR == errno) {
372 if (xread(0, rbuf, 512) <= 0) {
373 if (EWOULDBLOCK == errno)
374 (void) 0;
375 else if (EAGAIN == errno)
376 (void) 0;
377 else
378 break;
379 }
380 }
381
382 if (EAGAIN == errno) {
383 continue;
384 }
385
386 perror("msgrcv");
387 break;
388 }
389
390 alarm(0);
391 msg_handle(&rmsg, rlen, &smsg);
392
393 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
394 perror("msgsnd");
395 break;
396 }
397 }
398
399 DEBUG(2) {
400 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
401 }
402
403 if (msgctl(rmsgid, IPC_RMID, nullptr) < 0)
404 perror("msgctl IPC_RMID");
405
406 if (msgctl(smsgid, IPC_RMID, nullptr) < 0)
407 perror("msgctl IPC_RMID");
408
409 if (shmdt(shmbuf) < 0)
410 perror("shmdt");
411
412 if (shmctl(shmid, IPC_RMID, nullptr) < 0)
413 perror("shmctl IPC_RMID");
414
415 return EXIT_SUCCESS;
416}
417
#define assert(EX)
Definition assert.h:17
#define SA_RESTART
#define SQUID_NONBLOCK
@ _MQD_UNLINK
Definition diomsg.h:25
@ _MQD_CREATE
Definition diomsg.h:21
@ _MQD_WRITE
Definition diomsg.h:24
@ _MQD_CLOSE
Definition diomsg.h:22
@ _MQD_OPEN
Definition diomsg.h:20
@ _MQD_READ
Definition diomsg.h:23
static hash_table * hash
Definition diskd.cc:50
static int do_open(diomsg *r, int, const char *buf)
Definition diskd.cc:56
#define DEBUG(LEVEL)
Definition diskd.cc:38
static int do_read(diomsg *r, int, char *buf)
Definition diskd.cc:119
static pid_t mypid
Definition diskd.cc:51
static void alarm_handler(int)
Definition diskd.cc:298
static int DebugLevel
Definition diskd.cc:53
static int do_close(diomsg *r, int)
Definition diskd.cc:89
static int fsCmp(const void *a, const void *b)
Definition diskd.cc:282
static char * shmbuf
Definition diskd.cc:52
static int do_write(diomsg *r, int, const char *buf)
Definition diskd.cc:168
static int do_unlink(diomsg *r, int, const char *buf)
Definition diskd.cc:213
static unsigned int fsHash(const void *key, unsigned int n)
Definition diskd.cc:290
void xassert(const char *msg, const char *file, int line)
Definition diskd.cc:30
static void msg_handle(diomsg *r, int rl, diomsg *s)
Definition diskd.cc:231
hash_link * hash_lookup(hash_table *, const void *)
Definition hash.cc:146
hash_table * hash_create(HASHCMP *, int, HASHHASH *)
Definition hash.cc:108
void hash_join(hash_table *, hash_link *)
Definition hash.cc:131
void hash_remove_link(hash_table *, hash_link *)
Definition hash.cc:220
int main()
#define xfree
off_t offset
Definition diskd.cc:47
file_state * next
Definition diskd.cc:44
void * key
Definition diskd.cc:43
mtyp_t mtype
Definition diomsg.h:31
int seq_no
Definition diomsg.h:33
off_t offset
Definition diomsg.h:37
int status
Definition diomsg.h:38
size_t size
Definition diomsg.h:36
Lock * requestor
Definition diomsg.h:35
static const int msg_snd_rcv_sz
Definition diomsg.h:41
bool newstyle
Definition diomsg.h:39
int shm_offset
Definition diomsg.h:40
void * callback_data
Definition diomsg.h:34
int id
Definition diomsg.h:32
#define PRId64
Definition types.h:104
long mtyp_t
Definition types.h:141
int xread(int fd, void *buf, size_t bufSize)
POSIX read(2) equivalent.
Definition unistd.h:61
int xwrite(int fd, const void *buf, size_t bufSize)
POSIX write(2) equivalent.
Definition unistd.h:67
int xclose(int fd)
POSIX close(2) equivalent.
Definition unistd.h:43
int xopen(const char *filename, int oflag, int pmode=0)
POSIX open(2) equivalent.
Definition unistd.h:55
void * xcalloc(size_t n, size_t sz)
Definition xalloc.cc:71
const char * xstrerr(int error)
Definition xstrerror.cc:83