]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/fs/ufs/UFSStoreState.cc
1f31de2d89e1cd28eef63152181b0f064d8a9621
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 79 Storage Manager UFS Interface */
12 #include "DiskIO/DiskFile.h"
13 #include "DiskIO/DiskIOStrategy.h"
14 #include "DiskIO/ReadRequest.h"
15 #include "DiskIO/WriteRequest.h"
17 #include "SquidConfig.h"
19 #include "store/Disk.h"
20 #include "UFSStoreState.h"
21 #include "UFSStrategy.h"
23 CBDATA_NAMESPACED_CLASS_INIT(Fs::Ufs
,UFSStoreState
);
26 Fs::Ufs::UFSStoreState::ioCompletedNotification()
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());
35 assert (FILE_MODE(mode
) == O_RDONLY
);
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());
53 assert (!(closing
||opening
));
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());
58 /* Ok, notification past open means an error has occured */
59 assert (theFile
->error());
64 Fs::Ufs::UFSStoreState::openDone()
67 debugs(0, DBG_CRITICAL
, HERE
<< "already closing in openDone()!?");
69 if (theFile
->error()) {
74 if (FILE_MODE(mode
) == O_WRONLY
) {
77 } else if ((FILE_MODE(mode
) == O_RDONLY
) && !closing
) {
82 if (flags
.try_closing
)
85 debugs(79, 3, "UFSStoreState::openDone: exiting");
89 Fs::Ufs::UFSStoreState::closeCompleted()
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
<<
97 if (theFile
->error()) {
98 debugs(79,3,HERE
<< "theFile->error() ret " << theFile
->error());
99 doCloseCallback(DISK_ERROR
);
101 doCloseCallback(DISK_OK
);
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.
117 Fs::Ufs::UFSStoreState::close(int)
119 debugs(79, 3, "UFSStoreState::close: dirno " << swap_dirn
<< ", fileno "<<
120 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
);
121 tryClosing(); // UFS does not distinguish different closure types
125 Fs::Ufs::UFSStoreState::read_(char *buf
, size_t size
, off_t aOffset
, STRCB
* aCallback
, void *aCallbackData
)
127 assert(read
.callback
== NULL
);
128 assert(read
.callback_data
== NULL
);
133 if (!theFile
->canRead()) {
134 debugs(79, 3, "queueing read because theFile can't read");
136 pending_reads
.emplace(buf
, size
, aOffset
, aCallback
, aCallbackData
);
140 read
.callback
= aCallback
;
141 read
.callback_data
= cbdataReference(aCallbackData
);
142 debugs(79, 3, "UFSStoreState::read_: dirno " << swap_dirn
<< ", fileno "<<
143 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
);
147 theFile
->read(new ReadRequest(buf
,aOffset
,size
));
152 * This, the public write interface, places the write request at the end
153 * of the pending_writes queue to ensure correct ordering of writes.
154 * We could optimize things a little if there are no other pending
155 * writes and just do the write directly. But for now we'll keep the
156 * code simpler and always go through the pending_writes queue.
159 Fs::Ufs::UFSStoreState::write(char const *buf
, size_t size
, off_t aOffset
, FREE
* free_func
)
161 debugs(79, 3, "UFSStoreState::write: dirn " << swap_dirn
<< ", fileno "<<
162 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
);
164 if (theFile
->error()) {
165 debugs(79, DBG_IMPORTANT
,HERE
<< "avoid write on theFile with error");
166 debugs(79, DBG_IMPORTANT
,HERE
<< "calling free_func for " << (void*) buf
);
167 free_func((void*)buf
);
171 const Store::Disk
&dir
= *INDEXSD(swap_dirn
);
172 if (static_cast<uint64_t>(offset_
+ size
) > static_cast<uint64_t>(dir
.maxObjectSize())) {
173 debugs(79, 2, "accepted unknown-size entry grew too big: " <<
174 (offset_
+ size
) << " > " << dir
.maxObjectSize());
175 free_func((void*)buf
);
180 debugs(79, 3, (void*)this << " queueing write of size " << size
);
181 pending_writes
.emplace(buf
, size
, aOffset
, free_func
);
188 * This, the private write method, calls the lower level write for the
189 * first write request in the pending_writes queue. doWrite() is only
190 * called by drainWriteQueue().
193 Fs::Ufs::UFSStoreState::doWrite()
195 debugs(79, 3, (void*)this);
197 assert(theFile
->canWrite());
199 if (pending_writes
.empty()) {
200 debugs(79, 3, (void*)this << " write queue is empty");
204 auto &q
= pending_writes
.front();
206 if (theFile
->error()) {
207 debugs(79, DBG_IMPORTANT
, MYNAME
<< " avoid write on theFile with error");
208 pending_writes
.pop();
214 * UFSStoreState has a 'writing' flag that we used to set here,
215 * but it wasn't really used anywhere. In fact, some lower
216 * layers such as DISKD allow multiple outstanding writes, which
217 * makes the boolean writing flag meaningless. We would need
218 * a counter to keep track of writes going out and write callbacks
219 * coming in. For now let's just not use the writing flag at
222 debugs(79, 3, (void*)this << " calling theFile->write(" << q
.size
<< ")");
224 theFile
->write(new WriteRequest(q
.buf
, q
.offset
, q
.size
, q
.free_func
));
225 q
.buf
= nullptr; // prevent buf deletion on pop, its used by the above object
226 pending_writes
.pop();
230 Fs::Ufs::UFSStoreState::readCompleted(const char *buf
, int len
, int, RefCount
<ReadRequest
> result
)
232 assert (result
.getRaw());
234 debugs(79, 3, "UFSStoreState::readCompleted: dirno " << swap_dirn
<<
235 ", fileno "<< std::setfill('0') << std::hex
<< std::setw(8) <<
236 swap_filen
<< " len "<< std::setfill(' ') << std::dec
<< len
);
241 STRCB
*callback_
= read
.callback
;
245 read
.callback
= NULL
;
250 * diskd IO queues closes via the diskd queue. So close callbacks
251 * occur strictly after reads and writes.
252 * ufs doesn't queue, it simply completes, so close callbacks occur
253 * strictly after reads and writes.
254 * aufs performs closes syncronously, so close events must be managed
255 * to force strict ordering.
256 * The below does this:
257 * closing is set when theFile->close() has been called, and close only triggers
258 * when no io's are pending.
259 * writeCompleted likewise.
261 if (!closing
&& cbdataReferenceValidDone(read
.callback_data
, &cbdata
)) {
262 if (len
> 0 && read_buf
!= buf
)
263 memcpy(read_buf
, buf
, len
);
265 callback_(cbdata
, read_buf
, len
, this);
268 if (flags
.try_closing
|| (theFile
!= NULL
&& theFile
->error()) )
273 Fs::Ufs::UFSStoreState::writeCompleted(int, size_t len
, RefCount
<WriteRequest
>)
275 debugs(79, 3, HERE
<< "dirno " << swap_dirn
<< ", fileno " <<
276 std::setfill('0') << std::hex
<< std::uppercase
<< std::setw(8) << swap_filen
<<
280 * See doWrites() for why we don't update UFSStoreState::writing
286 if (theFile
->error()) {
287 debugs(79,2,HERE
<< " detected an error, will try to close");
293 * Kick any pending write/close operations alive
299 Fs::Ufs::UFSStoreState::doCloseCallback(int errflag
)
301 debugs(79, 3, "storeUfsIOCallback: errflag=" << errflag
);
304 * When we signal the higher layer with this callback, it might unlock
305 * the StoreEntry and its associated data. We must "free" any queued
306 * I/Os (especially writes) now, otherwise the StoreEntry's mem_node's
307 * will have their write_pending flag set, and we'll get an assertion.
310 STIOCB
*theCallback
= callback
;
315 if (cbdataReferenceValidDone(callback_data
, &cbdata
) && theCallback
)
316 theCallback(cbdata
, errflag
, this);
319 * We are finished with theFile since the lower layer signalled
320 * us that the file has been closed. This must be the last line,
321 * as theFile may be the only object holding us in memory.
323 theFile
= NULL
; // refcounted
326 /* ============= THE REAL UFS CODE ================ */
328 Fs::Ufs::UFSStoreState::UFSStoreState(SwapDir
* SD
, StoreEntry
* anEntry
, STIOCB
* cbIo
, void *data
) :
329 StoreIOState(NULL
, cbIo
, data
),
337 // StoreIOState inherited members
338 swap_filen
= anEntry
->swap_filen
;
339 swap_dirn
= SD
->index
;
343 flags
.write_draining
= false;
344 flags
.try_closing
= false;
347 Fs::Ufs::UFSStoreState::~UFSStoreState()
349 assert(pending_reads
.empty());
350 assert(pending_writes
.empty());
354 Fs::Ufs::UFSStoreState::freePending()
356 while (!pending_reads
.empty())
358 debugs(79, 3, "freed pending reads");
360 while (!pending_writes
.empty())
361 pending_writes
.pop();
362 debugs(79, 3, "freed pending writes");
366 Fs::Ufs::UFSStoreState::kickReadQueue()
368 if (pending_reads
.empty())
371 auto &q
= pending_reads
.front();
373 debugs(79, 3, "reading queued request of " << q
.size
<< " bytes");
377 if (cbdataReferenceValidDone(q
.callback_data
, &cbdata
)) {
378 read_(q
.buf
, q
.size
, q
.offset
, q
.callback
, cbdata
);
380 debugs(79, 2, "this=" << (void*)this << " cbdataReferenceValidDone returned false." <<
381 " closing: " << closing
<< " flags.try_closing: " << flags
.try_closing
);
385 pending_reads
.pop(); // erase the front object
391 * drainWriteQueue() is a loop around doWrite().
394 Fs::Ufs::UFSStoreState::drainWriteQueue()
398 * We might find that flags.write_draining is already set
399 * because schemes like diskd can process I/O acks
400 * before sending another I/O request. e.g. the following
401 * sequence of events: open request -> write request ->
402 * drainWriteQueue() -> queue full -> callbacks -> openDone() ->
405 if (flags
.write_draining
)
408 if (!theFile
|| !theFile
->canWrite())
411 flags
.write_draining
= true;
413 while (!pending_writes
.empty())
416 flags
.write_draining
= false;
418 if (flags
.try_closing
)
424 * This blows. DiskThreadsDiskFile::close() won't actually do the close
425 * if ioInProgress() is true. So we have to check it here. Maybe someday
426 * DiskThreadsDiskFile::close() will be modified to have a return value,
427 * or will remember to do the close for us.
430 Fs::Ufs::UFSStoreState::tryClosing()
432 debugs(79,3,HERE
<< this << " tryClosing()" <<
433 " closing = " << closing
<<
434 " flags.try_closing = " << flags
.try_closing
<<
435 " ioInProgress = " << theFile
->ioInProgress());
437 if (theFile
->ioInProgress()) {
438 debugs(79, 3, HERE
<< this <<
439 " won't close since ioInProgress is true, bailing");
440 flags
.try_closing
= true;
445 flags
.try_closing
= false;