diff --git a/headers/os/drivers/fs_interface.h b/headers/os/drivers/fs_interface.h index 26a2ccc777..d667a8309b 100644 --- a/headers/os/drivers/fs_interface.h +++ b/headers/os/drivers/fs_interface.h @@ -27,8 +27,10 @@ typedef void *fs_cookie; typedef void *fs_vnode; /* additional flags passed to write_stat() (see NodeMonitor.h for the others) */ - // NOTE: Changing the constants here or in NodeMonitor.h will break - // src/kits/storage/LibBeAdapter.cpp:_kern_write_stat(). +// NOTE: Changing the constants here or in NodeMonitor.h will break +// src/kits/storage/LibBeAdapter.cpp:_kern_write_stat(). +#define B_STAT_SIZE_INSECURE 0x2000 + // TODO: this should be faded out once BFS supports sparse files /* passed to write_fs_info() */ #define FS_WRITE_FSINFO_NAME 0x0001 diff --git a/headers/private/fs_shell/fssh_api_wrapper.h b/headers/private/fs_shell/fssh_api_wrapper.h index ffb230cb4f..26fdefdbd2 100644 --- a/headers/private/fs_shell/fssh_api_wrapper.h +++ b/headers/private/fs_shell/fssh_api_wrapper.h @@ -874,6 +874,9 @@ #define fs_cookie fssh_fs_cookie #define fs_vnode fssh_fs_vnode +/* additional flags passed to write_stat() */ +#define B_STAT_SIZE_INSECURE FSSH_B_STAT_SIZE_INSECURE + /* passed to write_fs_info() */ #define FS_WRITE_FSINFO_NAME FSSH_FS_WRITE_FSINFO_NAME diff --git a/headers/private/fs_shell/fssh_fs_interface.h b/headers/private/fs_shell/fssh_fs_interface.h index 4c43c22eb1..b08aac7fee 100644 --- a/headers/private/fs_shell/fssh_fs_interface.h +++ b/headers/private/fs_shell/fssh_fs_interface.h @@ -29,6 +29,7 @@ typedef void *fssh_fs_cookie; typedef void *fssh_fs_vnode; /* additional flags passed to write_stat() */ +#define FSSH_B_STAT_SIZE_INSECURE 0x2000 /* passed to write_fs_info() */ #define FSSH_FS_WRITE_FSINFO_NAME 0x0001 diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index dc14ea56cb..2db3a1869f 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -176,7 +176,7 @@ InodeAllocator::~InodeAllocator() } -status_t +status_t InodeAllocator::New(block_run *parentRun, mode_t mode, block_run &run, Inode **_inode) { @@ -273,7 +273,7 @@ InodeAllocator::_TransactionListener(int32 id, int32 event, void *_inode) // #pragma mark - -status_t +status_t bfs_inode::InitCheck(Volume *volume) { if (Magic1() != INODE_MAGIC1 @@ -407,7 +407,7 @@ Inode::InitCheck(bool checkNode) } if (IsContainer()) { - // inodes that have a + // inodes that have a B+tree if (fTree == NULL) RETURN_ERROR(B_NO_MEMORY); @@ -715,7 +715,7 @@ Inode::_AddSmallData(Transaction &transaction, NodeGetter &nodeGetter, small_data *next = item->Next(); if (!next->IsLast(node)) memmove((uint8 *)item + spaceNeeded, next, (uint8 *)last - (uint8 *)next); - + // Move the "last" one to its new location and // correctly terminate the small_data section last = (small_data *)((uint8 *)last - ((uint8 *)next - ((uint8 *)item + spaceNeeded))); @@ -967,7 +967,7 @@ Inode::ReadAttribute(const char *name, int32 type, off_t pos, uint8 *buffer, } if (length + pos > smallData->DataSize()) length = smallData->DataSize() - pos; - + memcpy(buffer, smallData->Data() + pos, length); *_length = length; return B_OK; @@ -1190,7 +1190,7 @@ Inode::CreateAttribute(Transaction &transaction, const char *name, uint32 type, { // do we need to create the attribute directory first? if (Attributes().IsZero()) { - status_t status = Inode::Create(transaction, this, NULL, + status_t status = Inode::Create(transaction, this, NULL, S_ATTR_DIR | S_DIRECTORY | 0666, 0, 0, NULL); if (status < B_OK) RETURN_ERROR(status); @@ -1201,7 +1201,7 @@ Inode::CreateAttribute(Transaction &transaction, const char *name, uint32 type, return B_ERROR; // Inode::Create() locks the inode for us - return Inode::Create(transaction, attributes, name, + return Inode::Create(transaction, attributes, name, S_ATTR | S_FILE | 0666, 0, type, NULL, NULL, attribute); } @@ -1426,8 +1426,6 @@ Inode::WriteAt(Transaction &transaction, off_t pos, const uint8 *buffer, locker.Lock(); if (pos + length > Size()) { - off_t oldSize = Size(); - // let's grow the data stream to the size needed status_t status = SetFileSize(transaction, pos + length); if (status < B_OK) { @@ -1438,11 +1436,6 @@ Inode::WriteAt(Transaction &transaction, off_t pos, const uint8 *buffer, // index here as part of the current transaction - this might just // be a bit too expensive, but worth a try. - // If the position of the write was beyond the file size, we - // have to fill the gap between that position and the old file - // size with zeros. - FillGapWithZeros(oldSize, pos); - // we need to write back the inode here because it has to // go into this transaction (we cannot wait until the file // is closed) @@ -1472,81 +1465,21 @@ Inode::WriteAt(Transaction &transaction, off_t pos, const uint8 *buffer, status_t Inode::FillGapWithZeros(off_t pos, off_t newSize) { - // ToDo: we currently do anything here, same as original BFS! - //if (pos >= newSize) - return B_OK; -#if 0 - block_run run; - off_t offset; - if (FindBlockRun(pos, run, offset) < B_OK) - RETURN_ERROR(B_BAD_VALUE); + while (pos < newSize) { + size_t size; + if (newSize > pos + 1024 * 1024 * 1024) + size = 1024 * 1024 * 1024; + else + size = newSize - pos; - off_t length = newSize - pos; - uint32 bytesWritten = 0; - uint32 blockSize = fVolume->BlockSize(); - uint32 blockShift = fVolume->BlockShift(); - uint8 *block; + status_t status = file_cache_write(FileCache(), NULL, pos, NULL, &size); + if (status < B_OK) + return status; - // the first block_run we write could not be aligned to the block_size boundary - // (write partial block at the beginning) - - // pos % block_size == (pos - offset) % block_size, offset % block_size == 0 - if (pos % blockSize != 0) { - run.start += (pos - offset) / blockSize; - run.length -= (pos - offset) / blockSize; - - CachedBlock cached(fVolume,run); - if ((block = cached.Block()) == NULL) - RETURN_ERROR(B_BAD_VALUE); - - bytesWritten = blockSize - (pos % blockSize); - if (length < bytesWritten) - bytesWritten = length; - - memset(block + (pos % blockSize), 0, bytesWritten); - if (fVolume->WriteBlocks(cached.BlockNumber(), block, 1) < B_OK) - RETURN_ERROR(B_IO_ERROR); - - pos += bytesWritten; - - length -= bytesWritten; - if (length == 0) - return B_OK; - - if (FindBlockRun(pos, run, offset) < B_OK) - RETURN_ERROR(B_BAD_VALUE); + pos += size; } - while (length > 0) { - // offset is the offset to the current pos in the block_run - run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift)); - run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift)); - - CachedBlock cached(fVolume); - off_t blockNumber = fVolume->ToBlock(run); - for (int32 i = 0; i < run.Length(); i++) { - if ((block = cached.SetTo(blockNumber + i, true)) == NULL) - RETURN_ERROR(B_IO_ERROR); - - if (fVolume->WriteBlocks(cached.BlockNumber(), block, 1) < B_OK) - RETURN_ERROR(B_IO_ERROR); - } - - int32 bytes = run.Length() << blockShift; - length -= bytes; - bytesWritten += bytes; - - // since we don't respect a last partial block, length can be lower - if (length <= 0) - break; - - pos += bytes; - - if (FindBlockRun(pos, run, offset) < B_OK) - RETURN_ERROR(B_BAD_VALUE); - } return B_OK; -#endif } @@ -2264,7 +2197,7 @@ Inode::Sync() if (indirectRuns[k].IsZero()) return B_OK; - block = fVolume->ToBlock(indirectRuns[k]); + block = fVolume->ToBlock(indirectRuns[k]); for (int32 j = 0; j < indirectRuns[k].Length(); j++) { block_run *runs = (block_run *)directCached.SetTo(block + j); if (runs == NULL) @@ -2532,7 +2465,7 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name, // handle this case on their own (or other cases where "parent" is // NULL) if (status < B_OK) - RETURN_ERROR(status); + RETURN_ERROR(status); // Update the main indices (name, size & last_modified) // (live queries might want to access us after this) diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index c3c8f52381..0a54c37767 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -708,7 +708,7 @@ bfs_write_stat(void *_ns, void *_node, const struct stat *stat, uint32 mask) // TODO: we should definitely check a bit more if the new stats are // valid - or even better, the VFS should check this before calling us - + status_t status = inode->CheckPermissions(W_OK); if (status < B_OK) RETURN_ERROR(status); @@ -734,7 +734,8 @@ bfs_write_stat(void *_ns, void *_node, const struct stat *stat, uint32 mask) return status; // fill the new blocks (if any) with zeros - inode->FillGapWithZeros(inode->OldSize(), inode->Size()); + if ((mask & B_STAT_SIZE_INSECURE) == 0) + inode->FillGapWithZeros(inode->OldSize(), inode->Size()); if (!inode->IsDeleted()) { Index index(volume); @@ -784,7 +785,7 @@ bfs_write_stat(void *_ns, void *_node, const struct stat *stat, uint32 mask) } -status_t +status_t bfs_create(void *_ns, void *_directory, const char *name, int openMode, int mode, void **_cookie, ino_t *_vnodeID) { @@ -804,7 +805,7 @@ bfs_create(void *_ns, void *_directory, const char *name, int openMode, // to remove the inode if we don't have enough free memory later... file_cookie *cookie = (file_cookie *)malloc(sizeof(file_cookie)); if (cookie == NULL) - RETURN_ERROR(B_NO_MEMORY); + RETURN_ERROR(B_NO_MEMORY); // initialize the cookie cookie->open_mode = openMode; @@ -832,7 +833,7 @@ bfs_create(void *_ns, void *_directory, const char *name, int openMode, } -static status_t +static status_t bfs_create_symlink(void *_ns, void *_directory, const char *name, const char *path, int mode) { @@ -895,7 +896,7 @@ bfs_create_symlink(void *_ns, void *_directory, const char *name, } -status_t +status_t bfs_link(void *ns, void *dir, const char *name, void *node) { FUNCTION_START(("name = \"%s\"\n", name)); @@ -906,7 +907,7 @@ bfs_link(void *ns, void *dir, const char *name, void *node) } -status_t +status_t bfs_unlink(void *_ns, void *_directory, const char *name) { FUNCTION_START(("name = \"%s\"\n", name)); @@ -935,7 +936,7 @@ bfs_unlink(void *_ns, void *_directory, const char *name) } -status_t +status_t bfs_rename(void *_ns, void *_oldDir, const char *oldName, void *_newDir, const char *newName) { FUNCTION_START(("oldDir = %p, oldName = \"%s\", newDir = %p, newName = \"%s\"\n", _oldDir, oldName, _newDir, newName)); @@ -1150,7 +1151,7 @@ bfs_open(void *_fs, void *_node, int openMode, void **_cookie) file_cookie *cookie = (file_cookie *)malloc(sizeof(file_cookie)); if (cookie == NULL) - RETURN_ERROR(B_NO_MEMORY); + RETURN_ERROR(B_NO_MEMORY); // initialize the cookie cookie->open_mode = openMode; @@ -1347,7 +1348,7 @@ static status_t bfs_access(void *_ns, void *_node, int accessMode) { //FUNCTION(); - + if (_ns == NULL || _node == NULL) return B_BAD_VALUE; @@ -1438,7 +1439,7 @@ static status_t bfs_remove_dir(void *_ns, void *_directory, const char *name) { FUNCTION_START(("name = \"%s\"\n", name)); - + if (_ns == NULL || _directory == NULL || name == NULL || *name == '\0') return B_BAD_VALUE; @@ -1467,10 +1468,10 @@ static status_t bfs_open_dir(void *_ns, void *_node, void **_cookie) { FUNCTION(); - + if (_ns == NULL || _node == NULL || _cookie == NULL) RETURN_ERROR(B_BAD_VALUE); - + Inode *inode = (Inode *)_node; status_t status = inode->CheckPermissions(R_OK); @@ -1496,7 +1497,7 @@ bfs_open_dir(void *_ns, void *_node, void **_cookie) static status_t -bfs_read_dir(void *_ns, void *_node, void *_cookie, struct dirent *dirent, +bfs_read_dir(void *_ns, void *_node, void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { FUNCTION(); @@ -1537,7 +1538,7 @@ bfs_rewind_dir(void * /*ns*/, void * /*node*/, void *_cookie) if (iterator == NULL) RETURN_ERROR(B_BAD_VALUE); - + return iterator->Rewind(); } @@ -1555,7 +1556,7 @@ static status_t bfs_free_dir_cookie(void *ns, void *node, void *_cookie) { TreeIterator *iterator = (TreeIterator *)_cookie; - + if (iterator == NULL) RETURN_ERROR(B_BAD_VALUE); @@ -1610,7 +1611,7 @@ static status_t bfs_rewind_attr_dir(void *_ns, void *_node, void *_cookie) { FUNCTION(); - + AttributeIterator *iterator = (AttributeIterator *)_cookie; if (iterator == NULL) RETURN_ERROR(B_BAD_VALUE); @@ -2234,7 +2235,7 @@ static file_system_module_info sBeFileSystem = { &bfs_free_dir_cookie, &bfs_read_dir, &bfs_rewind_dir, - + /* attribute directory operations */ &bfs_open_attr_dir, &bfs_close_attr_dir, diff --git a/src/kits/storage/File.cpp b/src/kits/storage/File.cpp index 74e0cacb47..8eb19570ad 100644 --- a/src/kits/storage/File.cpp +++ b/src/kits/storage/File.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -77,7 +78,7 @@ BFile::BFile(const BEntry *entry, uint32 openMode) /*! \brief Creates a BFile and initializes it to the file referred to by the supplied path name and according to the specified open mode. - \param path the file's path name + \param path the file's path name \param openMode the mode in which the file should be opened \see SetTo() for values for \a openMode */ @@ -217,7 +218,7 @@ BFile::SetTo(const BEntry *entry, uint32 openMode) /*! \brief Re-initializes the BFile to the file referred to by the supplied path name and according to the specified open mode. - \param path the file's path name + \param path the file's path name \param openMode the mode in which the file should be opened \return - \c B_OK: Everything went fine. @@ -352,7 +353,7 @@ BFile::ReadAt(off_t location, void *buffer, size_t size) return InitCheck(); if (location < 0) return B_BAD_VALUE; - + return _kern_read(get_fd(), location, buffer, size); } @@ -453,7 +454,7 @@ BFile::SetSize(off_t size) return B_BAD_VALUE; struct stat statData; statData.st_size = size; - return set_stat(statData, B_STAT_SIZE); + return set_stat(statData, B_STAT_SIZE | B_STAT_SIZE_INSECURE); } diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 837f29c708..d4b022dcd4 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -51,7 +51,7 @@ struct file_cache_ref { }; typedef status_t (*cache_func)(file_cache_ref *ref, void *cookie, off_t offset, - int32 pageOffset, addr_t buffer, size_t bufferSize, + int32 pageOffset, addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages, size_t reservePages); @@ -169,7 +169,7 @@ reserve_pages(file_cache_ref *ref, size_t reservePages, bool isWrite) */ static status_t read_into_cache(file_cache_ref *ref, void *cookie, off_t offset, - int32 pageOffset, addr_t buffer, size_t bufferSize, + int32 pageOffset, addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages, size_t reservePages) { TRACE(("read_into_cache(offset = %Ld, pageOffset = %ld, buffer = %#lx, " @@ -240,14 +240,14 @@ read_into_cache(file_cache_ref *ref, void *cookie, off_t offset, return status; } - // copy the pages and unmap them again + // copy the pages if needed and unmap them again for (int32 i = 0; i < vecCount; i++) { addr_t base = (addr_t)vecs[i].iov_base; size_t size = vecs[i].iov_len; // copy to user buffer if necessary - if (bufferSize != 0) { + if (useBuffer && bufferSize != 0) { size_t bytes = min_c(bufferSize, size - pageOffset); user_memcpy((void *)buffer, (void *)(base + pageOffset), bytes); @@ -278,12 +278,15 @@ read_into_cache(file_cache_ref *ref, void *cookie, off_t offset, static status_t read_from_file(file_cache_ref *ref, void *cookie, off_t offset, - int32 pageOffset, addr_t buffer, size_t bufferSize, + int32 pageOffset, addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages, size_t reservePages) { TRACE(("read_from_file(offset = %Ld, pageOffset = %ld, buffer = %#lx, " "bufferSize = %lu\n", offset, pageOffset, buffer, bufferSize)); + if (!useBuffer) + return B_OK; + iovec vec; vec.iov_base = (void *)buffer; vec.iov_len = bufferSize; @@ -310,7 +313,7 @@ read_from_file(file_cache_ref *ref, void *cookie, off_t offset, */ static status_t write_to_cache(file_cache_ref *ref, void *cookie, off_t offset, - int32 pageOffset, addr_t buffer, size_t bufferSize, + int32 pageOffset, addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages, size_t reservePages) { // TODO: We're using way too much stack! Rather allocate a sufficiently @@ -400,8 +403,13 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset, addr_t base = (addr_t)vecs[i].iov_base; size_t bytes = min_c(bufferSize, size_t(vecs[i].iov_len - pageOffset)); - // copy data from user buffer - user_memcpy((void *)(base + pageOffset), (void *)buffer, bytes); + if (useBuffer) { + // copy data from user buffer + user_memcpy((void *)(base + pageOffset), (void *)buffer, bytes); + } else { + // clear buffer instead + memset((void *)(base + pageOffset), 0, bytes); + } bufferSize -= bytes; if (bufferSize == 0) @@ -454,9 +462,21 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset, static status_t write_to_file(file_cache_ref *ref, void *cookie, off_t offset, int32 pageOffset, - addr_t buffer, size_t bufferSize, size_t lastReservedPages, + addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages, size_t reservePages) { + size_t chunkSize; + if (!useBuffer) { + // we need to allocate a zero buffer + // TODO: use smaller buffers if this fails + chunkSize = min_c(bufferSize, B_PAGE_SIZE); + buffer = (addr_t)malloc(chunkSize); + if (buffer == 0) + return B_NO_MEMORY; + + memset((void *)buffer, 0, chunkSize); + } + iovec vec; vec.iov_base = (void *)buffer; vec.iov_len = bufferSize; @@ -465,8 +485,26 @@ write_to_file(file_cache_ref *ref, void *cookie, off_t offset, int32 pageOffset, mutex_unlock(&ref->cache->lock); vm_page_unreserve_pages(lastReservedPages); - status_t status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset, - &vec, 1, &bufferSize, false); + status_t status; + + if (!useBuffer) { + while (bufferSize > 0) { + if (bufferSize < chunkSize) + chunkSize = bufferSize; + + status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset, + &vec, 1, &chunkSize, false); + if (status < B_OK) + break; + + bufferSize -= chunkSize; + pageOffset += chunkSize; + } + } else { + status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset, + &vec, 1, &bufferSize, false); + } + if (status == B_OK) reserve_pages(ref, reservePages, true); @@ -478,9 +516,10 @@ write_to_file(file_cache_ref *ref, void *cookie, off_t offset, int32 pageOffset, static inline status_t satisfy_cache_io(file_cache_ref *ref, void *cookie, cache_func function, - off_t offset, addr_t buffer, int32 &pageOffset, size_t bytesLeft, - size_t &reservePages, off_t &lastOffset, addr_t &lastBuffer, - int32 &lastPageOffset, size_t &lastLeft, size_t &lastReservedPages) + off_t offset, addr_t buffer, bool useBuffer, int32 &pageOffset, + size_t bytesLeft, size_t &reservePages, off_t &lastOffset, + addr_t &lastBuffer, int32 &lastPageOffset, size_t &lastLeft, + size_t &lastReservedPages) { if (lastBuffer == buffer) return B_OK; @@ -490,7 +529,7 @@ satisfy_cache_io(file_cache_ref *ref, void *cookie, cache_func function, + lastPageOffset + B_PAGE_SIZE - 1) >> PAGE_SHIFT); status_t status = function(ref, cookie, lastOffset, lastPageOffset, - lastBuffer, requestSize, lastReservedPages, reservePages); + lastBuffer, requestSize, useBuffer, lastReservedPages, reservePages); if (status == B_OK) { lastReservedPages = reservePages; lastBuffer = buffer; @@ -513,6 +552,7 @@ cache_io(void *_cacheRef, void *cookie, off_t offset, addr_t buffer, file_cache_ref *ref = (file_cache_ref *)_cacheRef; vm_cache *cache = ref->cache; off_t fileSize = cache->virtual_size; + bool useBuffer = buffer != 0; TRACE(("cache_io(ref = %p, offset = %Ld, buffer = %p, size = %lu, %s)\n", ref, offset, (void *)buffer, *_size, doWrite ? "write" : "read")); @@ -575,8 +615,9 @@ cache_io(void *_cacheRef, void *cookie, off_t offset, addr_t buffer, // we didn't get yet (to make sure no one else interferes in the // mean time). status_t status = satisfy_cache_io(ref, cookie, function, offset, - buffer, pageOffset, bytesLeft, reservePages, lastOffset, - lastBuffer, lastPageOffset, lastLeft, lastReservedPages); + buffer, useBuffer, pageOffset, bytesLeft, reservePages, + lastOffset, lastBuffer, lastPageOffset, lastLeft, + lastReservedPages); if (status != B_OK) return status; @@ -606,13 +647,18 @@ cache_io(void *_cacheRef, void *cookie, off_t offset, addr_t buffer, // and copy the contents of the page already in memory if (doWrite) { - user_memcpy((void *)(virtualAddress + pageOffset), - (void *)buffer, bytesInPage); + if (useBuffer) { + user_memcpy((void *)(virtualAddress + pageOffset), + (void *)buffer, bytesInPage); + } else { + user_memset((void *)(virtualAddress + pageOffset), + 0, bytesInPage); + } // make sure the page is in the modified list if (page->state != PAGE_STATE_MODIFIED) vm_page_set_state(page, PAGE_STATE_MODIFIED); - } else { + } else if (useBuffer) { user_memcpy((void *)buffer, (void *)(virtualAddress + pageOffset), bytesInPage); } @@ -643,8 +689,9 @@ cache_io(void *_cacheRef, void *cookie, off_t offset, addr_t buffer, if (buffer - lastBuffer + lastPageOffset >= kMaxChunkSize) { status_t status = satisfy_cache_io(ref, cookie, function, offset, - buffer, pageOffset, bytesLeft, reservePages, lastOffset, - lastBuffer, lastPageOffset, lastLeft, lastReservedPages); + buffer, useBuffer, pageOffset, bytesLeft, reservePages, + lastOffset, lastBuffer, lastPageOffset, lastLeft, + lastReservedPages); if (status != B_OK) return status; } @@ -653,7 +700,7 @@ cache_io(void *_cacheRef, void *cookie, off_t offset, addr_t buffer, // fill the last remaining bytes of the request (either write or read) return function(ref, cookie, lastOffset, lastPageOffset, lastBuffer, - lastLeft, lastReservedPages, 0); + lastLeft, useBuffer, lastReservedPages, 0); } @@ -837,7 +884,7 @@ cache_node_closed(struct vnode *vnode, int32 fdType, vm_cache *cache, } -extern "C" void +extern "C" void cache_node_launched(size_t argCount, char * const *args) { if (sCacheModule == NULL || sCacheModule->node_launched == NULL)