diff --git a/headers/private/userlandfs/private/Requests.h b/headers/private/userlandfs/private/Requests.h index c97e6473aa..2e7fb80b97 100644 --- a/headers/private/userlandfs/private/Requests.h +++ b/headers/private/userlandfs/private/Requests.h @@ -311,8 +311,8 @@ class FileCacheRequest : public Request { public: FileCacheRequest(uint32 type) : Request(type) {} - dev_t volumeID; - ino_t vnodeID; + dev_t nsid; + ino_t vnid; }; @@ -1597,7 +1597,7 @@ class FileCacheCreateRequest : public FileCacheRequest { public: FileCacheCreateRequest() : FileCacheRequest(FILE_CACHE_CREATE_REQUEST) {} - size_t size; + off_t size; }; // FileCacheCreateReply @@ -1678,7 +1678,6 @@ public: status_t GetAddressInfos(AddressInfo* infos, int32* count); Address buffer; - size_t bytesRead; }; // FileCacheWriteRequest diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/file_cache.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/file_cache.cpp index 48340328ac..3fbce8b9fb 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/file_cache.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/file_cache.cpp @@ -5,58 +5,119 @@ #include +#include + +#include "AutoDeleter.h" + +#include "../kernel_emu.h" + + +struct FileCache { + dev_t mountID; + ino_t vnodeID; + bool enabled; + + FileCache(dev_t mountID, ino_t vnodeID) + : + mountID(mountID), + vnodeID(vnodeID), + enabled(true) + { + } +}; + void* file_cache_create(dev_t mountID, ino_t vnodeID, off_t size) { - // TODO: Implement! - return NULL; + // create the client-side object + FileCache* fileCache = new(std::nothrow) FileCache(mountID, vnodeID); + if (fileCache == NULL) + return NULL; + ObjectDeleter cacheDeleter(fileCache); + + + // create the kernel-size file cache + status_t error = UserlandFS::KernelEmu::file_cache_create(mountID, vnodeID, + size); + if (error != B_OK) + return NULL; + + cacheDeleter.Detach(); + return fileCache; } void file_cache_delete(void *cacheRef) { - // TODO: Implement! + FileCache* fileCache = (FileCache*)cacheRef; + + UserlandFS::KernelEmu::file_cache_delete(fileCache->mountID, + fileCache->vnodeID); + + delete fileCache; } void file_cache_enable(void *cacheRef) { - // TODO: Implement! + FileCache* fileCache = (FileCache*)cacheRef; + + if (fileCache->enabled) + return; + + if (UserlandFS::KernelEmu::file_cache_set_enabled(fileCache->mountID, + fileCache->vnodeID, true) == B_OK) { + fileCache->enabled = true; + } } bool file_cache_is_enabled(void *cacheRef) { - // TODO: Implement! - return false; + FileCache* fileCache = (FileCache*)cacheRef; + + return fileCache->enabled; } status_t file_cache_disable(void *cacheRef) { - // TODO: Implement! - return B_NOT_SUPPORTED; + FileCache* fileCache = (FileCache*)cacheRef; + + if (!fileCache->enabled) + return B_OK; + + status_t error = UserlandFS::KernelEmu::file_cache_set_enabled( + fileCache->mountID, fileCache->vnodeID, false); + if (error == B_OK) + fileCache->enabled = false; + + return error; } status_t file_cache_set_size(void *cacheRef, off_t size) { - // TODO: Implement! - return B_NOT_SUPPORTED; + FileCache* fileCache = (FileCache*)cacheRef; + + return UserlandFS::KernelEmu::file_cache_set_size(fileCache->mountID, + fileCache->vnodeID, size); } status_t -file_cache_sync(void *cache) +file_cache_sync(void *cacheRef) { - // TODO: Implement! - return B_NOT_SUPPORTED; + FileCache* fileCache = (FileCache*)cacheRef; + + return UserlandFS::KernelEmu::file_cache_sync(fileCache->mountID, + fileCache->vnodeID); } @@ -64,8 +125,10 @@ status_t file_cache_read(void *cacheRef, void *cookie, off_t offset, void *bufferBase, size_t *_size) { - // TODO: Implement! - return B_NOT_SUPPORTED; + FileCache* fileCache = (FileCache*)cacheRef; + + return UserlandFS::KernelEmu::file_cache_read(fileCache->mountID, + fileCache->vnodeID, cookie, offset, bufferBase, _size); } @@ -73,6 +136,8 @@ status_t file_cache_write(void *cacheRef, void *cookie, off_t offset, const void *buffer, size_t *_size) { - // TODO: Implement! - return B_NOT_SUPPORTED; + FileCache* fileCache = (FileCache*)cacheRef; + + return UserlandFS::KernelEmu::file_cache_write(fileCache->mountID, + fileCache->vnodeID, cookie, offset, buffer, _size); } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp index 34e6dbbe49..481ea06f42 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp @@ -562,8 +562,286 @@ UserlandFS::KernelEmu::get_vnode_removed(dev_t nsid, ino_t vnid, return reply->error; } + +// #pragma mark - file cache + + +// file_cache_create +status_t +UserlandFS::KernelEmu::file_cache_create(dev_t mountID, ino_t vnodeID, + off_t size) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + FileCacheCreateRequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->nsid = mountID; + request->vnid = vnodeID; + request->size = size; + + // send the request + UserlandRequestHandler handler(fileSystem, FILE_CACHE_CREATE_REPLY); + FileCacheCreateReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + return reply->error; +} + + +// file_cache_delete +status_t +UserlandFS::KernelEmu::file_cache_delete(dev_t mountID, ino_t vnodeID) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + FileCacheDeleteRequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->nsid = mountID; + request->vnid = vnodeID; + + // send the request + UserlandRequestHandler handler(fileSystem, FILE_CACHE_DELETE_REPLY); + FileCacheDeleteReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + return reply->error; +} + + +// file_cache_set_enable +status_t +UserlandFS::KernelEmu::file_cache_set_enabled(dev_t mountID, ino_t vnodeID, + bool enabled) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + FileCacheSetEnabledRequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->nsid = mountID; + request->vnid = vnodeID; + request->enabled = enabled; + + // send the request + UserlandRequestHandler handler(fileSystem, FILE_CACHE_SET_ENABLED_REPLY); + FileCacheSetEnabledReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + return reply->error; +} + + +// file_cache_set_size +status_t +UserlandFS::KernelEmu::file_cache_set_size(dev_t mountID, ino_t vnodeID, + off_t size) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + FileCacheSetSizeRequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->nsid = mountID; + request->vnid = vnodeID; + request->size = size; + + // send the request + UserlandRequestHandler handler(fileSystem, FILE_CACHE_SET_SIZE_REPLY); + FileCacheSetSizeReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + return reply->error; +} + + +// file_cache_sync +status_t +UserlandFS::KernelEmu::file_cache_sync(dev_t mountID, ino_t vnodeID) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + FileCacheSyncRequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->nsid = mountID; + request->vnid = vnodeID; + + // send the request + UserlandRequestHandler handler(fileSystem, FILE_CACHE_SYNC_REPLY); + FileCacheSyncReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + return reply->error; +} + + +// file_cache_read +status_t +UserlandFS::KernelEmu::file_cache_read(dev_t mountID, ino_t vnodeID, + void *cookie, off_t offset, void *bufferBase, size_t *_size) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + FileCacheReadRequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->nsid = mountID; + request->vnid = vnodeID; + request->cookie = cookie; + // TODO: cookie can only be NULL! + request->pos = offset; + request->size = *_size; + + // send the request + UserlandRequestHandler handler(fileSystem, FILE_CACHE_READ_REPLY); + FileCacheReadReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + if (reply->error != B_OK) + return reply->error; + + if (reply->buffer.GetSize() > 0) { + memcpy(bufferBase, reply->buffer.GetData(), reply->buffer.GetSize()); + + // send receipt-ack + RequestAllocator receiptAckAllocator(port->GetPort()); + ReceiptAckReply* receiptAck; + if (AllocateRequest(receiptAckAllocator, &receiptAck) == B_OK) + port->SendRequest(&receiptAckAllocator); + } + + *_size = reply->buffer.GetSize(); + + return B_OK; +} + + +// file_cache_write +status_t +UserlandFS::KernelEmu::file_cache_write(dev_t mountID, ino_t vnodeID, + void *cookie, off_t offset, const void *buffer, size_t *_size) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + FileCacheWriteRequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->nsid = mountID; + request->vnid = vnodeID; + request->cookie = cookie; + // TODO: cookie can only be NULL! + request->pos = offset; + + error = allocator.AllocateData(request->buffer, buffer, *_size, 1, false); + if (error != B_OK) + return error; + + // send the request + UserlandRequestHandler handler(fileSystem, FILE_CACHE_WRITE_REPLY); + FileCacheWriteReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + *_size = reply->bytesWritten; + return reply->error; +} + + // #pragma mark - + // kernel_debugger void UserlandFS::KernelEmu::kernel_debugger(const char *message) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h index 5cd4069ab9..778a847311 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h @@ -31,6 +31,18 @@ status_t remove_vnode(dev_t nsid, ino_t vnid); status_t unremove_vnode(dev_t nsid, ino_t vnid); status_t get_vnode_removed(dev_t nsid, ino_t vnid, bool* removed); +extern status_t file_cache_create(dev_t mountID, ino_t vnodeID, off_t size); +extern status_t file_cache_delete(dev_t mountID, ino_t vnodeID); +extern status_t file_cache_set_enabled(dev_t mountID, ino_t vnodeID, + bool enabled); +extern status_t file_cache_set_size(dev_t mountID, ino_t vnodeID, off_t size); +extern status_t file_cache_sync(dev_t mountID, ino_t vnodeID); + +extern status_t file_cache_read(dev_t mountID, ino_t vnodeID, void *cookie, + off_t offset, void *bufferBase, size_t *_size); +extern status_t file_cache_write(dev_t mountID, ino_t vnodeID, void *cookie, + off_t offset, const void *buffer, size_t *_size); + void kernel_debugger(const char *message); void vpanic(const char *format, va_list args); void panic(const char *format, ...) __attribute__ ((format (__printf__, 1, 2)));