DiskdFile.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 79 Squid-side DISKD I/O functions. */
10 
11 #include "squid.h"
12 #include "ConfigOption.h"
13 #include "diomsg.h"
14 #include "DiskdFile.h"
15 #include "DiskdIOStrategy.h"
16 #include "DiskIO/IORequestor.h"
17 #include "DiskIO/ReadRequest.h"
18 #include "DiskIO/WriteRequest.h"
19 #include "StatCounters.h"
20 
21 #if HAVE_SYS_IPC_H
22 #include <sys/ipc.h>
23 #endif
24 #if HAVE_SYS_MSG_H
25 #include <sys/msg.h>
26 #endif
27 #if HAVE_SYS_SHM_H
28 #include <sys/shm.h>
29 #endif
30 
32 
33 DiskdFile::DiskdFile(char const *aPath, DiskdIOStrategy *anIO) :
34  errorOccured(false),
35  IO(anIO),
36  mode(0),
37  inProgressIOs(0)
38 {
39  assert(aPath);
40  debugs(79, 3, "DiskdFile::DiskdFile: " << aPath);
41  path_ = xstrdup(aPath);
42  id = diskd_stats.sio_id;
44 }
45 
47 {
48  assert(inProgressIOs == 0);
49  safe_free (path_);
50 }
51 
52 void
54 {
55  debugs(79, 3, "DiskdFile::open: " << this << " opening for " << callback.getRaw());
56  assert(ioRequestor.getRaw() == nullptr);
57  ioRequestor = callback;
58  assert(callback.getRaw());
59  mode = flags;
60  ssize_t shm_offset;
61  char *buf = (char *)IO->shm.get(&shm_offset);
62  if (!buf) {
63  errorOccured = true;
65  ioRequestor = nullptr;
66  return;
67  }
68 
70  ioAway();
71  int x = IO->send(_MQD_OPEN,
72  id,
73  this,
74  strlen(buf) + 1,
75  mode,
76  shm_offset,
77  nullptr);
78 
79  if (x < 0) {
80  ioCompleted();
81  errorOccured = true;
82  // IO->shm.put (shm_offset);
84  ioRequestor = nullptr;
85  }
86 
88 }
89 
90 void
92 {
93  debugs(79, 3, "DiskdFile::create: " << this << " creating for " << callback.getRaw());
94  assert (ioRequestor.getRaw() == nullptr);
95  ioRequestor = callback;
96  assert (callback.getRaw());
97  mode = flags;
98  ssize_t shm_offset;
99  char *buf = (char *)IO->shm.get(&shm_offset);
100  if (!buf) {
101  errorOccured = true;
102  notifyClient();
103  ioRequestor = nullptr;
104  return;
105  }
106 
107  xstrncpy(buf, path_, SHMBUF_BLKSZ);
108  ioAway();
109  int x = IO->send(_MQD_CREATE,
110  id,
111  this,
112  strlen(buf) + 1,
113  mode,
114  shm_offset,
115  nullptr);
116 
117  if (x < 0) {
118  int xerrno = errno;
119  ioCompleted();
120  errorOccured = true;
121  // IO->shm.put (shm_offset);
122  debugs(79, DBG_IMPORTANT, "storeDiskdSend CREATE: " << xstrerr(xerrno));
123  notifyClient();
124  ioRequestor = nullptr;
125  return;
126  }
127 
129 }
130 
131 void
133 {
134  assert (ioRequestor.getRaw() != nullptr);
135  ssize_t shm_offset;
136  char *rbuf = (char *)IO->shm.get(&shm_offset);
137  if (!rbuf) {
138  errorOccured = true;
139  notifyClient();
140  ioRequestor = nullptr;
141  return;
142  }
143  ioAway();
144  int x = IO->send(_MQD_READ,
145  id,
146  this,
147  aRead->len,
148  aRead->offset,
149  shm_offset,
150  aRead);
151 
152  if (x < 0) {
153  int xerrno = errno;
154  ioCompleted();
155  errorOccured = true;
156  // IO->shm.put (shm_offset);
157  debugs(79, DBG_IMPORTANT, "storeDiskdSend READ: " << xstrerr(xerrno));
158  notifyClient();
159  ioRequestor = nullptr;
160  return;
161  }
162 
163  ++diskd_stats.read.ops;
164 }
165 
166 void
168 {
169  debugs(79, 3, "DiskdFile::close: " << this << " closing for " << ioRequestor.getRaw());
171  ioAway();
172  int x = IO->send(_MQD_CLOSE,
173  id,
174  this,
175  0,
176  0,
177  -1,
178  nullptr);
179 
180  if (x < 0) {
181  int xerrno = errno;
182  ioCompleted();
183  errorOccured = true;
184  debugs(79, DBG_IMPORTANT, "storeDiskdSend CLOSE: " << xstrerr(xerrno));
185  notifyClient();
186  ioRequestor = nullptr;
187  return;
188  }
189 
191 }
192 
193 bool
195 {
196  return errorOccured;
197 }
198 
199 bool
201 {
202  return !error();
203 }
204 
205 bool
207 {
208  if (!ioRequestor.getRaw()) {
209  debugs(79, 3, "DiskdFile::canNotifyClient: No ioRequestor to notify");
210  return false;
211  }
212 
213  return true;
214 }
215 
216 void
218 {
219  if (!canNotifyClient()) {
220  return;
221  }
222 
224 }
225 
226 void
228 {
229  assert (M->newstyle);
230 
231  switch (M->mtype) {
232 
233  case _MQD_OPEN:
234  openDone(M);
235  break;
236 
237  case _MQD_CREATE:
238  createDone(M);
239  break;
240 
241  case _MQD_CLOSE:
242  closeDone(M);
243  break;
244 
245  case _MQD_READ:
246  readDone(M);
247  break;
248 
249  case _MQD_WRITE:
250  writeDone(M);
251  break;
252 
253  case _MQD_UNLINK:
254  assert (0);
255  break;
256 
257  default:
258  assert(0);
259  break;
260  }
261 }
262 
263 void
265 {
266  ++statCounter.syscalls.disk.opens;
267  debugs(79, 3, "storeDiskdOpenDone: status " << M->status);
268 
269  if (M->status < 0) {
271  errorOccured = true;
272  } else {
274  }
275 
276  ioCompleted();
277  notifyClient();
278 }
279 
280 void
282 {
283  ++statCounter.syscalls.disk.opens;
284  debugs(79, 3, "storeDiskdCreateDone: status " << M->status);
285 
286  if (M->status < 0) {
288  errorOccured = true;
289  } else {
291  }
292 
293  ioCompleted();
294  notifyClient();
295 }
296 
297 void
299 {
300  debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len);
301  ssize_t shm_offset;
302  char *sbuf = (char *)IO->shm.get(&shm_offset);
303  if (!sbuf) {
304  errorOccured = true;
305  if (aRequest->free_func)
306  aRequest->free_func(const_cast<char *>(aRequest->buf));
307  notifyClient();
308  ioRequestor = nullptr;
309  return;
310  }
311 
312  memcpy(sbuf, aRequest->buf, aRequest->len);
313 
314  if (aRequest->free_func)
315  aRequest->free_func(const_cast<char *>(aRequest->buf));
316 
317  ioAway();
318 
319  int x = IO->send(_MQD_WRITE,
320  id,
321  this,
322  aRequest->len,
323  aRequest->offset,
324  shm_offset,
325  aRequest);
326 
327  if (x < 0) {
328  int xerrno = errno;
329  ioCompleted();
330  errorOccured = true;
331  debugs(79, DBG_IMPORTANT, "storeDiskdSend WRITE: " << xstrerr(xerrno));
332  // IO->shm.put (shm_offset);
333  notifyClient();
334  ioRequestor = nullptr;
335  return;
336  }
337 
339 }
340 
341 void
343 {
344  ++inProgressIOs;
345 }
346 
347 void
349 {
350  --inProgressIOs;
351 }
352 
353 void
355 {
356  ++statCounter.syscalls.disk.closes;
357  debugs(79, 3, "DiskdFile::closeDone: status " << M->status);
358 
359  if (M->status < 0) {
361  errorOccured = true;
362  } else {
364  }
365 
366  ioCompleted();
367 
368  if (canNotifyClient())
370 
371  ioRequestor = nullptr;
372 }
373 
374 void
376 {
377  ++statCounter.syscalls.disk.reads;
378  debugs(79, 3, "DiskdFile::readDone: status " << M->status);
379  assert (M->requestor);
380  ReadRequest::Pointer readRequest = dynamic_cast<ReadRequest *>(M->requestor);
381 
382  /* remove the free protection */
383  if (readRequest != nullptr) {
384  const uint32_t lcount = readRequest->unlock();
385  if (lcount == 0)
386  debugs(79, DBG_IMPORTANT, "ERROR: invariant check failed: readRequest reference count is 0");
387  }
388 
389  if (M->status < 0) {
391  ioCompleted();
392  errorOccured = true;
393  ioRequestor->readCompleted(nullptr, -1, DISK_ERROR, readRequest);
394  return;
395  }
396 
398 
399  ioCompleted();
400  ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest);
401 }
402 
403 void
405 {
406  ++statCounter.syscalls.disk.writes;
407  debugs(79, 3, "storeDiskdWriteDone: status " << M->status);
408  assert (M->requestor);
409  WriteRequest::Pointer writeRequest = dynamic_cast<WriteRequest *>(M->requestor);
410 
411  /* remove the free protection */
412  if (writeRequest != nullptr) {
413  const uint32_t lcount = writeRequest->unlock();
414  if (lcount == 0)
415  debugs(79, DBG_IMPORTANT, "ERROR: invariant check failed: writeRequest reference count is 0");
416  }
417 
418  if (M->status < 0) {
419  errorOccured = true;
421  ioCompleted();
422  ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest);
423  return;
424  }
425 
427  ioCompleted();
428  ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest);
429 }
430 
431 bool
433 {
434  return inProgressIOs != 0;
435 }
436 
const char * xstrerr(int error)
Definition: xstrerror.cc:83
RefCount< IORequestor > ioRequestor
Definition: DiskdFile.h:50
bool canNotifyClient() const
Definition: DiskdFile.cc:206
void openDone(diomsg *)
Definition: DiskdFile.cc:264
DiskdFile(char const *path, DiskdIOStrategy *)
Definition: DiskdFile.cc:33
#define SHMBUF_BLKSZ
const char * path_
Definition: DiskdFile.h:47
#define xstrdup
struct diskd_stats_t::@34 close
C * getRaw() const
Definition: RefCount.h:89
void ioCompleted()
Definition: DiskdFile.cc:348
void open(int flags, mode_t aMode, RefCount< IORequestor > callback) override
Definition: DiskdFile.cc:53
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
void close() override
Definition: DiskdFile.cc:167
void writeDone(diomsg *)
Definition: DiskdFile.cc:404
@ _MQD_READ
Definition: diomsg.h:23
int status
Definition: diomsg.h:38
Lock * requestor
Definition: diomsg.h:35
#define DISK_OK
Definition: defines.h:27
@ _MQD_CREATE
Definition: diomsg.h:21
SharedMemory shm
void ioAway()
Definition: DiskdFile.cc:342
struct diskd_stats_t::@34 read
@ _MQD_WRITE
Definition: diomsg.h:24
virtual void ioCompletedNotification()=0
void closeDone(diomsg *)
Definition: DiskdFile.cc:354
void completed(diomsg *)
Definition: DiskdFile.cc:227
bool canRead() const override
Definition: DiskdFile.cc:200
void * get(ssize_t *)
struct diskd_stats_t::@34 open
#define safe_free(x)
Definition: xalloc.h:73
#define assert(EX)
Definition: assert.h:17
diskd_stats_t diskd_stats
~DiskdFile() override
Definition: DiskdFile.cc:46
@ _MQD_CLOSE
Definition: diomsg.h:22
int mode
Definition: DiskdFile.h:56
@ _MQD_UNLINK
Definition: diomsg.h:25
size_t inProgressIOs
Definition: DiskdFile.h:61
size_t len
Definition: ReadRequest.h:26
void write(WriteRequest *) override
Definition: DiskdFile.cc:298
FREE * free_func
Definition: WriteRequest.h:28
CBDATA_CLASS_INIT(DiskdFile)
struct diskd_stats_t::@34 write
virtual void writeCompleted(int errflag, size_t len, RefCount< WriteRequest >)=0
int shm_offset
Definition: diomsg.h:40
int send(int mtype, int id, DiskdFile *theFile, size_t size, off_t offset, ssize_t shm_offset, Lock *requestor)
struct diskd_stats_t::@34 create
const char * buf
Definition: WriteRequest.h:25
struct StatCounters::@112::@116 disk
void read(ReadRequest *) override
Definition: DiskdFile.cc:132
Definition: diomsg.h:30
unsigned short mode_t
Definition: types.h:129
#define DBG_IMPORTANT
Definition: Stream.h:38
bool ioInProgress() const override
Definition: DiskdFile.cc:432
virtual void closeCompleted()=0
void readDone(diomsg *)
Definition: DiskdFile.cc:375
@ _MQD_OPEN
Definition: diomsg.h:20
void create(int flags, mode_t aMode, RefCount< IORequestor > callback) override
Definition: DiskdFile.cc:91
#define DISK_ERROR
Definition: defines.h:28
void createDone(diomsg *)
Definition: DiskdFile.cc:281
bool newstyle
Definition: diomsg.h:39
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
off_t offset
Definition: ReadRequest.h:25
mtyp_t mtype
Definition: diomsg.h:31
virtual void readCompleted(const char *buf, int len, int errflag, RefCount< ReadRequest >)=0
bool error() const override
Definition: DiskdFile.cc:194
struct StatCounters::@112 syscalls
bool errorOccured
Definition: DiskdFile.h:48
StatCounters statCounter
Definition: StatCounters.cc:12
DiskdIOStrategy * IO
Definition: DiskdFile.h:49
void notifyClient()
Definition: DiskdFile.cc:217

 

Introduction

Documentation

Support

Miscellaneous