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