]> git.ipfire.org Git - thirdparty/squid.git/blame - src/fs/ufs/store_io_ufs.cc
Cleanup: zap CVS Id tags
[thirdparty/squid.git] / src / fs / ufs / store_io_ufs.cc
CommitLineData
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
36#include "squid.h"
e6ccf245 37#include "Store.h"
4d6d905e 38#include "ufscommon.h"
b9ae18aa 39#include "Generic.h"
40#include "DiskIO/DiskFile.h"
41#include "DiskIO/DiskIOStrategy.h"
42#include "DiskIO/ReadRequest.h"
43#include "DiskIO/WriteRequest.h"
cd748f27 44
d3b3ab85 45#include "SwapDir.h"
cd748f27 46
d3b3ab85 47bool
b9ae18aa 48UFSStrategy::shedLoad()
d3b3ab85 49{
b9ae18aa 50 return io->shedLoad();
d3b3ab85 51}
62e76326 52
59b2d47f 53int
b9ae18aa 54UFSStrategy::load()
59b2d47f 55{
b9ae18aa 56 return io->load();
57}
58
59UFSStrategy::UFSStrategy (DiskIOStrategy *anIO) : io(anIO)
60{}
61
62UFSStrategy::~UFSStrategy ()
63{
64 delete io;
59b2d47f 65}
66
d3b3ab85 67StoreIOState::Pointer
4fcc8876 68UFSStrategy::createState(SwapDir *SD, StoreEntry *e, StoreIOState::STIOCB * callback, void *callback_data) const
d3b3ab85 69{
59b2d47f 70 return new UFSStoreState (SD, e, callback, callback_data);
d3b3ab85 71}
72
62e76326 73DiskFile::Pointer
b9ae18aa 74UFSStrategy::newFile (char const *path)
d3b3ab85 75{
b9ae18aa 76 return io->newFile(path);
d3b3ab85 77}
cd748f27 78
b9ae18aa 79
59b2d47f 80void
b9ae18aa 81UFSStrategy::unlinkFile(char const *path)
59b2d47f 82{
b9ae18aa 83 io->unlinkFile(path);
59b2d47f 84}
85
86CBDATA_CLASS_INIT(UFSStoreState);
72711e31 87
d3b3ab85 88void *
59b2d47f 89UFSStoreState::operator new (size_t)
d3b3ab85 90{
59b2d47f 91 CBDATA_INIT_TYPE(UFSStoreState);
92 return cbdataAlloc(UFSStoreState);
d3b3ab85 93}
62e76326 94
d3b3ab85 95void
59b2d47f 96UFSStoreState::operator delete (void *address)
d3b3ab85 97{
d3b3ab85 98 cbdataFree(address);
d3b3ab85 99}
cd748f27 100
cd748f27 101void
59b2d47f 102UFSStoreState::ioCompletedNotification()
cd748f27 103{
d3b3ab85 104 if (opening) {
62e76326 105 opening = false;
bf8fe701 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());
110
59b2d47f 111 assert (FILE_MODE(mode) == O_RDONLY);
112 openDone();
113
62e76326 114 return;
d3b3ab85 115 }
62e76326 116
d3b3ab85 117 if (creating) {
62e76326 118 creating = false;
bf8fe701 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());
123
59b2d47f 124 openDone();
125
62e76326 126 return;
d3b3ab85 127 }
62e76326 128
59b2d47f 129 assert (!(closing ||opening));
bf8fe701 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());
133
59b2d47f 134 /* Ok, notification past open means an error has occured */
135 assert (theFile->error());
1e0d7905 136 tryClosing();
d3b3ab85 137}
cd748f27 138
d3b3ab85 139void
59b2d47f 140UFSStoreState::openDone()
d3b3ab85 141{
1e0d7905 142 if (closing)
143 debugs(0,0,HERE << "already closing in openDone()!?");
144
59b2d47f 145 if (theFile->error()) {
1e0d7905 146 tryClosing();
59b2d47f 147 return;
148 }
149
150 if (FILE_MODE(mode) == O_WRONLY) {
1e0d7905 151 drainWriteQueue();
152
59b2d47f 153 } else if ((FILE_MODE(mode) == O_RDONLY) && !closing) {
154 if (kickReadQueue())
155 return;
156 }
157
1e0d7905 158 if (flags.try_closing)
159 tryClosing();
59b2d47f 160
bf8fe701 161 debugs(79, 3, "UFSStoreState::openDone: exiting");
d3b3ab85 162}
163
164void
59b2d47f 165UFSStoreState::closeCompleted()
d3b3ab85 166{
59b2d47f 167 assert (closing);
bf8fe701 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 <<
171 theFile->error());
62e76326 172
1e0d7905 173 if (theFile->error()) {
174 debugs(79,3,HERE<< "theFile->error() ret " << theFile->error());
3e2cded3 175 doCloseCallback(DISK_ERROR);
1e0d7905 176 } else {
3e2cded3 177 doCloseCallback(DISK_OK);
1e0d7905 178 }
59b2d47f 179
180 closing = false;
181}
182
1e0d7905 183/*
184 * DPW 2006-05-24
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.
191 */
59b2d47f 192void
193UFSStoreState::close()
194{
bf8fe701 195 debugs(79, 3, "UFSStoreState::close: dirno " << swap_dirn << ", fileno "<<
196 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
1e0d7905 197 tryClosing();
d3b3ab85 198}
199
200void
201UFSStoreState::read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
202{
203 assert(read.callback == NULL);
204 assert(read.callback_data == NULL);
205 assert(!reading);
206 assert(!closing);
207 assert (callback);
62e76326 208
d3b3ab85 209 if (!theFile->canRead()) {
bf8fe701 210 debugs(79, 3, "UFSStoreState::read_: queueing read because theFile can't read");
62e76326 211 queueRead (buf, size, offset, callback, callback_data);
212 return;
cd748f27 213 }
62e76326 214
d3b3ab85 215 read.callback = callback;
216 read.callback_data = cbdataReference(callback_data);
bf8fe701 217 debugs(79, 3, "UFSStoreState::read_: dirno " << swap_dirn << ", fileno "<<
218 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
d3b3ab85 219 offset_ = offset;
220 read_buf = buf;
221 reading = true;
b9ae18aa 222 theFile->read(new ReadRequest(buf,offset,size));
d3b3ab85 223}
62e76326 224
cd748f27 225
1e0d7905 226/*
227 * DPW 2006-05-24
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.
233 */
cd748f27 234void
528b2c61 235UFSStoreState::write(char const *buf, size_t size, off_t offset, FREE * free_func)
d3b3ab85 236{
bf8fe701 237 debugs(79, 3, "UFSStoreState::write: dirn " << swap_dirn << ", fileno "<<
238 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
62e76326 239
1e0d7905 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);
244 return;
245 }
246
247 queueWrite(buf, size, offset, free_func);
248 drainWriteQueue();
249}
250
251
252/*
253 * DPW 2006-05-24
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().
257 */
258void
259UFSStoreState::doWrite()
260{
261 debugs(79, 3, HERE << this << " UFSStoreState::doWrite");
262
263 assert(theFile->canWrite());
264
265 _queued_write *q = (_queued_write *)linklistShift(&pending_writes);
266
267 if (q == NULL) {
268 debugs(79, 3, HERE << this << " UFSStoreState::doWrite queue is empty");
269 return;
270 }
271
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);
275 /*
276 * DPW 2006-05-24
277 * Note "free_func" is memNodeWriteComplete(), which doesn't
278 * really free the memory. Instead it clears the node's
279 * write_pending flag.
280 */
281 q->free_func((void*)q->buf);
9db2e213 282 delete q;
62e76326 283 return;
d3b3ab85 284 }
62e76326 285
1e0d7905 286 /*
287 * DPW 2006-05-24
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
294 * all.
295 */
296 debugs(79, 3, HERE << this << " calling theFile->write(" << q->size << ")");
297
298 theFile->write(new WriteRequest(q->buf, q->offset, q->size, q->free_func));
9db2e213 299 delete q;
d3b3ab85 300}
301
302void
b9ae18aa 303UFSStoreState::readCompleted(const char *buf, int len, int errflag, RefCount<ReadRequest> result)
d3b3ab85 304{
b9ae18aa 305 assert (result.getRaw());
d3b3ab85 306 reading = false;
bf8fe701 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);
62e76326 310
d3b3ab85 311 if (len > 0)
62e76326 312 offset_ += len;
313
d3b3ab85 314 STRCB *callback = read.callback;
62e76326 315
d3b3ab85 316 assert(callback);
62e76326 317
d3b3ab85 318 read.callback = NULL;
62e76326 319
d3b3ab85 320 void *cbdata;
62e76326 321
59b2d47f 322 /* A note:
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:
1e0d7905 330 * closing is set when theFile->close() has been called, and close only triggers
59b2d47f 331 * when no io's are pending.
332 * writeCompleted likewise.
333 */
d3b3ab85 334 if (!closing && cbdataReferenceValidDone(read.callback_data, &cbdata)) {
62e76326 335 if (len > 0 && read_buf != buf)
336 memcpy(read_buf, buf, len);
337
e5de8b13 338 callback(cbdata, read_buf, len, this);
1e0d7905 339 }
340
8bc0c94b 341 if (flags.try_closing || (theFile != NULL && theFile->error()) )
1e0d7905 342 tryClosing();
d3b3ab85 343}
344
345void
b9ae18aa 346UFSStoreState::writeCompleted(int errflag, size_t len, RefCount<WriteRequest> writeRequest)
d3b3ab85 347{
26ac0430
AJ
348 debugs(79, 3, "UFSStoreState::writeCompleted: dirno " << swap_dirn << ", fileno " <<
349 std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen <<
350 ", len " << len );
1e0d7905 351 /*
352 * DPW 2006-05-24
353 * See doWrites() for why we don't update UFSStoreState::writing
354 * here anymore.
355 */
62e76326 356
59b2d47f 357 offset_ += len;
358
359 if (theFile->error()) {
1e0d7905 360 debugs(79,2,HERE << "UFSStoreState::writeCompleted" <<
361 " detected an error, will try to close");
362 tryClosing();
59b2d47f 363 }
bdf5b250 364
365 /*
366 * DPW 2007-04-12
367 * I'm seeing disk files remain open under vanilla UFS storage
368 * because storeClose() gets called before the last write is
369 * complete. I guess we have to check for the try_closing
370 * flag here.
371 */
372 if (flags.try_closing) {
26ac0430
AJ
373 debugs(72, 2, HERE << "UFSStoreState::writeCompleted" <<
374 " flags.try_closing is set");
375 tryClosing();
bdf5b250 376 }
d3b3ab85 377}
378
379void
3e2cded3 380UFSStoreState::doCloseCallback(int errflag)
cd748f27 381{
bf8fe701 382 debugs(79, 3, "storeUfsIOCallback: errflag=" << errflag);
1e0d7905 383 /*
384 * DPW 2006-05-24
385 * When we signal the higher layer with this callback, it might unlock
386 * the StoreEntry and its associated data. We must "free" any queued
387 * I/Os (especially writes) now, otherwise the StoreEntry's mem_node's
388 * will have their write_pending flag set, and we'll get an assertion.
389 */
390 freePending();
59b2d47f 391 STIOCB *theCallback = callback;
d3b3ab85 392 callback = NULL;
d3b3ab85 393
59b2d47f 394 void *cbdata;
d3b3ab85 395
59b2d47f 396 if (cbdataReferenceValidDone(callback_data, &cbdata) && theCallback)
e5de8b13 397 theCallback(cbdata, errflag, this);
7fbb6b8f 398
1e0d7905 399 /*
400 * We are finished with theFile since the lower layer signalled
401 * us that the file has been closed. This must be the last line,
402 * as theFile may be the only object holding us in memory.
7fbb6b8f 403 */
1e0d7905 404 theFile = NULL; // refcounted
59b2d47f 405}
d3b3ab85 406
407/* ============= THE REAL UFS CODE ================ */
408
59b2d47f 409UFSStoreState::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)
410{
411 swap_filen = anEntry->swap_filen;
412 swap_dirn = SD->index;
413 mode = O_BINARY;
414 callback = callback_;
415 callback_data = cbdataReference(callback_data_);
416 e = anEntry;
1e0d7905 417 flags.write_draining = false;
418 flags.try_closing = false;
59b2d47f 419}
62e76326 420
d3b3ab85 421UFSStoreState::~UFSStoreState()
1e0d7905 422{
423 assert(pending_reads == NULL);
424 assert(pending_writes == NULL);
425}
426
427void
428UFSStoreState::freePending()
d3b3ab85 429{
430 _queued_read *qr;
62e76326 431
d3b3ab85 432 while ((qr = (_queued_read *)linklistShift(&pending_reads))) {
62e76326 433 cbdataReferenceDone(qr->callback_data);
434 delete qr;
d3b3ab85 435 }
436
1e0d7905 437 debugs(79,3,HERE << "UFSStoreState::freePending: freed pending reads");
438
5aeabf95 439 _queued_write *qw;
62e76326 440
5aeabf95 441 while ((qw = (_queued_write *)linklistShift(&pending_writes))) {
62e76326 442 if (qw->free_func)
443 qw->free_func(const_cast<char *>(qw->buf));
444 delete qw;
d3b3ab85 445 }
1e0d7905 446
447 debugs(79,3,HERE << "UFSStoreState::freePending: freed pending writes");
d3b3ab85 448}
449
450bool
451UFSStoreState::kickReadQueue()
452{
453 _queued_read *q = (_queued_read *)linklistShift(&pending_reads);
62e76326 454
d3b3ab85 455 if (NULL == q)
62e76326 456 return false;
457
4a7a3d56 458 debugs(79, 3, "UFSStoreState::kickReadQueue: reading queued request of " << q->size << " bytes");
62e76326 459
d3b3ab85 460 void *cbdata;
62e76326 461
d3b3ab85 462 if (cbdataReferenceValidDone(q->callback_data, &cbdata))
62e76326 463 read_(q->buf, q->size, q->offset, q->callback, cbdata);
464
d3b3ab85 465 delete q;
62e76326 466
d3b3ab85 467 return true;
468}
469
d3b3ab85 470void
471UFSStoreState::queueRead(char *buf, size_t size, off_t offset, STRCB *callback, void *callback_data)
472{
bf8fe701 473 debugs(79, 3, "UFSStoreState::queueRead: queueing read");
d3b3ab85 474 assert(opening);
475 assert (pending_reads == NULL);
476 _queued_read *q = new _queued_read;
477 q->buf = buf;
478 q->size = size;
479 q->offset = offset;
480 q->callback = callback;
481 q->callback_data = cbdataReference(callback_data);
482 linklistPush(&pending_reads, q);
483}
484
1e0d7905 485/*
486 * DPW 2006-05-24
487 * drainWriteQueue() is a loop around doWrite().
488 */
489void
490UFSStoreState::drainWriteQueue()
cd748f27 491{
2eaddcc2 492 /*
493 * DPW 2007-04-12
494 * We might find that flags.write_draining is already set
495 * because schemes like diskd can process I/O acks
496 * before sending another I/O request. e.g. the following
497 * sequence of events: open request -> write request ->
498 * drainWriteQueue() -> queue full -> callbacks -> openDone() ->
499 * drainWriteQueue().
500 */
501 if (flags.write_draining)
26ac0430 502 return;
62e76326 503
1e0d7905 504 if (!theFile->canWrite())
505 return;
62e76326 506
1e0d7905 507 flags.write_draining = true;
62e76326 508
1e0d7905 509 while (pending_writes != NULL) {
510 doWrite();
511 }
512
513 flags.write_draining = false;
514
515 if (flags.try_closing)
516 tryClosing();
517}
518
519/*
520 * DPW 2006-05-24
521 * This blows. DiskThreadsDiskFile::close() won't actually do the close
522 * if ioInProgress() is true. So we have to check it here. Maybe someday
523 * DiskThreadsDiskFile::close() will be modified to have a return value,
524 * or will remember to do the close for us.
525 */
526void
527UFSStoreState::tryClosing()
528{
529 debugs(79,3,HERE << this << " tryClosing()" <<
530 " closing = " << closing <<
531 " flags.try_closing = " << flags.try_closing <<
532 " ioInProgress = " << theFile->ioInProgress());
533
534 if (theFile->ioInProgress()) {
26ac0430
AJ
535 debugs(79, 3, HERE << this <<
536 " won't close since ioInProgress is true, bailing");
1e0d7905 537 flags.try_closing = true;
538 return;
539 }
540
541 closing = true;
542 flags.try_closing = false;
543 theFile->close();
d3b3ab85 544}
545
546void
528b2c61 547UFSStoreState::queueWrite(char const *buf, size_t size, off_t offset, FREE * free_func)
d3b3ab85 548{
1e0d7905 549 debugs(79, 3, HERE << this << " UFSStoreState::queueWrite: queueing write of size " << size);
62e76326 550
5aeabf95 551 _queued_write *q;
d3b3ab85 552 q = new _queued_write;
553 q->buf = buf;
554 q->size = size;
555 q->offset = offset;
556 q->free_func = free_func;
557 linklistPush(&pending_writes, q);
558}
559
560StoreIOState::Pointer
4fcc8876 561UFSStrategy::open(SwapDir * SD, StoreEntry * e, StoreIOState::STFNCB * file_callback,
562 StoreIOState::STIOCB * callback, void *callback_data)
d3b3ab85 563{
59b2d47f 564 assert (((UFSSwapDir *)SD)->IO == this);
bf8fe701 565 debugs(79, 3, "UFSStrategy::open: fileno "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << e->swap_filen);
62e76326 566
d3b3ab85 567 /* to consider: make createstate a private UFSStrategy call */
568 StoreIOState::Pointer sio = createState (SD, e, callback, callback_data);
62e76326 569
d3b3ab85 570 sio->mode |= O_RDONLY;
62e76326 571
d3b3ab85 572 UFSStoreState *state = dynamic_cast <UFSStoreState *>(sio.getRaw());
62e76326 573
d3b3ab85 574 assert (state);
62e76326 575
d3b3ab85 576 char *path = ((UFSSwapDir *)SD)->fullPath(e->swap_filen, NULL);
577
578 DiskFile::Pointer myFile = newFile (path);
62e76326 579
b9ae18aa 580 if (myFile.getRaw() == NULL)
581 return NULL;
582
d3b3ab85 583 state->theFile = myFile;
62e76326 584
d3b3ab85 585 state->opening = true;
62e76326 586
d3b3ab85 587 myFile->open (sio->mode, 0644, state);
62e76326 588
d3b3ab85 589 if (myFile->error())
62e76326 590 return NULL;
591
d3b3ab85 592 return sio;
593}
594
595StoreIOState::Pointer
4fcc8876 596UFSStrategy::create(SwapDir * SD, StoreEntry * e, StoreIOState::STFNCB * file_callback,
597 StoreIOState::STIOCB * callback, void *callback_data)
d3b3ab85 598{
59b2d47f 599 assert (((UFSSwapDir *)SD)->IO == this);
d3b3ab85 600 /* Allocate a number */
601 sfileno filn = ((UFSSwapDir *)SD)->mapBitAllocate();
bf8fe701 602 debugs(79, 3, "UFSStrategy::create: fileno "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << filn);
62e76326 603
d3b3ab85 604 /* Shouldn't we handle a 'bitmap full' error here? */
605
606 StoreIOState::Pointer sio = createState (SD, e, callback, callback_data);
607
608 sio->mode |= O_WRONLY | O_CREAT | O_TRUNC;
62e76326 609
d3b3ab85 610 sio->swap_filen = filn;
611
612 UFSStoreState *state = dynamic_cast <UFSStoreState *>(sio.getRaw());
62e76326 613
d3b3ab85 614 assert (state);
62e76326 615
d3b3ab85 616 char *path = ((UFSSwapDir *)SD)->fullPath(filn, NULL);
62e76326 617
d3b3ab85 618 DiskFile::Pointer myFile = newFile (path);
62e76326 619
b9ae18aa 620 if (myFile.getRaw() == NULL) {
621 ((UFSSwapDir *)SD)->mapBitReset (filn);
622 return NULL;
623 }
624
d3b3ab85 625 state->theFile = myFile;
62e76326 626
d3b3ab85 627 state->creating = true;
62e76326 628
d3b3ab85 629 myFile->create (state->mode, 0644, state);
62e76326 630
d3b3ab85 631 if (myFile->error()) {
62e76326 632 ((UFSSwapDir *)SD)->mapBitReset (filn);
633 return NULL;
d3b3ab85 634 }
62e76326 635
d3b3ab85 636 /* now insert into the replacement policy */
637 ((UFSSwapDir *)SD)->replacementAdd(e);
62e76326 638
d3b3ab85 639 return sio;
cd748f27 640}
59b2d47f 641
b9ae18aa 642int
643UFSStrategy::callback()
59b2d47f 644{
b9ae18aa 645 return io->callback();
59b2d47f 646}
647
648void
b9ae18aa 649UFSStrategy::init()
650{
651 io->init();
652}
59b2d47f 653
654void
b9ae18aa 655UFSStrategy::sync()
656{
657 io->sync();
658}
59b2d47f 659
b9ae18aa 660void
661UFSStrategy::statfs(StoreEntry & sentry)const
59b2d47f 662{
b9ae18aa 663 io->statfs(sentry);
59b2d47f 664}
665