Updated write_to_cache() to use physical pages for I/O and the new

{memset,memcpy_to}_physical() functions.
Mapping lots of physical pages at once as done before was an actual
problem on systems with enough RAM, as the physical page mapper can map
only 64 chunks at a time. So multiple threads could play dining
philosophers, each getting only one of two chopsticks, waiting for
another one to be freed.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28220 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-10-17 16:45:14 +00:00
parent 901f1930e1
commit 7b8683b252
+13 -26
View File
@@ -17,6 +17,7 @@
#include <file_cache.h>
#include <generic_syscall.h>
#include <low_resource_manager.h>
#include <thread.h>
#include <util/AutoLock.h>
#include <util/kernel_cpp.h>
#include <vfs.h>
@@ -332,12 +333,8 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
ref->cache->InsertPage(page, offset + pos);
addr_t virtualAddress;
vm_get_physical_page(page->physical_page_number * B_PAGE_SIZE,
&virtualAddress, 0);
add_to_iovec(vecs, vecCount, MAX_IO_VECS, virtualAddress, B_PAGE_SIZE);
// ToDo: check if the array is large enough!
add_to_iovec(vecs, vecCount, MAX_IO_VECS,
page->physical_page_number * B_PAGE_SIZE, B_PAGE_SIZE);
}
push_access(ref, offset, bufferSize, true);
@@ -352,8 +349,8 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
iovec readVec = { vecs[0].iov_base, B_PAGE_SIZE };
size_t bytesRead = B_PAGE_SIZE;
status = vfs_read_pages(ref->vnode, cookie, offset, &readVec, 1, 0,
&bytesRead);
status = vfs_read_pages(ref->vnode, cookie, offset, &readVec, 1,
B_PHYSICAL_IO_REQUEST, &bytesRead);
// ToDo: handle errors for real!
if (status < B_OK)
panic("1. vfs_read_pages() failed: %s!\n", strerror(status));
@@ -367,7 +364,7 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
if (offset + pageOffset + bufferSize == ref->cache->virtual_end) {
// the space in the page after this write action needs to be cleaned
memset((void *)(last + lastPageOffset), 0,
memset_physical(last + lastPageOffset, 0,
B_PAGE_SIZE - lastPageOffset);
} else {
// the end of this write does not happen on a page boundary, so we
@@ -377,28 +374,29 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
status = vfs_read_pages(ref->vnode, cookie,
PAGE_ALIGN(offset + pageOffset + bufferSize) - B_PAGE_SIZE,
&readVec, 1, 0, &bytesRead);
&readVec, 1, B_PHYSICAL_IO_REQUEST, &bytesRead);
// ToDo: handle errors for real!
if (status < B_OK)
panic("vfs_read_pages() failed: %s!\n", strerror(status));
if (bytesRead < B_PAGE_SIZE) {
// the space beyond the file size needs to be cleaned
memset((void *)(last + bytesRead), 0, B_PAGE_SIZE - bytesRead);
memset_physical(last + bytesRead, 0, B_PAGE_SIZE - bytesRead);
}
}
}
for (int32 i = 0; i < vecCount; i++) {
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
user_memcpy((void *)(base + pageOffset), (void *)buffer, bytes);
memcpy_to_physical(base + pageOffset, (void *)buffer, bytes, true);
} else {
// clear buffer instead
memset((void *)(base + pageOffset), 0, bytes);
memset_physical(base + pageOffset, 0, bytes);
}
bufferSize -= bytes;
@@ -412,7 +410,7 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
if (writeThrough) {
// write cached pages back to the file if we were asked to do that
status_t status = vfs_write_pages(ref->vnode, cookie, offset, vecs,
vecCount, 0, &numBytes);
vecCount, B_PHYSICAL_IO_REQUEST, &numBytes);
if (status < B_OK) {
// ToDo: remove allocated pages, ...?
panic("file_cache: remove allocated pages! write pages failed: %s\n",
@@ -425,17 +423,6 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
ref->cache->Lock();
// unmap the pages again
for (int32 i = 0; i < vecCount; i++) {
addr_t base = (addr_t)vecs[i].iov_base;
size_t size = vecs[i].iov_len;
for (size_t pos = 0; pos < size; pos += B_PAGE_SIZE,
base += B_PAGE_SIZE) {
vm_put_physical_page(base);
}
}
// make the pages accessible in the cache
for (int32 i = pageIndex; i-- > 0;) {
busyConditions[i].Unpublish();