From c74777f3d3fcc7c0437ba6738f504f5551179fed Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 4 Mar 2009 00:44:13 +0000 Subject: [PATCH] Finished node management. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29392 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../server/haiku/HaikuKernelFileSystem.cpp | 18 ++- .../userlandfs/server/haiku/HaikuKernelNode.h | 18 +++ .../server/haiku/HaikuKernelVolume.cpp | 128 +++++++++++++++--- .../server/haiku/HaikuKernelVolume.h | 9 +- 4 files changed, 146 insertions(+), 27 deletions(-) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp index 3024dd1931..4e99539e7f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp @@ -59,16 +59,24 @@ HaikuKernelFileSystem::Init() // CreateVolume status_t -HaikuKernelFileSystem::CreateVolume(Volume** volume, dev_t id) +HaikuKernelFileSystem::CreateVolume(Volume** _volume, dev_t id) { // check initialization and parameters - if (!fFSModule || !volume) + if (!fFSModule || !_volume) return B_BAD_VALUE; - // create the volume - *volume = new(std::nothrow) HaikuKernelVolume(this, id, fFSModule); - if (!*volume) + // create and init the volume + HaikuKernelVolume* volume + = new(std::nothrow) HaikuKernelVolume(this, id, fFSModule); + if (!volume) return B_NO_MEMORY; + + status_t error = volume->Init(); + if (error != B_OK) { + delete volume; + return error; + } + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelNode.h b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelNode.h index d1b8fd2417..e1163cc72a 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelNode.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelNode.h @@ -18,15 +18,33 @@ using UserlandFSUtil::FSVNodeCapabilities; struct HaikuKernelNode : fs_vnode { + ino_t id; HaikuKernelVolume* volume; + bool published; public: + inline HaikuKernelNode(HaikuKernelVolume* volume, + ino_t vnodeID, void* privateNode, + fs_vnode_ops* ops); + static HaikuKernelNode* GetNode(fs_vnode* node); HaikuKernelVolume* GetVolume() const { return volume; } }; +HaikuKernelNode::HaikuKernelNode(HaikuKernelVolume* volume, ino_t vnodeID, + void* privateNode, fs_vnode_ops* ops) + : + id(vnodeID), + volume(volume), + published(false) +{ + this->private_node = privateNode; + this->ops = ops; +} + + /*static*/ inline HaikuKernelNode* HaikuKernelNode::GetNode(fs_vnode* node) { diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp index 59df1e343e..f614f56076 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp @@ -7,18 +7,29 @@ #include #include +#include "AutoDeleter.h" +#include "AutoLocker.h" #include "Debug.h" +#include "HashMap.h" #include "../kernel_emu.h" #include "HaikuKernelNode.h" +// NodeMap +class HaikuKernelVolume::NodeMap + : public SynchronizedHashMap, HaikuKernelNode*> { +}; + + // constructor HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id, file_system_module_info* fsModule) - : Volume(fileSystem, id), - fFSModule(fsModule) + : + Volume(fileSystem, id), + fFSModule(fsModule), + fNodes(NULL) { fVolume.id = id; fVolume.partition = -1; @@ -38,41 +49,98 @@ HaikuKernelVolume::~HaikuKernelVolume() } +// Init +status_t +HaikuKernelVolume::Init() +{ + fNodes = new(std::nothrow) NodeMap; + if (fNodes == NULL) + return B_NO_MEMORY; + + return fNodes->InitCheck(); +} + + // NewVNode status_t HaikuKernelVolume::NewVNode(ino_t vnodeID, void* privateNode, fs_vnode_ops* ops, - HaikuKernelNode** node) + HaikuKernelNode** _node) { - // TODO: Implement! - return B_NOT_SUPPORTED; + AutoLocker _(fNodes); + + // check whether we do already know the node + HaikuKernelNode* node = fNodes->Get(vnodeID); + if (node != NULL) + return B_BAD_VALUE; + + // create a new node + node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, ops); + if (node == NULL) + return B_NO_MEMORY; + + // add to map + status_t error = fNodes->Put(vnodeID, node); + if (error != B_OK) { + delete node; + return error; + } + + *_node = node; + + return B_OK; } // PublishVNode status_t HaikuKernelVolume::PublishVNode(ino_t vnodeID, void* privateNode, - fs_vnode_ops* ops, int type, uint32 flags, HaikuKernelNode** node) + fs_vnode_ops* ops, int type, uint32 flags, HaikuKernelNode** _node) { - // TODO: Implement! - return B_NOT_SUPPORTED; + AutoLocker _(fNodes); + + // check whether we do already know the node + HaikuKernelNode* node = fNodes->Get(vnodeID); + if (node != NULL) { + if (node->published) + return B_BAD_VALUE; + } else { + // create a new node + node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, + ops); + if (node == NULL) + return B_NO_MEMORY; + + // add to map + status_t error = fNodes->Put(vnodeID, node); + if (error != B_OK) { + delete node; + return error; + } + } + + node->published = true; + + *_node = node; + + return B_OK; } // UndoNewVNode -status_t +void HaikuKernelVolume::UndoNewVNode(HaikuKernelNode* node) { - // TODO: Implement! - return B_NOT_SUPPORTED; + fNodes->Remove(node->id); + delete node; } // UndoPublishVNode -status_t +void HaikuKernelVolume::UndoPublishVNode(HaikuKernelNode* node) { - // TODO: Implement! - return B_NOT_SUPPORTED; + fNodes->Remove(node->id); + delete node; } @@ -189,21 +257,37 @@ HaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type, if (!fVolume.ops->get_vnode) return B_BAD_VALUE; - // create a new wrapper node - HaikuKernelNode* node = new(std::nothrow) HaikuKernelNode; + // create a new wrapper node and add it to the map + HaikuKernelNode* node = new(std::nothrow) HaikuKernelNode(this, vnid, NULL, + NULL); if (node == NULL) return B_NO_MEMORY; - node->volume = this; + ObjectDeleter nodeDeleter(node); + + AutoLocker locker(fNodes); + if (fNodes->Get(vnid) != NULL) + return B_BAD_VALUE; + + status_t error = fNodes->Put(vnid, node); + if (error != B_OK) + return error; + + locker.Unlock(); // get the node - status_t error = fVolume.ops->get_vnode(&fVolume, vnid, node, type, flags, - reenter); + error = fVolume.ops->get_vnode(&fVolume, vnid, node, type, flags, reenter); if (error != B_OK) { - delete node; + locker.Lock(); + fNodes->Remove(vnid); return error; } + locker.Lock(); + node->published = true; + nodeDeleter.Detach(); + *_node = node; + return B_OK; } @@ -213,6 +297,8 @@ HaikuKernelVolume::WriteVNode(void* _node, bool reenter) { HaikuKernelNode* node = (HaikuKernelNode*)_node; + fNodes->Remove(node->id); + if (!node->ops->put_vnode) return B_BAD_VALUE; status_t error = node->ops->put_vnode(&fVolume, node, reenter); @@ -228,6 +314,8 @@ HaikuKernelVolume::RemoveVNode(void* _node, bool reenter) { HaikuKernelNode* node = (HaikuKernelNode*)_node; + fNodes->Remove(node->id); + if (!node->ops->remove_vnode) return B_BAD_VALUE; return node->ops->remove_vnode(&fVolume, node, reenter); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h index 0812f9cc02..8ba21e0c9e 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h @@ -23,13 +23,15 @@ public: inline fs_volume* GetFSVolume() { return &fVolume; } + status_t Init(); + status_t NewVNode(ino_t vnodeID, void* privateNode, fs_vnode_ops* ops, HaikuKernelNode** node); status_t PublishVNode(ino_t vnodeID, void* privateNode, fs_vnode_ops* ops, int type, uint32 flags, HaikuKernelNode** node); - status_t UndoNewVNode(HaikuKernelNode* node); - status_t UndoPublishVNode(HaikuKernelNode* node); + void UndoNewVNode(HaikuKernelNode* node); + void UndoPublishVNode(HaikuKernelNode* node); // FS virtual status_t Mount(const char* device, uint32 flags, @@ -173,12 +175,15 @@ private: HaikuKernelVolume* haikuVolume; }; + class NodeMap; + private: void _InitCapabilities(); private: file_system_module_info* fFSModule; FSVolume fVolume; + NodeMap* fNodes; };