]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/fs/ufs/UFSStoreState.cc
3 * DEBUG: section 79 Storage Manager UFS Interface
4 * AUTHOR: Duane Wessels
6 * SQUID Web Proxy Cache http://www.squid-cache.org/
7 * ----------------------------------------------------------
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.
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.
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.
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.
37 #include "DiskIO/DiskFile.h"
38 #include "DiskIO/DiskIOStrategy.h"
39 #include "DiskIO/ReadRequest.h"
40 #include "DiskIO/WriteRequest.h"
41 #include "SquidList.h"
43 #include "UFSStrategy.h"
44 #include "UFSStoreState.h"
46 CBDATA_NAMESPACED_CLASS_INIT(Fs::Ufs
,UFSStoreState
);
49 Fs::Ufs::UFSStoreState::operator new (size_t)
51 CBDATA_INIT_TYPE(UFSStoreState
);
52 return cbdataAlloc(UFSStoreState
);
56 Fs::Ufs::UFSStoreState::operator delete (void *address
)
62 Fs::Ufs::UFSStoreState::ioCompletedNotification()
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());
71 assert (FILE_MODE(mode
) == O_RDONLY
);
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());
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());
94 /* Ok, notification past open means an error has occured */
95 assert (theFile
->error());
100 Fs::Ufs::UFSStoreState::openDone()
103 debugs(0, DBG_CRITICAL
, HERE
<< "already closing in openDone()!?");
105 if (theFile
->error()) {
110 if (FILE_MODE(mode
) == O_WRONLY
) {
113 } else if ((FILE_MODE(mode
) == O_RDONLY
) && !closing
) {
118 if (flags
.try_closing
)
121 debugs(79, 3, "UFSStoreState::openDone: exiting");
125 Fs::Ufs::UFSStoreState::closeCompleted()
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
<<
133 if (theFile
->error()) {
134 debugs(79,3,HERE
<< "theFile->error() ret " << theFile
->error());
135 doCloseCallback(DISK_ERROR
);
137 doCloseCallback(DISK_OK
);
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.
153 Fs::Ufs::UFSStoreState::close(int)
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
161 Fs::Ufs::UFSStoreState::read_(char *buf
, size_t size
, off_t aOffset
, STRCB
* aCallback
, void *aCallbackData
)
163 assert(read
.callback
== NULL
);
164 assert(read
.callback_data
== NULL
);
169 if (!theFile
->canRead()) {
170 debugs(79, 3, "UFSStoreState::read_: queueing read because theFile can't read");
171 queueRead (buf
, size
, aOffset
, aCallback
, aCallbackData
);
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
);
182 theFile
->read(new ReadRequest(buf
,aOffset
,size
));
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.
194 Fs::Ufs::UFSStoreState::write(char const *buf
, size_t size
, off_t aOffset
, FREE
* free_func
)
196 debugs(79, 3, "UFSStoreState::write: dirn " << swap_dirn
<< ", fileno "<<
197 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
);
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
);
206 queueWrite(buf
, size
, aOffset
, free_func
);
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().
217 Fs::Ufs::UFSStoreState::doWrite()
219 debugs(79, 3, HERE
<< this << " UFSStoreState::doWrite");
221 assert(theFile
->canWrite());
223 _queued_write
*q
= (_queued_write
*)linklistShift(&pending_writes
);
226 debugs(79, 3, HERE
<< this << " UFSStoreState::doWrite queue is empty");
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
);
235 * Note "free_func" is memNodeWriteComplete(), which doesn't
236 * really free the memory. Instead it clears the node's
237 * write_pending flag.
239 q
->free_func((void*)q
->buf
);
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
254 debugs(79, 3, HERE
<< this << " calling theFile->write(" << q
->size
<< ")");
256 theFile
->write(new WriteRequest(q
->buf
, q
->offset
, q
->size
, q
->free_func
));
261 Fs::Ufs::UFSStoreState::readCompleted(const char *buf
, int len
, int errflag
, RefCount
<ReadRequest
> result
)
263 assert (result
.getRaw());
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
);
272 STRCB
*callback_
= read
.callback
;
276 read
.callback
= NULL
;
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.
292 if (!closing
&& cbdataReferenceValidDone(read
.callback_data
, &cbdata
)) {
293 if (len
> 0 && read_buf
!= buf
)
294 memcpy(read_buf
, buf
, len
);
296 callback_(cbdata
, read_buf
, len
, this);
299 if (flags
.try_closing
|| (theFile
!= NULL
&& theFile
->error()) )
304 Fs::Ufs::UFSStoreState::writeCompleted(int errflag
, size_t len
, RefCount
<WriteRequest
> writeRequest
)
306 debugs(79, 3, HERE
<< "dirno " << swap_dirn
<< ", fileno " <<
307 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
<<
311 * See doWrites() for why we don't update UFSStoreState::writing
317 if (theFile
->error()) {
318 debugs(79,2,HERE
<< " detected an error, will try to close");
324 * Kick any pending write/close operations alive
330 Fs::Ufs::UFSStoreState::doCloseCallback(int errflag
)
332 debugs(79, 3, "storeUfsIOCallback: errflag=" << errflag
);
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.
341 STIOCB
*theCallback
= callback
;
346 if (cbdataReferenceValidDone(callback_data
, &cbdata
) && theCallback
)
347 theCallback(cbdata
, errflag
, this);
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.
354 theFile
= NULL
; // refcounted
357 /* ============= THE REAL UFS CODE ================ */
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
)
361 swap_filen
= anEntry
->swap_filen
;
362 swap_dirn
= SD
->index
;
364 callback
= callback_
;
365 callback_data
= cbdataReference(callback_data_
);
367 flags
.write_draining
= false;
368 flags
.try_closing
= false;
371 Fs::Ufs::UFSStoreState::~UFSStoreState()
373 assert(pending_reads
== NULL
);
374 assert(pending_writes
== NULL
);
378 Fs::Ufs::UFSStoreState::freePending()
382 while ((qr
= (_queued_read
*)linklistShift(&pending_reads
))) {
383 cbdataReferenceDone(qr
->callback_data
);
387 debugs(79,3,HERE
<< "UFSStoreState::freePending: freed pending reads");
391 while ((qw
= (_queued_write
*)linklistShift(&pending_writes
))) {
393 qw
->free_func(const_cast<char *>(qw
->buf
));
397 debugs(79,3,HERE
<< "UFSStoreState::freePending: freed pending writes");
401 Fs::Ufs::UFSStoreState::kickReadQueue()
403 _queued_read
*q
= (_queued_read
*)linklistShift(&pending_reads
);
408 debugs(79, 3, "UFSStoreState::kickReadQueue: reading queued request of " << q
->size
<< " bytes");
412 if (cbdataReferenceValidDone(q
->callback_data
, &cbdata
)) {
413 read_(q
->buf
, q
->size
, q
->offset
, q
->callback
, cbdata
);
415 debugs(79, 2, "UFSStoreState::kickReadQueue: this: " << this << " cbdataReferenceValidDone returned false." << " closing: " << closing
<< " flags.try_closing: " << flags
.try_closing
);
426 Fs::Ufs::UFSStoreState::queueRead(char *buf
, size_t size
, off_t aOffset
, STRCB
*callback_
, void *callback_data_
)
428 debugs(79, 3, "UFSStoreState::queueRead: queueing read");
430 assert (pending_reads
== NULL
);
431 _queued_read
*q
= new _queued_read
;
435 q
->callback
= callback_
;
436 q
->callback_data
= cbdataReference(callback_data_
);
437 linklistPush(&pending_reads
, q
);
442 * drainWriteQueue() is a loop around doWrite().
445 Fs::Ufs::UFSStoreState::drainWriteQueue()
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() ->
456 if (flags
.write_draining
)
459 if (!theFile
->canWrite())
462 flags
.write_draining
= true;
464 while (pending_writes
!= NULL
) {
468 flags
.write_draining
= false;
470 if (flags
.try_closing
)
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.
482 Fs::Ufs::UFSStoreState::tryClosing()
484 debugs(79,3,HERE
<< this << " tryClosing()" <<
485 " closing = " << closing
<<
486 " flags.try_closing = " << flags
.try_closing
<<
487 " ioInProgress = " << theFile
->ioInProgress());
489 if (theFile
->ioInProgress()) {
490 debugs(79, 3, HERE
<< this <<
491 " won't close since ioInProgress is true, bailing");
492 flags
.try_closing
= true;
497 flags
.try_closing
= false;
502 Fs::Ufs::UFSStoreState::queueWrite(char const *buf
, size_t size
, off_t aOffset
, FREE
* free_func
)
504 debugs(79, 3, HERE
<< this << " UFSStoreState::queueWrite: queueing write of size " << size
);
507 q
= new _queued_write
;
511 q
->free_func
= free_func
;
512 linklistPush(&pending_writes
, q
);