From bb94d91d075bd9727f778e72c2e419eb70077269 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 28 Jul 2008 14:29:49 +0000 Subject: [PATCH] Implemented the devfs io() hook. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26660 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/device_manager/devfs.cpp | 82 +++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/system/kernel/device_manager/devfs.cpp b/src/system/kernel/device_manager/devfs.cpp index 6349a74358..d53d432f41 100644 --- a/src/system/kernel/device_manager/devfs.cpp +++ b/src/system/kernel/device_manager/devfs.cpp @@ -36,6 +36,7 @@ #include #include "BaseDevice.h" +#include "io_requests.h" #include "legacy_drivers.h" @@ -113,6 +114,11 @@ struct devfs_cookie { void* device_cookie; }; +struct synchronous_io_cookie { + BaseDevice* device; + void* cookie; +}; + // directory iteration states enum { ITERATION_STATE_DOT = 0, @@ -443,6 +449,18 @@ translate_partition_access(devfs_partition* partition, off_t& offset, } +static inline void +translate_partition_access(devfs_partition* partition, io_request* request) +{ + off_t offset = request->Offset(); + + ASSERT(offset >= 0); + ASSERT(offset + request->Length() <= partition->info.size); + + request->SetOffset(offset + partition->info.offset); +} + + static status_t get_node_for_path(struct devfs *fs, const char *path, struct devfs_vnode **_node) @@ -737,6 +755,30 @@ get_device_name(struct devfs_vnode* vnode, char* buffer, size_t size) } +static status_t +device_read(void* _cookie, off_t offset, void* buffer, size_t length) +{ + synchronous_io_cookie* cookie = (synchronous_io_cookie*)_cookie; + + size_t transferred = length; + status_t error = cookie->device->Read(cookie->cookie, offset, buffer, + &transferred); + return error == B_OK && transferred != length ? B_FILE_ERROR : error; +} + + +static status_t +device_write(void* _cookie, off_t offset, void* buffer, size_t length) +{ + synchronous_io_cookie* cookie = (synchronous_io_cookie*)_cookie; + + size_t transferred = length; + status_t error = cookie->device->Write(cookie->cookie, offset, buffer, + &transferred); + return error == B_OK && transferred != length ? B_FILE_ERROR : error; +} + + static int dump_node(int argc, char **argv) { @@ -1707,6 +1749,44 @@ devfs_write_pages(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, } +static status_t +devfs_io(fs_volume *volume, fs_vnode *_vnode, void *_cookie, + io_request *request) +{ + devfs_vnode* vnode = (devfs_vnode*)_vnode->private_node; + devfs_cookie* cookie = (devfs_cookie*)_cookie; + + bool isWrite = request->IsWrite(); + + if (!S_ISCHR(vnode->stream.type) + || ((isWrite && !vnode->stream.u.dev.device->HasWrite() + || !isWrite && !vnode->stream.u.dev.device->HasRead()) + && !vnode->stream.u.dev.device->HasIO()) + || cookie == NULL) { + return B_NOT_ALLOWED; + } + + if (vnode->stream.u.dev.partition) { + if (request->Offset() + request->Length() + >= vnode->stream.u.dev.partition->info.size) { + return B_BAD_VALUE; + } + translate_partition_access(vnode->stream.u.dev.partition, request); + } + + if (vnode->stream.u.dev.device->HasIO()) + return vnode->stream.u.dev.device->IO(cookie->device_cookie, request); + + synchronous_io_cookie synchronousCookie = { + vnode->stream.u.dev.device, + cookie->device_cookie + }; + + return vfs_synchronous_io(request, + request->IsWrite() ? &device_write : &device_read, &synchronousCookie); +} + + static status_t devfs_read_stat(fs_volume* _volume, fs_vnode* _vnode, struct stat* stat) { @@ -1836,7 +1916,7 @@ fs_vnode_ops kVnodeOps = { &devfs_read_pages, &devfs_write_pages, - NULL, // io() + &devfs_io, NULL, // cancel_io() NULL, // get_file_map