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