]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/fs/ufs/store_io_ufs.cc
5 * DEBUG: section 79 Storage Manager UFS Interface
6 * AUTHOR: Duane Wessels
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
38 #include "ufscommon.h"
40 #include "DiskIO/DiskFile.h"
41 #include "DiskIO/DiskIOStrategy.h"
42 #include "DiskIO/ReadRequest.h"
43 #include "DiskIO/WriteRequest.h"
48 UFSStrategy::shedLoad()
50 return io
->shedLoad();
59 UFSStrategy::UFSStrategy (DiskIOStrategy
*anIO
) : io(anIO
)
62 UFSStrategy::~UFSStrategy ()
68 UFSStrategy::createState(SwapDir
*SD
, StoreEntry
*e
, StoreIOState::STIOCB
* aCallback
, void *callback_data
) const
70 return new UFSStoreState (SD
, e
, aCallback
, callback_data
);
74 UFSStrategy::newFile (char const *path
)
76 return io
->newFile(path
);
81 UFSStrategy::unlinkFile(char const *path
)
86 CBDATA_CLASS_INIT(UFSStoreState
);
89 UFSStoreState::operator new (size_t)
91 CBDATA_INIT_TYPE(UFSStoreState
);
92 return cbdataAlloc(UFSStoreState
);
96 UFSStoreState::operator delete (void *address
)
102 UFSStoreState::ioCompletedNotification()
106 debugs(79, 3, "UFSStoreState::ioCompletedNotification: dirno " <<
107 swap_dirn
<< ", fileno "<< std::setfill('0') << std::hex
<<
108 std::setw(8) << swap_filen
<< " status "<< std::setfill(' ') <<
109 std::dec
<< theFile
->error());
111 assert (FILE_MODE(mode
) == O_RDONLY
);
119 debugs(79, 3, "UFSStoreState::ioCompletedNotification: dirno " <<
120 swap_dirn
<< ", fileno "<< std::setfill('0') << std::hex
<<
121 std::setw(8) << swap_filen
<< " status "<< std::setfill(' ') <<
122 std::dec
<< theFile
->error());
129 assert (!(closing
||opening
));
130 debugs(79, 3, "diskd::ioCompleted: dirno " << swap_dirn
<< ", fileno "<<
131 std::setfill('0') << std::hex
<< std::setw(8) << swap_filen
<<
132 " status "<< std::setfill(' ') << std::dec
<< theFile
->error());
134 /* Ok, notification past open means an error has occured */
135 assert (theFile
->error());
140 UFSStoreState::openDone()
143 debugs(0,0,HERE
<< "already closing in openDone()!?");
145 if (theFile
->error()) {
150 if (FILE_MODE(mode
) == O_WRONLY
) {
153 } else if ((FILE_MODE(mode
) == O_RDONLY
) && !closing
) {
158 if (flags
.try_closing
)
161 debugs(79, 3, "UFSStoreState::openDone: exiting");
165 UFSStoreState::closeCompleted()
168 debugs(79, 3, "UFSStoreState::closeCompleted: dirno " << swap_dirn
<<
169 ", fileno "<< std::setfill('0') << std::hex
<< std::setw(8) <<
170 swap_filen
<< " status "<< std::setfill(' ') << std::dec
<<
173 if (theFile
->error()) {
174 debugs(79,3,HERE
<< "theFile->error() ret " << theFile
->error());
175 doCloseCallback(DISK_ERROR
);
177 doCloseCallback(DISK_OK
);
185 * This close function is called by the higher layer when it has finished
186 * reading/writing everything, or otherwise wants to close the swap
187 * file. In the case of writing and using aufs storage, close() might
188 * be called before any/all data is written, and even before the open
189 * callback occurs. Thus, we use our tryClosing() method, which knows
190 * when it is safe to actually signal the lower layer for closing.
193 UFSStoreState::close()
195 debugs(79, 3, "UFSStoreState::close: dirno " << swap_dirn
<< ", fileno "<<
196 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
);
201 UFSStoreState::read_(char *buf
, size_t size
, off_t aOffset
, STRCB
* aCallback
, void *aCallbackData
)
203 assert(read
.callback
== NULL
);
204 assert(read
.callback_data
== NULL
);
209 if (!theFile
->canRead()) {
210 debugs(79, 3, "UFSStoreState::read_: queueing read because theFile can't read");
211 queueRead (buf
, size
, aOffset
, aCallback
, aCallbackData
);
215 read
.callback
= aCallback
;
216 read
.callback_data
= cbdataReference(aCallbackData
);
217 debugs(79, 3, "UFSStoreState::read_: dirno " << swap_dirn
<< ", fileno "<<
218 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
);
222 theFile
->read(new ReadRequest(buf
,aOffset
,size
));
228 * This, the public write interface, places the write request at the end
229 * of the pending_writes queue to ensure correct ordering of writes.
230 * We could optimize things a little if there are no other pending
231 * writes and just do the write directly. But for now we'll keep the
232 * code simpler and always go through the pending_writes queue.
235 UFSStoreState::write(char const *buf
, size_t size
, off_t aOffset
, FREE
* free_func
)
237 debugs(79, 3, "UFSStoreState::write: dirn " << swap_dirn
<< ", fileno "<<
238 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
);
240 if (theFile
->error()) {
241 debugs(79,1,HERE
<< "avoid write on theFile with error");
242 debugs(79,1,HERE
<< "calling free_func for " << (void*) buf
);
243 free_func((void*)buf
);
247 queueWrite(buf
, size
, aOffset
, free_func
);
254 * This, the private write method, calls the lower level write for the
255 * first write request in the pending_writes queue. doWrite() is only
256 * called by drainWriteQueue().
259 UFSStoreState::doWrite()
261 debugs(79, 3, HERE
<< this << " UFSStoreState::doWrite");
263 assert(theFile
->canWrite());
265 _queued_write
*q
= (_queued_write
*)linklistShift(&pending_writes
);
268 debugs(79, 3, HERE
<< this << " UFSStoreState::doWrite queue is empty");
272 if (theFile
->error()) {
273 debugs(79,1,HERE
<< "avoid write on theFile with error");
274 debugs(79,3,HERE
<< "calling free_func for " << (void*) q
->buf
);
277 * Note "free_func" is memNodeWriteComplete(), which doesn't
278 * really free the memory. Instead it clears the node's
279 * write_pending flag.
281 q
->free_func((void*)q
->buf
);
288 * UFSStoreState has a 'writing' flag that we used to set here,
289 * but it wasn't really used anywhere. In fact, some lower
290 * layers such as DISKD allow multiple outstanding writes, which
291 * makes the boolean writing flag meaningless. We would need
292 * a counter to keep track of writes going out and write callbacks
293 * coming in. For now let's just not use the writing flag at
296 debugs(79, 3, HERE
<< this << " calling theFile->write(" << q
->size
<< ")");
298 theFile
->write(new WriteRequest(q
->buf
, q
->offset
, q
->size
, q
->free_func
));
303 UFSStoreState::readCompleted(const char *buf
, int len
, int errflag
, RefCount
<ReadRequest
> result
)
305 assert (result
.getRaw());
307 debugs(79, 3, "UFSStoreState::readCompleted: dirno " << swap_dirn
<<
308 ", fileno "<< std::setfill('0') << std::hex
<< std::setw(8) <<
309 swap_filen
<< " len "<< std::setfill(' ') << std::dec
<< len
);
314 STRCB
*callback_
= read
.callback
;
318 read
.callback
= NULL
;
323 * diskd IO queues closes via the diskd queue. So close callbacks
324 * occur strictly after reads and writes.
325 * ufs doesn't queue, it simply completes, so close callbacks occur
326 * strictly after reads and writes.
327 * aufs performs closes syncronously, so close events must be managed
328 * to force strict ordering.
329 * The below does this:
330 * closing is set when theFile->close() has been called, and close only triggers
331 * when no io's are pending.
332 * writeCompleted likewise.
334 if (!closing
&& cbdataReferenceValidDone(read
.callback_data
, &cbdata
)) {
335 if (len
> 0 && read_buf
!= buf
)
336 memcpy(read_buf
, buf
, len
);
338 callback_(cbdata
, read_buf
, len
, this);
341 if (flags
.try_closing
|| (theFile
!= NULL
&& theFile
->error()) )
346 UFSStoreState::writeCompleted(int errflag
, size_t len
, RefCount
<WriteRequest
> writeRequest
)
348 debugs(79, 3, HERE
<< "dirno " << swap_dirn
<< ", fileno " <<
349 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
<<
353 * See doWrites() for why we don't update UFSStoreState::writing
359 if (theFile
->error()) {
360 debugs(79,2,HERE
<< " detected an error, will try to close");
366 * Kick any pending write/close operations alive
372 UFSStoreState::doCloseCallback(int errflag
)
374 debugs(79, 3, "storeUfsIOCallback: errflag=" << errflag
);
377 * When we signal the higher layer with this callback, it might unlock
378 * the StoreEntry and its associated data. We must "free" any queued
379 * I/Os (especially writes) now, otherwise the StoreEntry's mem_node's
380 * will have their write_pending flag set, and we'll get an assertion.
383 STIOCB
*theCallback
= callback
;
388 if (cbdataReferenceValidDone(callback_data
, &cbdata
) && theCallback
)
389 theCallback(cbdata
, errflag
, this);
392 * We are finished with theFile since the lower layer signalled
393 * us that the file has been closed. This must be the last line,
394 * as theFile may be the only object holding us in memory.
396 theFile
= NULL
; // refcounted
399 /* ============= THE REAL UFS CODE ================ */
401 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
)
403 swap_filen
= anEntry
->swap_filen
;
404 swap_dirn
= SD
->index
;
406 callback
= callback_
;
407 callback_data
= cbdataReference(callback_data_
);
409 flags
.write_draining
= false;
410 flags
.try_closing
= false;
413 UFSStoreState::~UFSStoreState()
415 assert(pending_reads
== NULL
);
416 assert(pending_writes
== NULL
);
420 UFSStoreState::freePending()
424 while ((qr
= (_queued_read
*)linklistShift(&pending_reads
))) {
425 cbdataReferenceDone(qr
->callback_data
);
429 debugs(79,3,HERE
<< "UFSStoreState::freePending: freed pending reads");
433 while ((qw
= (_queued_write
*)linklistShift(&pending_writes
))) {
435 qw
->free_func(const_cast<char *>(qw
->buf
));
439 debugs(79,3,HERE
<< "UFSStoreState::freePending: freed pending writes");
443 UFSStoreState::kickReadQueue()
445 _queued_read
*q
= (_queued_read
*)linklistShift(&pending_reads
);
450 debugs(79, 3, "UFSStoreState::kickReadQueue: reading queued request of " << q
->size
<< " bytes");
454 if (cbdataReferenceValidDone(q
->callback_data
, &cbdata
)) {
455 read_(q
->buf
, q
->size
, q
->offset
, q
->callback
, cbdata
);
457 debugs(79, 2, "UFSStoreState::kickReadQueue: this: " << this << " cbdataReferenceValidDone returned false." << " closing: " << closing
<< " flags.try_closing: " << flags
.try_closing
);
468 UFSStoreState::queueRead(char *buf
, size_t size
, off_t aOffset
, STRCB
*callback_
, void *callback_data_
)
470 debugs(79, 3, "UFSStoreState::queueRead: queueing read");
472 assert (pending_reads
== NULL
);
473 _queued_read
*q
= new _queued_read
;
477 q
->callback
= callback_
;
478 q
->callback_data
= cbdataReference(callback_data_
);
479 linklistPush(&pending_reads
, q
);
484 * drainWriteQueue() is a loop around doWrite().
487 UFSStoreState::drainWriteQueue()
491 * We might find that flags.write_draining is already set
492 * because schemes like diskd can process I/O acks
493 * before sending another I/O request. e.g. the following
494 * sequence of events: open request -> write request ->
495 * drainWriteQueue() -> queue full -> callbacks -> openDone() ->
498 if (flags
.write_draining
)
501 if (!theFile
->canWrite())
504 flags
.write_draining
= true;
506 while (pending_writes
!= NULL
) {
510 flags
.write_draining
= false;
512 if (flags
.try_closing
)
518 * This blows. DiskThreadsDiskFile::close() won't actually do the close
519 * if ioInProgress() is true. So we have to check it here. Maybe someday
520 * DiskThreadsDiskFile::close() will be modified to have a return value,
521 * or will remember to do the close for us.
524 UFSStoreState::tryClosing()
526 debugs(79,3,HERE
<< this << " tryClosing()" <<
527 " closing = " << closing
<<
528 " flags.try_closing = " << flags
.try_closing
<<
529 " ioInProgress = " << theFile
->ioInProgress());
531 if (theFile
->ioInProgress()) {
532 debugs(79, 3, HERE
<< this <<
533 " won't close since ioInProgress is true, bailing");
534 flags
.try_closing
= true;
539 flags
.try_closing
= false;
544 UFSStoreState::queueWrite(char const *buf
, size_t size
, off_t aOffset
, FREE
* free_func
)
546 debugs(79, 3, HERE
<< this << " UFSStoreState::queueWrite: queueing write of size " << size
);
549 q
= new _queued_write
;
553 q
->free_func
= free_func
;
554 linklistPush(&pending_writes
, q
);
557 StoreIOState::Pointer
558 UFSStrategy::open(SwapDir
* SD
, StoreEntry
* e
, StoreIOState::STFNCB
* file_callback
,
559 StoreIOState::STIOCB
* aCallback
, void *callback_data
)
561 assert (((UFSSwapDir
*)SD
)->IO
== this);
562 debugs(79, 3, "UFSStrategy::open: fileno "<< std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << e
->swap_filen
);
564 /* to consider: make createstate a private UFSStrategy call */
565 StoreIOState::Pointer sio
= createState (SD
, e
, aCallback
, callback_data
);
567 sio
->mode
|= O_RDONLY
;
569 UFSStoreState
*state
= dynamic_cast <UFSStoreState
*>(sio
.getRaw());
573 char *path
= ((UFSSwapDir
*)SD
)->fullPath(e
->swap_filen
, NULL
);
575 DiskFile::Pointer myFile
= newFile (path
);
577 if (myFile
.getRaw() == NULL
)
580 state
->theFile
= myFile
;
582 state
->opening
= true;
584 myFile
->open (sio
->mode
, 0644, state
);
592 StoreIOState::Pointer
593 UFSStrategy::create(SwapDir
* SD
, StoreEntry
* e
, StoreIOState::STFNCB
* file_callback
,
594 StoreIOState::STIOCB
* aCallback
, void *callback_data
)
596 assert (((UFSSwapDir
*)SD
)->IO
== this);
597 /* Allocate a number */
598 sfileno filn
= ((UFSSwapDir
*)SD
)->mapBitAllocate();
599 debugs(79, 3, "UFSStrategy::create: fileno "<< std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << filn
);
601 /* Shouldn't we handle a 'bitmap full' error here? */
603 StoreIOState::Pointer sio
= createState (SD
, e
, aCallback
, callback_data
);
605 sio
->mode
|= O_WRONLY
| O_CREAT
| O_TRUNC
;
607 sio
->swap_filen
= filn
;
609 UFSStoreState
*state
= dynamic_cast <UFSStoreState
*>(sio
.getRaw());
613 char *path
= ((UFSSwapDir
*)SD
)->fullPath(filn
, NULL
);
615 DiskFile::Pointer myFile
= newFile (path
);
617 if (myFile
.getRaw() == NULL
) {
618 ((UFSSwapDir
*)SD
)->mapBitReset (filn
);
622 state
->theFile
= myFile
;
624 state
->creating
= true;
626 myFile
->create (state
->mode
, 0644, state
);
628 if (myFile
->error()) {
629 ((UFSSwapDir
*)SD
)->mapBitReset (filn
);
633 /* now insert into the replacement policy */
634 ((UFSSwapDir
*)SD
)->replacementAdd(e
);
640 UFSStrategy::callback()
642 return io
->callback();
658 UFSStrategy::statfs(StoreEntry
& sentry
)const