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