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