* Added a new flag for write stat: B_STAT_SIZE_INSECURE that allows a
file system to not fill newly created space with zeros. BFile::SetSize() now uses this, while [f]truncate() does not. This is only a temporary work-around until BFS supports sparse files. * Apps that want to reserve space to fill up later should use BFile::SetSize() for now, as this will be a lot faster than [f]truncate(). * cache_io() and the functions below now use a special mode when you pass in a NULL buffer: for read access, the cache is only populated (useful for prefetching), for write access, the file is filled with zeros. * Implemented BFS's Inode::FillGapWithZeros() using this method now. * Removed extraneous white space. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24555 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -29,6 +29,8 @@ typedef void *fs_vnode;
|
|||||||
/* additional flags passed to write_stat() (see NodeMonitor.h for the others) */
|
/* additional flags passed to write_stat() (see NodeMonitor.h for the others) */
|
||||||
// NOTE: Changing the constants here or in NodeMonitor.h will break
|
// NOTE: Changing the constants here or in NodeMonitor.h will break
|
||||||
// src/kits/storage/LibBeAdapter.cpp:_kern_write_stat().
|
// 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() */
|
/* passed to write_fs_info() */
|
||||||
#define FS_WRITE_FSINFO_NAME 0x0001
|
#define FS_WRITE_FSINFO_NAME 0x0001
|
||||||
|
|||||||
@@ -874,6 +874,9 @@
|
|||||||
#define fs_cookie fssh_fs_cookie
|
#define fs_cookie fssh_fs_cookie
|
||||||
#define fs_vnode fssh_fs_vnode
|
#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() */
|
/* passed to write_fs_info() */
|
||||||
#define FS_WRITE_FSINFO_NAME FSSH_FS_WRITE_FSINFO_NAME
|
#define FS_WRITE_FSINFO_NAME FSSH_FS_WRITE_FSINFO_NAME
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ typedef void *fssh_fs_cookie;
|
|||||||
typedef void *fssh_fs_vnode;
|
typedef void *fssh_fs_vnode;
|
||||||
|
|
||||||
/* additional flags passed to write_stat() */
|
/* additional flags passed to write_stat() */
|
||||||
|
#define FSSH_B_STAT_SIZE_INSECURE 0x2000
|
||||||
|
|
||||||
/* passed to write_fs_info() */
|
/* passed to write_fs_info() */
|
||||||
#define FSSH_FS_WRITE_FSINFO_NAME 0x0001
|
#define FSSH_FS_WRITE_FSINFO_NAME 0x0001
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ Inode::InitCheck(bool checkNode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IsContainer()) {
|
if (IsContainer()) {
|
||||||
// inodes that have a
|
// inodes that have a B+tree
|
||||||
if (fTree == NULL)
|
if (fTree == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
@@ -1426,8 +1426,6 @@ Inode::WriteAt(Transaction &transaction, off_t pos, const uint8 *buffer,
|
|||||||
locker.Lock();
|
locker.Lock();
|
||||||
|
|
||||||
if (pos + length > Size()) {
|
if (pos + length > Size()) {
|
||||||
off_t oldSize = Size();
|
|
||||||
|
|
||||||
// let's grow the data stream to the size needed
|
// let's grow the data stream to the size needed
|
||||||
status_t status = SetFileSize(transaction, pos + length);
|
status_t status = SetFileSize(transaction, pos + length);
|
||||||
if (status < B_OK) {
|
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
|
// index here as part of the current transaction - this might just
|
||||||
// be a bit too expensive, but worth a try.
|
// 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
|
// we need to write back the inode here because it has to
|
||||||
// go into this transaction (we cannot wait until the file
|
// go into this transaction (we cannot wait until the file
|
||||||
// is closed)
|
// is closed)
|
||||||
@@ -1472,81 +1465,21 @@ Inode::WriteAt(Transaction &transaction, off_t pos, const uint8 *buffer,
|
|||||||
status_t
|
status_t
|
||||||
Inode::FillGapWithZeros(off_t pos, off_t newSize)
|
Inode::FillGapWithZeros(off_t pos, off_t newSize)
|
||||||
{
|
{
|
||||||
// ToDo: we currently do anything here, same as original BFS!
|
while (pos < newSize) {
|
||||||
//if (pos >= newSize)
|
size_t size;
|
||||||
return B_OK;
|
if (newSize > pos + 1024 * 1024 * 1024)
|
||||||
#if 0
|
size = 1024 * 1024 * 1024;
|
||||||
block_run run;
|
else
|
||||||
off_t offset;
|
size = newSize - pos;
|
||||||
if (FindBlockRun(pos, run, offset) < B_OK)
|
|
||||||
RETURN_ERROR(B_BAD_VALUE);
|
|
||||||
|
|
||||||
off_t length = newSize - pos;
|
status_t status = file_cache_write(FileCache(), NULL, pos, NULL, &size);
|
||||||
uint32 bytesWritten = 0;
|
if (status < B_OK)
|
||||||
uint32 blockSize = fVolume->BlockSize();
|
return status;
|
||||||
uint32 blockShift = fVolume->BlockShift();
|
|
||||||
uint8 *block;
|
|
||||||
|
|
||||||
// the first block_run we write could not be aligned to the block_size boundary
|
pos += size;
|
||||||
// (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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return B_OK;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -734,6 +734,7 @@ bfs_write_stat(void *_ns, void *_node, const struct stat *stat, uint32 mask)
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
// fill the new blocks (if any) with zeros
|
// fill the new blocks (if any) with zeros
|
||||||
|
if ((mask & B_STAT_SIZE_INSECURE) == 0)
|
||||||
inode->FillGapWithZeros(inode->OldSize(), inode->Size());
|
inode->FillGapWithZeros(inode->OldSize(), inode->Size());
|
||||||
|
|
||||||
if (!inode->IsDeleted()) {
|
if (!inode->IsDeleted()) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
|
#include <fs_interface.h>
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
@@ -453,7 +454,7 @@ BFile::SetSize(off_t size)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
struct stat statData;
|
struct stat statData;
|
||||||
statData.st_size = size;
|
statData.st_size = size;
|
||||||
return set_stat(statData, B_STAT_SIZE);
|
return set_stat(statData, B_STAT_SIZE | B_STAT_SIZE_INSECURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+66
-19
@@ -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.
|
* 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,
|
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);
|
size_t lastReservedPages, size_t reservePages);
|
||||||
|
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ reserve_pages(file_cache_ref *ref, size_t reservePages, bool isWrite)
|
|||||||
*/
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
read_into_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
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)
|
size_t lastReservedPages, size_t reservePages)
|
||||||
{
|
{
|
||||||
TRACE(("read_into_cache(offset = %Ld, pageOffset = %ld, buffer = %#lx, "
|
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;
|
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++) {
|
for (int32 i = 0; i < vecCount; i++) {
|
||||||
addr_t base = (addr_t)vecs[i].iov_base;
|
addr_t base = (addr_t)vecs[i].iov_base;
|
||||||
size_t size = vecs[i].iov_len;
|
size_t size = vecs[i].iov_len;
|
||||||
|
|
||||||
// copy to user buffer if necessary
|
// copy to user buffer if necessary
|
||||||
if (bufferSize != 0) {
|
if (useBuffer && bufferSize != 0) {
|
||||||
size_t bytes = min_c(bufferSize, size - pageOffset);
|
size_t bytes = min_c(bufferSize, size - pageOffset);
|
||||||
|
|
||||||
user_memcpy((void *)buffer, (void *)(base + pageOffset), bytes);
|
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
|
static status_t
|
||||||
read_from_file(file_cache_ref *ref, void *cookie, off_t offset,
|
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)
|
size_t lastReservedPages, size_t reservePages)
|
||||||
{
|
{
|
||||||
TRACE(("read_from_file(offset = %Ld, pageOffset = %ld, buffer = %#lx, "
|
TRACE(("read_from_file(offset = %Ld, pageOffset = %ld, buffer = %#lx, "
|
||||||
"bufferSize = %lu\n", offset, pageOffset, buffer, bufferSize));
|
"bufferSize = %lu\n", offset, pageOffset, buffer, bufferSize));
|
||||||
|
|
||||||
|
if (!useBuffer)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
iovec vec;
|
iovec vec;
|
||||||
vec.iov_base = (void *)buffer;
|
vec.iov_base = (void *)buffer;
|
||||||
vec.iov_len = bufferSize;
|
vec.iov_len = bufferSize;
|
||||||
@@ -310,7 +313,7 @@ read_from_file(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
*/
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
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)
|
size_t lastReservedPages, size_t reservePages)
|
||||||
{
|
{
|
||||||
// TODO: We're using way too much stack! Rather allocate a sufficiently
|
// 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;
|
addr_t base = (addr_t)vecs[i].iov_base;
|
||||||
size_t bytes = min_c(bufferSize, size_t(vecs[i].iov_len - pageOffset));
|
size_t bytes = min_c(bufferSize, size_t(vecs[i].iov_len - pageOffset));
|
||||||
|
|
||||||
|
if (useBuffer) {
|
||||||
// copy data from user buffer
|
// copy data from user buffer
|
||||||
user_memcpy((void *)(base + pageOffset), (void *)buffer, bytes);
|
user_memcpy((void *)(base + pageOffset), (void *)buffer, bytes);
|
||||||
|
} else {
|
||||||
|
// clear buffer instead
|
||||||
|
memset((void *)(base + pageOffset), 0, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
bufferSize -= bytes;
|
bufferSize -= bytes;
|
||||||
if (bufferSize == 0)
|
if (bufferSize == 0)
|
||||||
@@ -454,9 +462,21 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
write_to_file(file_cache_ref *ref, void *cookie, off_t offset, int32 pageOffset,
|
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 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;
|
iovec vec;
|
||||||
vec.iov_base = (void *)buffer;
|
vec.iov_base = (void *)buffer;
|
||||||
vec.iov_len = bufferSize;
|
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);
|
mutex_unlock(&ref->cache->lock);
|
||||||
vm_page_unreserve_pages(lastReservedPages);
|
vm_page_unreserve_pages(lastReservedPages);
|
||||||
|
|
||||||
status_t status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
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);
|
&vec, 1, &bufferSize, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
reserve_pages(ref, reservePages, true);
|
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
|
static inline status_t
|
||||||
satisfy_cache_io(file_cache_ref *ref, void *cookie, cache_func function,
|
satisfy_cache_io(file_cache_ref *ref, void *cookie, cache_func function,
|
||||||
off_t offset, addr_t buffer, int32 &pageOffset, size_t bytesLeft,
|
off_t offset, addr_t buffer, bool useBuffer, int32 &pageOffset,
|
||||||
size_t &reservePages, off_t &lastOffset, addr_t &lastBuffer,
|
size_t bytesLeft, size_t &reservePages, off_t &lastOffset,
|
||||||
int32 &lastPageOffset, size_t &lastLeft, size_t &lastReservedPages)
|
addr_t &lastBuffer, int32 &lastPageOffset, size_t &lastLeft,
|
||||||
|
size_t &lastReservedPages)
|
||||||
{
|
{
|
||||||
if (lastBuffer == buffer)
|
if (lastBuffer == buffer)
|
||||||
return B_OK;
|
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);
|
+ lastPageOffset + B_PAGE_SIZE - 1) >> PAGE_SHIFT);
|
||||||
|
|
||||||
status_t status = function(ref, cookie, lastOffset, lastPageOffset,
|
status_t status = function(ref, cookie, lastOffset, lastPageOffset,
|
||||||
lastBuffer, requestSize, lastReservedPages, reservePages);
|
lastBuffer, requestSize, useBuffer, lastReservedPages, reservePages);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
lastReservedPages = reservePages;
|
lastReservedPages = reservePages;
|
||||||
lastBuffer = buffer;
|
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;
|
file_cache_ref *ref = (file_cache_ref *)_cacheRef;
|
||||||
vm_cache *cache = ref->cache;
|
vm_cache *cache = ref->cache;
|
||||||
off_t fileSize = cache->virtual_size;
|
off_t fileSize = cache->virtual_size;
|
||||||
|
bool useBuffer = buffer != 0;
|
||||||
|
|
||||||
TRACE(("cache_io(ref = %p, offset = %Ld, buffer = %p, size = %lu, %s)\n",
|
TRACE(("cache_io(ref = %p, offset = %Ld, buffer = %p, size = %lu, %s)\n",
|
||||||
ref, offset, (void *)buffer, *_size, doWrite ? "write" : "read"));
|
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
|
// we didn't get yet (to make sure no one else interferes in the
|
||||||
// mean time).
|
// mean time).
|
||||||
status_t status = satisfy_cache_io(ref, cookie, function, offset,
|
status_t status = satisfy_cache_io(ref, cookie, function, offset,
|
||||||
buffer, pageOffset, bytesLeft, reservePages, lastOffset,
|
buffer, useBuffer, pageOffset, bytesLeft, reservePages,
|
||||||
lastBuffer, lastPageOffset, lastLeft, lastReservedPages);
|
lastOffset, lastBuffer, lastPageOffset, lastLeft,
|
||||||
|
lastReservedPages);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
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
|
// and copy the contents of the page already in memory
|
||||||
if (doWrite) {
|
if (doWrite) {
|
||||||
|
if (useBuffer) {
|
||||||
user_memcpy((void *)(virtualAddress + pageOffset),
|
user_memcpy((void *)(virtualAddress + pageOffset),
|
||||||
(void *)buffer, bytesInPage);
|
(void *)buffer, bytesInPage);
|
||||||
|
} else {
|
||||||
|
user_memset((void *)(virtualAddress + pageOffset),
|
||||||
|
0, bytesInPage);
|
||||||
|
}
|
||||||
|
|
||||||
// make sure the page is in the modified list
|
// make sure the page is in the modified list
|
||||||
if (page->state != PAGE_STATE_MODIFIED)
|
if (page->state != PAGE_STATE_MODIFIED)
|
||||||
vm_page_set_state(page, PAGE_STATE_MODIFIED);
|
vm_page_set_state(page, PAGE_STATE_MODIFIED);
|
||||||
} else {
|
} else if (useBuffer) {
|
||||||
user_memcpy((void *)buffer,
|
user_memcpy((void *)buffer,
|
||||||
(void *)(virtualAddress + pageOffset), bytesInPage);
|
(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) {
|
if (buffer - lastBuffer + lastPageOffset >= kMaxChunkSize) {
|
||||||
status_t status = satisfy_cache_io(ref, cookie, function, offset,
|
status_t status = satisfy_cache_io(ref, cookie, function, offset,
|
||||||
buffer, pageOffset, bytesLeft, reservePages, lastOffset,
|
buffer, useBuffer, pageOffset, bytesLeft, reservePages,
|
||||||
lastBuffer, lastPageOffset, lastLeft, lastReservedPages);
|
lastOffset, lastBuffer, lastPageOffset, lastLeft,
|
||||||
|
lastReservedPages);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
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)
|
// fill the last remaining bytes of the request (either write or read)
|
||||||
|
|
||||||
return function(ref, cookie, lastOffset, lastPageOffset, lastBuffer,
|
return function(ref, cookie, lastOffset, lastPageOffset, lastBuffer,
|
||||||
lastLeft, lastReservedPages, 0);
|
lastLeft, useBuffer, lastReservedPages, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user