]>
Commit | Line | Data |
---|---|---|
b9ae18aa | 1 | /* |
f70aedc4 | 2 | * Copyright (C) 1996-2021 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 Disk IO Routines */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
b9ae18aa | 12 | #include "DiskIO/IORequestor.h" |
13 | #include "DiskIO/ReadRequest.h" | |
14 | #include "DiskIO/WriteRequest.h" | |
602d9612 | 15 | #include "DiskThreadsDiskFile.h" |
c4ad1349 | 16 | #include "fd.h" |
b3f7fd88 | 17 | #include "fs_io.h" |
582c2af2 FC |
18 | #include "Generic.h" |
19 | #include "globals.h" | |
e4f1fdae | 20 | #include "StatCounters.h" |
582c2af2 | 21 | #include "Store.h" |
b9ae18aa | 22 | |
1a30fdf5 | 23 | #include <cerrno> |
21d845b1 | 24 | |
b9ae18aa | 25 | /* === PUBLIC =========================================================== */ |
26 | ||
27 | CBDATA_CLASS_INIT(DiskThreadsDiskFile); | |
b9ae18aa | 28 | |
43b6575c | 29 | DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath) |
b9ae18aa | 30 | { |
86c63190 | 31 | assert(aPath); |
bf8fe701 | 32 | debugs(79, 3, "UFSFile::UFSFile: " << aPath); |
86c63190 | 33 | path_ = xstrdup(aPath); |
b9ae18aa | 34 | } |
35 | ||
36 | DiskThreadsDiskFile::~DiskThreadsDiskFile() | |
37 | { | |
86c63190 | 38 | safe_free(path_); |
b9ae18aa | 39 | doClose(); |
40 | } | |
41 | ||
42 | void | |
63be0a78 | 43 | DiskThreadsDiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback) |
b9ae18aa | 44 | { |
e4f1fdae | 45 | ++statCounter.syscalls.disk.opens; |
b9ae18aa | 46 | #if !ASYNC_OPEN |
47 | ||
48 | fd = file_open(path_, flags); | |
49 | ||
50 | if (fd < 0) { | |
bf8fe701 | 51 | debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno << ")"); |
b9ae18aa | 52 | errorOccured = true; |
53 | return; | |
54 | } | |
55 | ||
56 | #endif | |
cb4185f1 | 57 | ++Opening_FD; |
b9ae18aa | 58 | |
59 | ioRequestor = callback; | |
60 | ||
61 | ++inProgressIOs; | |
62 | ||
63 | #if ASYNC_OPEN | |
64 | ||
65 | aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this); | |
66 | ||
67 | #else | |
68 | ||
69 | openDone(fd, NULL, fd, 0); | |
70 | ||
71 | #endif | |
72 | } | |
73 | ||
74 | void | |
75 | DiskThreadsDiskFile::read(ReadRequest * request) | |
76 | { | |
77 | debugs(79, 3, "DiskThreadsDiskFile::read: " << this << ", size " << request->len); | |
78 | assert (fd > -1); | |
79 | assert (ioRequestor.getRaw()); | |
e4f1fdae | 80 | ++statCounter.syscalls.disk.reads; |
b9ae18aa | 81 | ++inProgressIOs; |
82 | #if ASYNC_READ | |
83 | ||
84 | aioRead(fd, request->offset, request->len, ReadDone, new IoResult<ReadRequest>(this, request)); | |
85 | #else | |
86 | ||
87 | file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult<ReadRequest>(this, request)); | |
88 | #endif | |
89 | } | |
90 | ||
91 | void | |
63be0a78 | 92 | DiskThreadsDiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback) |
b9ae18aa | 93 | { |
e4f1fdae | 94 | ++statCounter.syscalls.disk.opens; |
b9ae18aa | 95 | #if !ASYNC_CREATE |
96 | ||
97 | int fd = file_open(path_, flags); | |
98 | ||
99 | if (fd < 0) { | |
bf8fe701 | 100 | debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno << ")"); |
b9ae18aa | 101 | errorOccured = true; |
102 | return; | |
103 | } | |
104 | ||
105 | #endif | |
cb4185f1 | 106 | ++Opening_FD; |
b9ae18aa | 107 | |
108 | ioRequestor = callback; | |
109 | ||
110 | ++inProgressIOs; | |
111 | ||
112 | #if ASYNC_CREATE | |
113 | ||
114 | aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this); | |
115 | ||
116 | #else | |
117 | ||
118 | openDone (fd, NULL, fd, 0); | |
119 | ||
120 | #endif | |
121 | } | |
122 | ||
123 | bool | |
124 | DiskThreadsDiskFile::error() const | |
125 | { | |
126 | return errorOccured; | |
127 | } | |
128 | ||
129 | void | |
130 | DiskThreadsDiskFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno) | |
131 | { | |
132 | DiskThreadsDiskFile *myFile = static_cast<DiskThreadsDiskFile *>(cbdata); | |
133 | myFile->openDone (fd, buf, aio_return, aio_errno); | |
134 | } | |
135 | ||
136 | void | |
ced8def3 | 137 | DiskThreadsDiskFile::openDone(int, const char *, int anFD, int errflag) |
b9ae18aa | 138 | { |
bf8fe701 | 139 | debugs(79, 3, "DiskThreadsDiskFile::openDone: FD " << anFD << ", errflag " << errflag); |
5e263176 | 140 | --Opening_FD; |
b9ae18aa | 141 | |
142 | fd = anFD; | |
143 | ||
144 | if (errflag || fd < 0) { | |
b69e9ffa | 145 | debugs(79, DBG_CRITICAL, MYNAME << xstrerr(errflag)); |
e0236918 | 146 | debugs(79, DBG_IMPORTANT, "\t" << path_); |
b9ae18aa | 147 | errorOccured = true; |
148 | } else { | |
cb4185f1 | 149 | ++store_open_disk_fd; |
b9ae18aa | 150 | commSetCloseOnExec(fd); |
151 | fd_open(fd, FD_FILE, path_); | |
152 | } | |
153 | ||
b9ae18aa | 154 | IORequestor::Pointer t = ioRequestor; |
155 | --inProgressIOs; | |
156 | t->ioCompletedNotification(); | |
ac97716e | 157 | |
bf8fe701 | 158 | debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting"); |
b9ae18aa | 159 | } |
160 | ||
161 | void DiskThreadsDiskFile::doClose() | |
162 | { | |
163 | if (fd > -1) { | |
e4f1fdae | 164 | ++statCounter.syscalls.disk.closes; |
d06925a4 | 165 | #if ASYNC_CLOSE |
166 | ||
b9ae18aa | 167 | aioClose(fd); |
168 | fd_close(fd); | |
d06925a4 | 169 | #else |
170 | ||
171 | aioCancel(fd); | |
172 | file_close(fd); | |
173 | #endif | |
174 | ||
5e263176 | 175 | --store_open_disk_fd; |
b9ae18aa | 176 | fd = -1; |
177 | } | |
178 | } | |
179 | ||
180 | void | |
63be0a78 | 181 | DiskThreadsDiskFile::close() |
b9ae18aa | 182 | { |
bf8fe701 | 183 | debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor.getRaw()); |
b9ae18aa | 184 | |
185 | if (!ioInProgress()) { | |
186 | doClose(); | |
ac97716e | 187 | assert (ioRequestor != NULL); |
b9ae18aa | 188 | ioRequestor->closeCompleted(); |
ac97716e | 189 | return; |
190 | } else { | |
fa84c01d | 191 | debugs(79, DBG_CRITICAL, HERE << "DiskThreadsDiskFile::close: " << |
ac97716e | 192 | "did NOT close because ioInProgress() is true. now what?"); |
b9ae18aa | 193 | } |
194 | } | |
195 | ||
196 | bool | |
197 | DiskThreadsDiskFile::canRead() const | |
198 | { | |
bf8fe701 | 199 | debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd); |
b9ae18aa | 200 | return fd > -1; |
201 | } | |
202 | ||
203 | void | |
204 | DiskThreadsDiskFile::write(WriteRequest * writeRequest) | |
205 | { | |
bf8fe701 | 206 | debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd); |
e4f1fdae | 207 | ++statCounter.syscalls.disk.writes; |
b9ae18aa | 208 | ++inProgressIOs; |
209 | #if ASYNC_WRITE | |
210 | ||
211 | aioWrite(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest), | |
212 | writeRequest->free_func); | |
213 | #else | |
214 | ||
215 | file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest), | |
216 | writeRequest->free_func); | |
217 | #endif | |
218 | } | |
219 | ||
220 | bool | |
221 | DiskThreadsDiskFile::canWrite() const | |
222 | { | |
223 | return fd > -1; | |
224 | } | |
225 | ||
226 | bool | |
63be0a78 | 227 | DiskThreadsDiskFile::ioInProgress() const |
b9ae18aa | 228 | { |
229 | return inProgressIOs > 0; | |
230 | } | |
231 | ||
232 | /* === STATIC =========================================================== */ | |
233 | ||
234 | #if ASYNC_READ | |
235 | void | |
236 | DiskThreadsDiskFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag) | |
237 | #else | |
238 | void | |
239 | DiskThreadsDiskFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data) | |
240 | #endif | |
241 | { | |
242 | IoResult<ReadRequest> * result = static_cast<IoResult<ReadRequest> *>(my_data); | |
243 | assert (result); | |
244 | result->file->readDone(fd, buf, len, errflag, result->request); | |
245 | delete result; | |
246 | } | |
247 | ||
248 | void | |
63be0a78 | 249 | DiskThreadsDiskFile::readDone(int rvfd, const char *buf, int len, int errflag, RefCount<ReadRequest> request) |
b9ae18aa | 250 | { |
bf8fe701 | 251 | debugs(79, 3, "DiskThreadsDiskFile::readDone: FD " << rvfd); |
b9ae18aa | 252 | assert (fd == rvfd); |
253 | ||
254 | ssize_t rlen; | |
255 | ||
256 | if (errflag) { | |
bf8fe701 | 257 | debugs(79, 3, "DiskThreadsDiskFile::readDone: got failure (" << errflag << ")"); |
b9ae18aa | 258 | rlen = -1; |
259 | } else { | |
260 | rlen = (ssize_t) len; | |
261 | } | |
262 | ||
263 | #if ASYNC_READ | |
264 | /* translate errflag from errno to Squid disk error */ | |
265 | errno = errflag; | |
266 | ||
267 | if (errflag) | |
268 | errflag = DISK_ERROR; | |
269 | else | |
270 | errflag = DISK_OK; | |
271 | ||
272 | #else | |
273 | ||
274 | if (errflag == DISK_EOF) | |
f53969cc | 275 | errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ |
b9ae18aa | 276 | |
277 | #endif | |
278 | ||
279 | --inProgressIOs; | |
280 | ||
281 | ioRequestor->readCompleted(buf, rlen, errflag, request); | |
282 | } | |
283 | ||
284 | void | |
285 | DiskThreadsDiskFile:: | |
286 | #if ASYNC_WRITE | |
a37ea9a1 | 287 | WriteDone(int fd, void *my_data, const char *buf, int len, int errflag) |
b9ae18aa | 288 | #else |
289 | WriteDone(int fd, int errflag, size_t len, void *my_data) | |
290 | #endif | |
291 | { | |
292 | IoResult<WriteRequest> * result = static_cast<IoResult<WriteRequest> *>(my_data); | |
293 | assert (result); | |
294 | result->file->writeDone(fd, errflag, len, result->request); | |
295 | delete result; | |
296 | } | |
297 | ||
298 | void | |
63be0a78 | 299 | DiskThreadsDiskFile::writeDone(int rvfd, int errflag, size_t len, RefCount<WriteRequest> request) |
b9ae18aa | 300 | { |
301 | assert (rvfd == fd); | |
302 | static int loop_detect = 0; | |
b9ae18aa | 303 | |
304 | #if ASYNC_WRITE | |
305 | /* Translate from errno to Squid disk error */ | |
b9ae18aa | 306 | |
307 | if (errflag) | |
a37ea9a1 | 308 | errflag = errflag == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; |
b9ae18aa | 309 | else |
310 | errflag = DISK_OK; | |
311 | ||
312 | #endif | |
313 | ||
4a7a3d56 | 314 | debugs(79, 3, "DiskThreadsDiskFile::writeDone: FD " << fd << ", len " << len << ", err=" << errflag); |
a37ea9a1 | 315 | |
7f56277d AJ |
316 | ++loop_detect; |
317 | assert(loop_detect < 10); | |
b9ae18aa | 318 | |
319 | --inProgressIOs; | |
320 | ||
321 | ioRequestor->writeCompleted(errflag, len, request); | |
322 | ||
323 | --loop_detect; | |
324 | } | |
325 | ||
d6d0eb11 | 326 | /** \cond AUTODOCS_IGNORE */ |
b9ae18aa | 327 | template <class RT> |
328 | cbdata_type IoResult<RT>::CBDATA_IoResult = CBDATA_UNKNOWN; | |
d85b8894 | 329 | /** \endcond */ |
f53969cc | 330 |