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 
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;
43  int id;
44  int fd;
45  off_t offset;
46 };
47 
48 static hash_table *hash = nullptr;
49 static pid_t mypid;
50 static char *shmbuf;
51 static int DebugLevel = 0;
52 
53 static int
54 do_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 
87 static int
88 do_close(diomsg * r, 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 
117 static int
118 do_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 
167 static int
168 do_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 
213 static int
214 do_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 
231 static void
232 msg_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 
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 extern "C" {
299  static void alarm_handler(int) {}
300 };
301 
302 int
303 main(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 
void xassert(const char *msg, const char *file, int line)
Definition: diskd.cc:28
const char * xstrerr(int error)
Definition: xstrerror.cc:83
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
@ _MQD_CLOSE
Definition: diomsg.h:22
static unsigned int fsHash(const void *key, unsigned int n)
Definition: diskd.cc:291
void * key
Definition: diskd.cc:41
void hash_remove_link(hash_table *, hash_link *)
Definition: hash.cc:220
static int DebugLevel
Definition: diskd.cc:51
@ _MQD_OPEN
Definition: diomsg.h:20
long mtyp_t
Definition: types.h:141
hash_link * hash_lookup(hash_table *, const void *)
Definition: hash.cc:146
int status
Definition: diomsg.h:38
Lock * requestor
Definition: diomsg.h:35
static int do_close(diomsg *r, int)
Definition: diskd.cc:88
static int do_read(diomsg *r, int, char *buf)
Definition: diskd.cc:118
@ _MQD_UNLINK
Definition: diomsg.h:25
static void msg_handle(diomsg *r, int rl, diomsg *s)
Definition: diskd.cc:232
#define DEBUG(LEVEL)
Definition: diskd.cc:36
int seq_no
Definition: diomsg.h:33
@ _MQD_READ
Definition: diomsg.h:23
static uint32 A
Definition: md4.c:43
static const int msg_snd_rcv_sz
Definition: diomsg.h:41
#define assert(EX)
Definition: assert.h:17
size_t size
Definition: diomsg.h:36
int main(int argc, char *argv[])
Definition: diskd.cc:303
#define SQUID_NONBLOCK
static int do_write(diomsg *r, int, const char *buf)
Definition: diskd.cc:168
static int fsCmp(const void *a, const void *b)
Definition: diskd.cc:283
#define SA_RESTART
int fd
Definition: diskd.cc:44
#define xfree
int shm_offset
Definition: diomsg.h:40
static void alarm_handler(int)
Definition: diskd.cc:299
static int do_open(diomsg *r, int, const char *buf)
Definition: diskd.cc:54
off_t offset
Definition: diomsg.h:37
@ _MQD_CREATE
Definition: diomsg.h:21
int id
Definition: diskd.cc:43
hash_table * hash_create(HASHCMP *, int, HASHHASH *)
Definition: hash.cc:108
int id
Definition: diomsg.h:32
Definition: diomsg.h:30
#define PRId64
Definition: types.h:104
static pid_t mypid
Definition: diskd.cc:49
file_state * next
Definition: diskd.cc:42
@ _MQD_WRITE
Definition: diomsg.h:24
static uint32 B
Definition: md4.c:43
bool newstyle
Definition: diomsg.h:39
static char * shmbuf
Definition: diskd.cc:50
static int do_unlink(diomsg *r, int, const char *buf)
Definition: diskd.cc:214
static hash_table * hash
Definition: diskd.cc:48
void * callback_data
Definition: diomsg.h:34
mtyp_t mtype
Definition: diomsg.h:31
void hash_join(hash_table *, hash_link *)
Definition: hash.cc:131
off_t offset
Definition: diskd.cc:45

 

Introduction

Documentation

Support

Miscellaneous