diskd.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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"
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
27void
28xassert(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
35const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
36#define DEBUG(LEVEL) if ((LEVEL) <= DebugLevel)
37
38typedef struct _file_state file_state;
39
41 void *key;
43 int id;
44 int fd;
45 off_t offset;
46};
47
48static hash_table *hash = nullptr;
49static pid_t mypid;
50static char *shmbuf;
51static int DebugLevel = 0;
52
53static int
54do_open(diomsg * r, int, 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
87static int
89{
90 int fd;
91 file_state *fs;
92 fs = (file_state *) hash_lookup(hash, &r->id);
93
94 if (nullptr == 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;
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
117static int
118do_read(diomsg * r, int, 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 (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 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
167static int
168do_write(diomsg * r, int, 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 (nullptr == 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
213static int
214do_unlink(diomsg * r, int, 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
231static void
232msg_handle(diomsg * r, int rl, diomsg * s)
233{
234 char *buf = nullptr;
235 s->mtype = r->mtype;
236 s->id = r->id;
237 s->seq_no = r->seq_no; /* optional, debugging */
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
282static int
283fsCmp(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
290static unsigned int
291fsHash(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
298extern "C" {
299 static void alarm_handler(int) {}
300};
301
302int
303main(int argc, char *argv[])
304{
305 int key;
306 int rmsgid;
307 int smsgid;
308 int shmid;
309 diomsg rmsg;
310 diomsg smsg;
311 int rlen;
312 char rbuf[512];
313
314 struct sigaction sa;
315 setbuf(stdout, nullptr);
316 setbuf(stderr, nullptr);
317 mypid = getpid();
318 assert(4 == argc);
319 key = atoi(argv[1]);
320 rmsgid = msgget(key, 0600);
321
322 if (rmsgid < 0) {
323 perror("msgget");
324 exit(EXIT_FAILURE);
325 }
326
327 key = atoi(argv[2]);
328 smsgid = msgget(key, 0600);
329
330 if (smsgid < 0) {
331 perror("msgget");
332 exit(EXIT_FAILURE);
333 }
334
335 key = atoi(argv[3]);
336 shmid = shmget(key, 0, 0600);
337
338 if (shmid < 0) {
339 perror("shmget");
340 exit(EXIT_FAILURE);
341 }
342
343 shmbuf = (char *)shmat(shmid, nullptr, 0);
344
345 if (shmbuf == (void *) -1) {
346 perror("shmat");
347 exit(EXIT_FAILURE);
348 }
349
350 hash = hash_create(fsCmp, 1 << 4, fsHash);
351 assert(hash);
352 if (fcntl(0, F_SETFL, SQUID_NONBLOCK) < 0) {
353 perror(xstrerr(errno));
354 exit(EXIT_FAILURE);
355 }
356 memset(&sa, '\0', sizeof(sa));
357 sa.sa_handler = alarm_handler;
358 sa.sa_flags = SA_RESTART;
359 sigaction(SIGALRM, &sa, nullptr);
360
361 for (;;) {
362 alarm(1);
363 memset(&rmsg, '\0', sizeof(rmsg));
364 DEBUG(2) {
365 std::cerr << "msgrcv: " << rmsgid << ", "
366 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
367 << ", " << 0 << ", " << 0 << std::endl;
368 }
369 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
370
371 if (rlen < 0) {
372 if (EINTR == errno) {
373 if (read(0, rbuf, 512) <= 0) {
374 if (EWOULDBLOCK == errno)
375 (void) 0;
376 else if (EAGAIN == errno)
377 (void) 0;
378 else
379 break;
380 }
381 }
382
383 if (EAGAIN == errno) {
384 continue;
385 }
386
387 perror("msgrcv");
388 break;
389 }
390
391 alarm(0);
392 msg_handle(&rmsg, rlen, &smsg);
393
394 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
395 perror("msgsnd");
396 break;
397 }
398 }
399
400 DEBUG(2) {
401 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
402 }
403
404 if (msgctl(rmsgid, IPC_RMID, nullptr) < 0)
405 perror("msgctl IPC_RMID");
406
407 if (msgctl(smsgid, IPC_RMID, nullptr) < 0)
408 perror("msgctl IPC_RMID");
409
410 if (shmdt(shmbuf) < 0)
411 perror("shmdt");
412
413 if (shmctl(shmid, IPC_RMID, nullptr) < 0)
414 perror("shmctl IPC_RMID");
415
416 return EXIT_SUCCESS;
417}
418
#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:48
int main(int argc, char *argv[])
Definition: diskd.cc:303
static int do_open(diomsg *r, int, const char *buf)
Definition: diskd.cc:54
#define DEBUG(LEVEL)
Definition: diskd.cc:36
static int do_read(diomsg *r, int, char *buf)
Definition: diskd.cc:118
static pid_t mypid
Definition: diskd.cc:49
static void alarm_handler(int)
Definition: diskd.cc:299
static int DebugLevel
Definition: diskd.cc:51
static int do_close(diomsg *r, int)
Definition: diskd.cc:88
static int fsCmp(const void *a, const void *b)
Definition: diskd.cc:283
static char * shmbuf
Definition: diskd.cc:50
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:214
static unsigned int fsHash(const void *key, unsigned int n)
Definition: diskd.cc:291
void xassert(const char *msg, const char *file, int line)
Definition: diskd.cc:28
static void msg_handle(diomsg *r, int rl, diomsg *s)
Definition: diskd.cc:232
SQUIDCEXTERN hash_table * hash_create(HASHCMP *, int, HASHHASH *)
Definition: hash.cc:108
SQUIDCEXTERN void hash_join(hash_table *, hash_link *)
Definition: hash.cc:131
SQUIDCEXTERN void hash_remove_link(hash_table *, hash_link *)
Definition: hash.cc:220
SQUIDCEXTERN hash_link * hash_lookup(hash_table *, const void *)
Definition: hash.cc:146
static uint32 A
Definition: md4.c:43
static uint32 B
Definition: md4.c:43
#define xfree
off_t offset
Definition: diskd.cc:45
file_state * next
Definition: diskd.cc:42
int fd
Definition: diskd.cc:44
void * key
Definition: diskd.cc:41
int id
Definition: diskd.cc:43
Definition: diomsg.h:30
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
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
const char * xstrerr(int error)
Definition: xstrerror.cc:83

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors