]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / DiskIO / DiskThreads / DiskThreadsDiskFile.cc
1 /*
2 * Copyright (C) 1996-2020 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 Disk IO Routines */
10
11 #include "squid.h"
12 #include "DiskIO/IORequestor.h"
13 #include "DiskIO/ReadRequest.h"
14 #include "DiskIO/WriteRequest.h"
15 #include "DiskThreadsDiskFile.h"
16 #include "fd.h"
17 #include "fs_io.h"
18 #include "Generic.h"
19 #include "globals.h"
20 #include "StatCounters.h"
21 #include "Store.h"
22
23 #include <cerrno>
24
25 /* === PUBLIC =========================================================== */
26
27 CBDATA_CLASS_INIT(DiskThreadsDiskFile);
28
29 DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath)
30 {
31 assert(aPath);
32 debugs(79, 3, "UFSFile::UFSFile: " << aPath);
33 path_ = xstrdup(aPath);
34 }
35
36 DiskThreadsDiskFile::~DiskThreadsDiskFile()
37 {
38 safe_free(path_);
39 doClose();
40 }
41
42 void
43 DiskThreadsDiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
44 {
45 ++statCounter.syscalls.disk.opens;
46 #if !ASYNC_OPEN
47
48 fd = file_open(path_, flags);
49
50 if (fd < 0) {
51 debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno << ")");
52 errorOccured = true;
53 return;
54 }
55
56 #endif
57 ++Opening_FD;
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());
80 ++statCounter.syscalls.disk.reads;
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
92 DiskThreadsDiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback)
93 {
94 ++statCounter.syscalls.disk.opens;
95 #if !ASYNC_CREATE
96
97 int fd = file_open(path_, flags);
98
99 if (fd < 0) {
100 debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno << ")");
101 errorOccured = true;
102 return;
103 }
104
105 #endif
106 ++Opening_FD;
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
137 DiskThreadsDiskFile::openDone(int, const char *, int anFD, int errflag)
138 {
139 debugs(79, 3, "DiskThreadsDiskFile::openDone: FD " << anFD << ", errflag " << errflag);
140 --Opening_FD;
141
142 fd = anFD;
143
144 if (errflag || fd < 0) {
145 debugs(79, DBG_CRITICAL, MYNAME << xstrerr(errflag));
146 debugs(79, DBG_IMPORTANT, "\t" << path_);
147 errorOccured = true;
148 } else {
149 ++store_open_disk_fd;
150 commSetCloseOnExec(fd);
151 fd_open(fd, FD_FILE, path_);
152 }
153
154 IORequestor::Pointer t = ioRequestor;
155 --inProgressIOs;
156 t->ioCompletedNotification();
157
158 debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting");
159 }
160
161 void DiskThreadsDiskFile::doClose()
162 {
163 if (fd > -1) {
164 ++statCounter.syscalls.disk.closes;
165 #if ASYNC_CLOSE
166
167 aioClose(fd);
168 fd_close(fd);
169 #else
170
171 aioCancel(fd);
172 file_close(fd);
173 #endif
174
175 --store_open_disk_fd;
176 fd = -1;
177 }
178 }
179
180 void
181 DiskThreadsDiskFile::close()
182 {
183 debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor.getRaw());
184
185 if (!ioInProgress()) {
186 doClose();
187 assert (ioRequestor != NULL);
188 ioRequestor->closeCompleted();
189 return;
190 } else {
191 debugs(79, DBG_CRITICAL, HERE << "DiskThreadsDiskFile::close: " <<
192 "did NOT close because ioInProgress() is true. now what?");
193 }
194 }
195
196 bool
197 DiskThreadsDiskFile::canRead() const
198 {
199 debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd);
200 return fd > -1;
201 }
202
203 void
204 DiskThreadsDiskFile::write(WriteRequest * writeRequest)
205 {
206 debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd);
207 ++statCounter.syscalls.disk.writes;
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
227 DiskThreadsDiskFile::ioInProgress() const
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
249 DiskThreadsDiskFile::readDone(int rvfd, const char *buf, int len, int errflag, RefCount<ReadRequest> request)
250 {
251 debugs(79, 3, "DiskThreadsDiskFile::readDone: FD " << rvfd);
252 assert (fd == rvfd);
253
254 ssize_t rlen;
255
256 if (errflag) {
257 debugs(79, 3, "DiskThreadsDiskFile::readDone: got failure (" << errflag << ")");
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)
275 errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */
276
277 #endif
278
279 --inProgressIOs;
280
281 ioRequestor->readCompleted(buf, rlen, errflag, request);
282 }
283
284 void
285 DiskThreadsDiskFile::
286 #if ASYNC_WRITE
287 WriteDone(int fd, void *my_data, const char *buf, int len, int errflag)
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
299 DiskThreadsDiskFile::writeDone(int rvfd, int errflag, size_t len, RefCount<WriteRequest> request)
300 {
301 assert (rvfd == fd);
302 static int loop_detect = 0;
303
304 #if ASYNC_WRITE
305 /* Translate from errno to Squid disk error */
306
307 if (errflag)
308 errflag = errflag == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
309 else
310 errflag = DISK_OK;
311
312 #endif
313
314 debugs(79, 3, "DiskThreadsDiskFile::writeDone: FD " << fd << ", len " << len << ", err=" << errflag);
315
316 ++loop_detect;
317 assert(loop_detect < 10);
318
319 --inProgressIOs;
320
321 ioRequestor->writeCompleted(errflag, len, request);
322
323 --loop_detect;
324 }
325
326 /** \cond AUTODOCS_IGNORE */
327 template <class RT>
328 cbdata_type IoResult<RT>::CBDATA_IoResult = CBDATA_UNKNOWN;
329 /** \endcond */
330