]> git.ipfire.org Git - thirdparty/squid.git/blame - src/fs/ufs/UFSStoreState.cc
Store API and layout polishing. No functionality changes intended.
[thirdparty/squid.git] / src / fs / ufs / UFSStoreState.cc
CommitLineData
cd748f27 1/*
bde978a6 2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
cd748f27 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.
cd748f27 7 */
8
bbc27441
AJ
9/* DEBUG: section 79 Storage Manager UFS Interface */
10
582c2af2 11#include "squid.h"
b9ae18aa 12#include "DiskIO/DiskFile.h"
13#include "DiskIO/DiskIOStrategy.h"
14#include "DiskIO/ReadRequest.h"
15#include "DiskIO/WriteRequest.h"
602d9612 16#include "Generic.h"
41c97755 17#include "SquidList.h"
602d9612 18#include "Store.h"
2745fea5 19#include "store/Disk.h"
58373ff8 20#include "UFSStoreState.h"
602d9612 21#include "UFSStrategy.h"
cd748f27 22
58373ff8 23CBDATA_NAMESPACED_CLASS_INIT(Fs::Ufs,UFSStoreState);
72711e31 24
cd748f27 25void
58373ff8 26Fs::Ufs::UFSStoreState::ioCompletedNotification()
cd748f27 27{
d3b3ab85 28 if (opening) {
62e76326 29 opening = false;
bf8fe701 30 debugs(79, 3, "UFSStoreState::ioCompletedNotification: dirno " <<
31 swap_dirn << ", fileno "<< std::setfill('0') << std::hex <<
32 std::setw(8) << swap_filen << " status "<< std::setfill(' ') <<
33 std::dec << theFile->error());
34
59b2d47f 35 assert (FILE_MODE(mode) == O_RDONLY);
36 openDone();
37
62e76326 38 return;
d3b3ab85 39 }
62e76326 40
d3b3ab85 41 if (creating) {
62e76326 42 creating = false;
bf8fe701 43 debugs(79, 3, "UFSStoreState::ioCompletedNotification: dirno " <<
44 swap_dirn << ", fileno "<< std::setfill('0') << std::hex <<
45 std::setw(8) << swap_filen << " status "<< std::setfill(' ') <<
46 std::dec << theFile->error());
47
59b2d47f 48 openDone();
49
62e76326 50 return;
d3b3ab85 51 }
62e76326 52
59b2d47f 53 assert (!(closing ||opening));
bf8fe701 54 debugs(79, 3, "diskd::ioCompleted: dirno " << swap_dirn << ", fileno "<<
55 std::setfill('0') << std::hex << std::setw(8) << swap_filen <<
56 " status "<< std::setfill(' ') << std::dec << theFile->error());
57
59b2d47f 58 /* Ok, notification past open means an error has occured */
59 assert (theFile->error());
1e0d7905 60 tryClosing();
d3b3ab85 61}
cd748f27 62
d3b3ab85 63void
58373ff8 64Fs::Ufs::UFSStoreState::openDone()
d3b3ab85 65{
1e0d7905 66 if (closing)
fa84c01d 67 debugs(0, DBG_CRITICAL, HERE << "already closing in openDone()!?");
1e0d7905 68
59b2d47f 69 if (theFile->error()) {
1e0d7905 70 tryClosing();
59b2d47f 71 return;
72 }
73
74 if (FILE_MODE(mode) == O_WRONLY) {
1e0d7905 75 drainWriteQueue();
76
59b2d47f 77 } else if ((FILE_MODE(mode) == O_RDONLY) && !closing) {
78 if (kickReadQueue())
79 return;
80 }
81
1e0d7905 82 if (flags.try_closing)
83 tryClosing();
59b2d47f 84
bf8fe701 85 debugs(79, 3, "UFSStoreState::openDone: exiting");
d3b3ab85 86}
87
88void
58373ff8 89Fs::Ufs::UFSStoreState::closeCompleted()
d3b3ab85 90{
59b2d47f 91 assert (closing);
bf8fe701 92 debugs(79, 3, "UFSStoreState::closeCompleted: dirno " << swap_dirn <<
93 ", fileno "<< std::setfill('0') << std::hex << std::setw(8) <<
94 swap_filen << " status "<< std::setfill(' ') << std::dec <<
95 theFile->error());
62e76326 96
1e0d7905 97 if (theFile->error()) {
98 debugs(79,3,HERE<< "theFile->error() ret " << theFile->error());
3e2cded3 99 doCloseCallback(DISK_ERROR);
1e0d7905 100 } else {
3e2cded3 101 doCloseCallback(DISK_OK);
1e0d7905 102 }
59b2d47f 103
104 closing = false;
105}
106
1e0d7905 107/*
108 * DPW 2006-05-24
109 * This close function is called by the higher layer when it has finished
110 * reading/writing everything, or otherwise wants to close the swap
111 * file. In the case of writing and using aufs storage, close() might
112 * be called before any/all data is written, and even before the open
113 * callback occurs. Thus, we use our tryClosing() method, which knows
114 * when it is safe to actually signal the lower layer for closing.
115 */
59b2d47f 116void
58373ff8 117Fs::Ufs::UFSStoreState::close(int)
59b2d47f 118{
bf8fe701 119 debugs(79, 3, "UFSStoreState::close: dirno " << swap_dirn << ", fileno "<<
120 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
aa1a691e 121 tryClosing(); // UFS does not distinguish different closure types
d3b3ab85 122}
123
124void
58373ff8 125Fs::Ufs::UFSStoreState::read_(char *buf, size_t size, off_t aOffset, STRCB * aCallback, void *aCallbackData)
d3b3ab85 126{
127 assert(read.callback == NULL);
128 assert(read.callback_data == NULL);
129 assert(!reading);
130 assert(!closing);
e4ae841b 131 assert (aCallback);
62e76326 132
d3b3ab85 133 if (!theFile->canRead()) {
bf8fe701 134 debugs(79, 3, "UFSStoreState::read_: queueing read because theFile can't read");
18ec8500 135 queueRead (buf, size, aOffset, aCallback, aCallbackData);
62e76326 136 return;
cd748f27 137 }
62e76326 138
e4ae841b
FC
139 read.callback = aCallback;
140 read.callback_data = cbdataReference(aCallbackData);
bf8fe701 141 debugs(79, 3, "UFSStoreState::read_: dirno " << swap_dirn << ", fileno "<<
142 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
18ec8500 143 offset_ = aOffset;
d3b3ab85 144 read_buf = buf;
145 reading = true;
18ec8500 146 theFile->read(new ReadRequest(buf,aOffset,size));
d3b3ab85 147}
62e76326 148
1e0d7905 149/*
150 * DPW 2006-05-24
151 * This, the public write interface, places the write request at the end
152 * of the pending_writes queue to ensure correct ordering of writes.
153 * We could optimize things a little if there are no other pending
154 * writes and just do the write directly. But for now we'll keep the
155 * code simpler and always go through the pending_writes queue.
156 */
90e8b325 157bool
58373ff8 158Fs::Ufs::UFSStoreState::write(char const *buf, size_t size, off_t aOffset, FREE * free_func)
d3b3ab85 159{
bf8fe701 160 debugs(79, 3, "UFSStoreState::write: dirn " << swap_dirn << ", fileno "<<
161 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
62e76326 162
1e0d7905 163 if (theFile->error()) {
e0236918
FC
164 debugs(79, DBG_IMPORTANT,HERE << "avoid write on theFile with error");
165 debugs(79, DBG_IMPORTANT,HERE << "calling free_func for " << (void*) buf);
1e0d7905 166 free_func((void*)buf);
90e8b325 167 return false;
1e0d7905 168 }
169
18ec8500 170 queueWrite(buf, size, aOffset, free_func);
1e0d7905 171 drainWriteQueue();
90e8b325 172 return true;
1e0d7905 173}
174
1e0d7905 175/*
176 * DPW 2006-05-24
177 * This, the private write method, calls the lower level write for the
178 * first write request in the pending_writes queue. doWrite() is only
179 * called by drainWriteQueue().
180 */
181void
58373ff8 182Fs::Ufs::UFSStoreState::doWrite()
1e0d7905 183{
184 debugs(79, 3, HERE << this << " UFSStoreState::doWrite");
185
186 assert(theFile->canWrite());
187
188 _queued_write *q = (_queued_write *)linklistShift(&pending_writes);
189
190 if (q == NULL) {
191 debugs(79, 3, HERE << this << " UFSStoreState::doWrite queue is empty");
192 return;
193 }
194
195 if (theFile->error()) {
e0236918 196 debugs(79, DBG_IMPORTANT,HERE << "avoid write on theFile with error");
1e0d7905 197 debugs(79,3,HERE << "calling free_func for " << (void*) q->buf);
198 /*
199 * DPW 2006-05-24
200 * Note "free_func" is memNodeWriteComplete(), which doesn't
201 * really free the memory. Instead it clears the node's
202 * write_pending flag.
203 */
204 q->free_func((void*)q->buf);
9db2e213 205 delete q;
62e76326 206 return;
d3b3ab85 207 }
62e76326 208
1e0d7905 209 /*
210 * DPW 2006-05-24
211 * UFSStoreState has a 'writing' flag that we used to set here,
212 * but it wasn't really used anywhere. In fact, some lower
213 * layers such as DISKD allow multiple outstanding writes, which
214 * makes the boolean writing flag meaningless. We would need
215 * a counter to keep track of writes going out and write callbacks
216 * coming in. For now let's just not use the writing flag at
217 * all.
218 */
219 debugs(79, 3, HERE << this << " calling theFile->write(" << q->size << ")");
220
221 theFile->write(new WriteRequest(q->buf, q->offset, q->size, q->free_func));
9db2e213 222 delete q;
d3b3ab85 223}
224
225void
ced8def3 226Fs::Ufs::UFSStoreState::readCompleted(const char *buf, int len, int, RefCount<ReadRequest> result)
d3b3ab85 227{
b9ae18aa 228 assert (result.getRaw());
d3b3ab85 229 reading = false;
bf8fe701 230 debugs(79, 3, "UFSStoreState::readCompleted: dirno " << swap_dirn <<
231 ", fileno "<< std::setfill('0') << std::hex << std::setw(8) <<
232 swap_filen << " len "<< std::setfill(' ') << std::dec << len);
62e76326 233
d3b3ab85 234 if (len > 0)
62e76326 235 offset_ += len;
236
e4ae841b 237 STRCB *callback_ = read.callback;
62e76326 238
e4ae841b 239 assert(callback_);
62e76326 240
d3b3ab85 241 read.callback = NULL;
62e76326 242
d3b3ab85 243 void *cbdata;
62e76326 244
59b2d47f 245 /* A note:
246 * diskd IO queues closes via the diskd queue. So close callbacks
247 * occur strictly after reads and writes.
248 * ufs doesn't queue, it simply completes, so close callbacks occur
249 * strictly after reads and writes.
250 * aufs performs closes syncronously, so close events must be managed
251 * to force strict ordering.
252 * The below does this:
1e0d7905 253 * closing is set when theFile->close() has been called, and close only triggers
59b2d47f 254 * when no io's are pending.
255 * writeCompleted likewise.
256 */
d3b3ab85 257 if (!closing && cbdataReferenceValidDone(read.callback_data, &cbdata)) {
62e76326 258 if (len > 0 && read_buf != buf)
259 memcpy(read_buf, buf, len);
260
e4ae841b 261 callback_(cbdata, read_buf, len, this);
1e0d7905 262 }
263
8bc0c94b 264 if (flags.try_closing || (theFile != NULL && theFile->error()) )
1e0d7905 265 tryClosing();
d3b3ab85 266}
267
268void
ced8def3 269Fs::Ufs::UFSStoreState::writeCompleted(int, size_t len, RefCount<WriteRequest>)
d3b3ab85 270{
983983ce 271 debugs(79, 3, HERE << "dirno " << swap_dirn << ", fileno " <<
26ac0430 272 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen <<
983983ce 273 ", len " << len);
1e0d7905 274 /*
275 * DPW 2006-05-24
276 * See doWrites() for why we don't update UFSStoreState::writing
277 * here anymore.
278 */
62e76326 279
59b2d47f 280 offset_ += len;
281
282 if (theFile->error()) {
983983ce 283 debugs(79,2,HERE << " detected an error, will try to close");
1e0d7905 284 tryClosing();
59b2d47f 285 }
bdf5b250 286
287 /*
8c212619
HN
288 * HNO 2009-07-24
289 * Kick any pending write/close operations alive
bdf5b250 290 */
8c212619 291 drainWriteQueue();
d3b3ab85 292}
293
294void
58373ff8 295Fs::Ufs::UFSStoreState::doCloseCallback(int errflag)
cd748f27 296{
bf8fe701 297 debugs(79, 3, "storeUfsIOCallback: errflag=" << errflag);
1e0d7905 298 /*
299 * DPW 2006-05-24
300 * When we signal the higher layer with this callback, it might unlock
301 * the StoreEntry and its associated data. We must "free" any queued
302 * I/Os (especially writes) now, otherwise the StoreEntry's mem_node's
303 * will have their write_pending flag set, and we'll get an assertion.
304 */
305 freePending();
59b2d47f 306 STIOCB *theCallback = callback;
d3b3ab85 307 callback = NULL;
d3b3ab85 308
59b2d47f 309 void *cbdata;
d3b3ab85 310
59b2d47f 311 if (cbdataReferenceValidDone(callback_data, &cbdata) && theCallback)
e5de8b13 312 theCallback(cbdata, errflag, this);
7fbb6b8f 313
1e0d7905 314 /*
315 * We are finished with theFile since the lower layer signalled
316 * us that the file has been closed. This must be the last line,
317 * as theFile may be the only object holding us in memory.
7fbb6b8f 318 */
f53969cc 319 theFile = NULL; // refcounted
59b2d47f 320}
d3b3ab85 321
322/* ============= THE REAL UFS CODE ================ */
323
cc8c4af2
AJ
324Fs::Ufs::UFSStoreState::UFSStoreState(SwapDir * SD, StoreEntry * anEntry, STIOCB * cbIo, void *data) :
325 StoreIOState(NULL, cbIo, data),
326 opening(false),
327 creating(false),
328 closing(false),
329 reading(false),
330 writing(false),
331 pending_reads(NULL),
332 pending_writes(NULL),
333 read_buf(NULL)
59b2d47f 334{
cc8c4af2 335 // StoreIOState inherited members
59b2d47f 336 swap_filen = anEntry->swap_filen;
337 swap_dirn = SD->index;
59b2d47f 338 e = anEntry;
cc8c4af2
AJ
339
340 // our flags
1e0d7905 341 flags.write_draining = false;
342 flags.try_closing = false;
59b2d47f 343}
62e76326 344
58373ff8 345Fs::Ufs::UFSStoreState::~UFSStoreState()
1e0d7905 346{
347 assert(pending_reads == NULL);
348 assert(pending_writes == NULL);
349}
350
351void
58373ff8 352Fs::Ufs::UFSStoreState::freePending()
d3b3ab85 353{
354 _queued_read *qr;
62e76326 355
d3b3ab85 356 while ((qr = (_queued_read *)linklistShift(&pending_reads))) {
62e76326 357 cbdataReferenceDone(qr->callback_data);
358 delete qr;
d3b3ab85 359 }
360
1e0d7905 361 debugs(79,3,HERE << "UFSStoreState::freePending: freed pending reads");
362
5aeabf95 363 _queued_write *qw;
62e76326 364
5aeabf95 365 while ((qw = (_queued_write *)linklistShift(&pending_writes))) {
62e76326 366 if (qw->free_func)
367 qw->free_func(const_cast<char *>(qw->buf));
368 delete qw;
d3b3ab85 369 }
1e0d7905 370
371 debugs(79,3,HERE << "UFSStoreState::freePending: freed pending writes");
d3b3ab85 372}
373
374bool
58373ff8 375Fs::Ufs::UFSStoreState::kickReadQueue()
d3b3ab85 376{
377 _queued_read *q = (_queued_read *)linklistShift(&pending_reads);
62e76326 378
d3b3ab85 379 if (NULL == q)
62e76326 380 return false;
381
4a7a3d56 382 debugs(79, 3, "UFSStoreState::kickReadQueue: reading queued request of " << q->size << " bytes");
62e76326 383
d3b3ab85 384 void *cbdata;
62e76326 385
dc5348e9 386 if (cbdataReferenceValidDone(q->callback_data, &cbdata)) {
62e76326 387 read_(q->buf, q->size, q->offset, q->callback, cbdata);
39d70ea8 388 } else {
dc5348e9
AJ
389 debugs(79, 2, "UFSStoreState::kickReadQueue: this: " << this << " cbdataReferenceValidDone returned false." << " closing: " << closing << " flags.try_closing: " << flags.try_closing);
390 delete q;
391 return false;
392 }
62e76326 393
d3b3ab85 394 delete q;
62e76326 395
d3b3ab85 396 return true;
397}
398
d3b3ab85 399void
58373ff8 400Fs::Ufs::UFSStoreState::queueRead(char *buf, size_t size, off_t aOffset, STRCB *callback_, void *callback_data_)
d3b3ab85 401{
bf8fe701 402 debugs(79, 3, "UFSStoreState::queueRead: queueing read");
d3b3ab85 403 assert(opening);
404 assert (pending_reads == NULL);
405 _queued_read *q = new _queued_read;
406 q->buf = buf;
407 q->size = size;
18ec8500 408 q->offset = aOffset;
e4ae841b
FC
409 q->callback = callback_;
410 q->callback_data = cbdataReference(callback_data_);
d3b3ab85 411 linklistPush(&pending_reads, q);
412}
413
1e0d7905 414/*
415 * DPW 2006-05-24
416 * drainWriteQueue() is a loop around doWrite().
417 */
418void
58373ff8 419Fs::Ufs::UFSStoreState::drainWriteQueue()
cd748f27 420{
2eaddcc2 421 /*
422 * DPW 2007-04-12
423 * We might find that flags.write_draining is already set
424 * because schemes like diskd can process I/O acks
425 * before sending another I/O request. e.g. the following
426 * sequence of events: open request -> write request ->
427 * drainWriteQueue() -> queue full -> callbacks -> openDone() ->
428 * drainWriteQueue().
429 */
430 if (flags.write_draining)
26ac0430 431 return;
62e76326 432
1e0d7905 433 if (!theFile->canWrite())
434 return;
62e76326 435
1e0d7905 436 flags.write_draining = true;
62e76326 437
1e0d7905 438 while (pending_writes != NULL) {
439 doWrite();
440 }
441
442 flags.write_draining = false;
443
444 if (flags.try_closing)
445 tryClosing();
446}
447
448/*
449 * DPW 2006-05-24
f53969cc 450 * This blows. DiskThreadsDiskFile::close() won't actually do the close
1e0d7905 451 * if ioInProgress() is true. So we have to check it here. Maybe someday
452 * DiskThreadsDiskFile::close() will be modified to have a return value,
453 * or will remember to do the close for us.
454 */
455void
58373ff8 456Fs::Ufs::UFSStoreState::tryClosing()
1e0d7905 457{
458 debugs(79,3,HERE << this << " tryClosing()" <<
459 " closing = " << closing <<
460 " flags.try_closing = " << flags.try_closing <<
461 " ioInProgress = " << theFile->ioInProgress());
462
463 if (theFile->ioInProgress()) {
26ac0430
AJ
464 debugs(79, 3, HERE << this <<
465 " won't close since ioInProgress is true, bailing");
1e0d7905 466 flags.try_closing = true;
467 return;
468 }
469
470 closing = true;
471 flags.try_closing = false;
472 theFile->close();
d3b3ab85 473}
474
475void
58373ff8 476Fs::Ufs::UFSStoreState::queueWrite(char const *buf, size_t size, off_t aOffset, FREE * free_func)
d3b3ab85 477{
1e0d7905 478 debugs(79, 3, HERE << this << " UFSStoreState::queueWrite: queueing write of size " << size);
62e76326 479
5aeabf95 480 _queued_write *q;
d3b3ab85 481 q = new _queued_write;
482 q->buf = buf;
483 q->size = size;
18ec8500 484 q->offset = aOffset;
d3b3ab85 485 q->free_func = free_func;
486 linklistPush(&pending_writes, q);
487}
488