From 0c05abb30406dc860034490de8d8eaafc10aa836 Mon Sep 17 00:00:00 2001 From: janwas Date: Thu, 8 Jul 2004 14:30:35 +0000 Subject: [PATCH] fixes for write code and new uncached_write routine (bypass cache, no file padding problem) This was SVN commit r654. --- source/lib/res/file.cpp | 109 +++++++++++++++++++++++----------------- source/lib/res/file.h | 2 + 2 files changed, 64 insertions(+), 47 deletions(-) diff --git a/source/lib/res/file.cpp b/source/lib/res/file.cpp index 6cec15599b..f572676231 100755 --- a/source/lib/res/file.cpp +++ b/source/lib/res/file.cpp @@ -513,31 +513,25 @@ static int ll_start_io(File* const f, const off_t ofs, size_t size, void* const { CHECK_FILE(f); - if(size == 0) - { - debug_warn("ll_start_io: size = 0 - why?"); - return ERR_INVALID_PARAM; - } + // sanity checks (caller should have taken care of this) + // .. size + assert(size != 0 && "ll_start_io: size = 0 - why?"); + // .. ofs before EOF + if(!(f->flags & FILE_WRITE)) + assert(ofs < f->size); + // .. alignment + if(ofs % 4096 != 0 || (uintptr_t)p % 4096 != 0) + debug_out("ll_start_io: p=%p or ofs=%lu is unaligned", p, ofs); const int op = (f->flags & FILE_WRITE)? LIO_WRITE : LIO_READ; - // cut off at EOF. - // avoid min() due to type conversion warnings. - const off_t bytes_left = f->size - ofs; - if(bytes_left < 0) - return ERR_EOF; - if((off_t)size > bytes_left) - size = (size_t)bytes_left; - // guaranteed to fit, since size was > bytes_left - - aiocb* cb = &lcb->cb; - // send off async read/write request + aiocb* cb = &lcb->cb; cb->aio_lio_opcode = op; cb->aio_buf = p; cb->aio_fildes = f->fd; - cb->aio_offset = (off_t)ofs; - cb->aio_nbytes = (size_t)size; + cb->aio_offset = ofs; + cb->aio_nbytes = size; return lio_listio(LIO_NOWAIT, &cb, 1, (struct sigevent*)0); // this just issues the I/O - doesn't wait until complete. } @@ -555,7 +549,7 @@ static ssize_t ll_wait_io(ll_cb* const lcb, void*& p) // posix has aio_buf as volatile void, and gcc doesn't like to cast it // implicitly - p = (void *)cb->aio_buf; + p = (void*)cb->aio_buf; // return how much was actually transferred, // or -1 if the transfer failed. @@ -901,10 +895,13 @@ static Handle io_find(const u64 block_id) } + + /////////////////////////////////////////////////////////////////////////////// + // rationale for extra alignment / copy layer, even though aio takes care of it: // aio would pad to its minimum read alignment, copy over, and be done; // in our case, if something is unaligned, a request for the remainder of the @@ -920,6 +917,8 @@ Handle file_start_io(File* const f, const off_t user_ofs, size_t user_size, void CHECK_FILE(f); + const bool is_write = (f->flags & FILE_WRITE) != 0; + if(user_size == 0) { debug_warn("file_start_io: user_size = 0 - why?"); @@ -927,13 +926,16 @@ Handle file_start_io(File* const f, const off_t user_ofs, size_t user_size, void } // cut off at EOF. - // avoid min() due to type conversion warnings. - const off_t bytes_left = f->size - user_ofs; - if(bytes_left < 0) - return ERR_EOF; - if((off_t)user_size > bytes_left) - user_size = (size_t)bytes_left; - // guaranteed to fit, since size was > bytes_left + if(!is_write) + { + // avoid min() due to type conversion warnings. + const off_t bytes_left = f->size - user_ofs; + if(bytes_left < 0) + return ERR_EOF; + if((off_t)user_size > bytes_left) + user_size = (size_t)bytes_left; + // guaranteed to fit, since size was > bytes_left + } u64 block_id = block_make_id(f->fn_hash, user_ofs); // reset to 0 if transferring more than 1 block. @@ -983,8 +985,11 @@ debug_out("file_start_io: cached! block # = %d\n", block_id & 0xffffffff); void* buf = 0; void* our_buf = 0; - if(user_p && !padding) + // can use the caller's buffer + if(user_p && !padding && user_size == size) buf = user_p; + // it's unaligned or too small (ll_io wants to read a whole block) - + // we have to allocate an align buffer else { if(size == BLOCK_SIZE) @@ -992,7 +997,7 @@ debug_out("file_start_io: cached! block # = %d\n", block_id & 0xffffffff); // transferring more than one block - doesn't go through cache! else { - our_buf = mem_alloc(size, BLOCK_SIZE); + our_buf = mem_alloc(size, BLOCK_SIZE, MEM_ZERO); block_id = 0; } if(!our_buf) @@ -1001,6 +1006,10 @@ debug_out("file_start_io: cached! block # = %d\n", block_id & 0xffffffff); goto fail; } + // have to copy over our data into align buffer + if(is_write) + memcpy(our_buf, user_p, user_size); + buf = our_buf; } @@ -1090,6 +1099,11 @@ int file_discard_io(Handle& hio) +/////////////////////////////////////////////////////////////////////////////// + + + + // transfer modes: // *p != 0: *p is the source/destination address for the transfer. // (FILE_MEM_READONLY?) @@ -1112,26 +1126,10 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); CHECK_FILE(f); - const bool is_write = (f->flags == FILE_WRITE); + const bool is_write = (f->flags & FILE_WRITE) != 0; - // - // transfer parameters - // - - // reading: make sure we don't go beyond EOF - if(!is_write) - { - // cut off at EOF. - // avoid min() due to type conversion warnings. - off_t bytes_left = f->size - raw_ofs; - if(bytes_left < 0) - return ERR_EOF; - if((off_t)raw_size > bytes_left) - raw_size = (size_t)bytes_left; - // guaranteed to fit, since size was > bytes_left - } - // writing: make sure buffer is valid - else + // sanity checks. + if(is_write) { // temp buffer OR supposed to be allocated here: invalid if(!p || !*p) @@ -1140,6 +1138,12 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); return ERR_INVALID_PARAM; } } + // note: file_start_io is responsible for truncating at EOF. + + + // + // transfer parameters + // const size_t misalign = raw_ofs % BLOCK_SIZE; @@ -1320,6 +1324,17 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); } +int file_uncached_io(File* f, size_t size, void* p) +{ + CHECK_FILE(f); + + if(f->flags & FILE_WRITE) + return write(f->fd, p, size); + else + return read(f->fd, p, size); +} + + /////////////////////////////////////////////////////////////////////////////// // // memory mapping diff --git a/source/lib/res/file.h b/source/lib/res/file.h index edc566515d..cf0ddaa100 100755 --- a/source/lib/res/file.h +++ b/source/lib/res/file.h @@ -143,5 +143,7 @@ typedef ssize_t(*FILE_IO_CB)(uintptr_t ctx, void* p, size_t size); extern ssize_t file_io(File* f, off_t ofs, size_t size, void** p, FILE_IO_CB cb = 0, uintptr_t ctx = 0); +extern int file_uncached_io(File* f, size_t size, void* p); + #endif // #ifndef FILE_H