From 6747f715cffc13e8effe4cd87a892bfc85e540e8 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 16 Mar 2009 03:21:04 +0000 Subject: [PATCH] ReadVNode(): We need to create the VNode object before sending the request to userland, since typically the file cache for the node is created there and our FileCacheCreate() method requires and existing VNode object. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29554 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../userlandfs/kernel_add_on/Volume.cpp | 59 +++++++++++++++---- .../userlandfs/kernel_add_on/Volume.h | 1 + 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp index 5ffbe7fecf..b8e77749d2 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp @@ -51,13 +51,15 @@ struct Volume::VNode : HashTableLink { void* clientNode; void* fileCache; int32 useCount; + bool valid; VNode(ino_t id, void* clientNode) : id(id), clientNode(clientNode), fileCache(NULL), - useCount(0) + useCount(0), + valid(true) { } @@ -955,27 +957,36 @@ Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type, request->vnid = vnid; request->reenter = reenter; + // add the uninitialized node to our map + VNode* vnode = new(std::nothrow) VNode(vnid, NULL); + if (vnode == NULL) + RETURN_ERROR(B_NO_MEMORY); + vnode->valid = false; + + MutexLocker locker(fLock); + fVNodes->Insert(vnode); + locker.Unlock(); + // send the request KernelRequestHandler handler(this, READ_VNODE_REPLY); ReadVNodeReply* reply; error = _SendRequest(port, &allocator, &handler, (Request**)&reply); - if (error != B_OK) + if (error != B_OK) { + _RemoveInvalidVNode(vnid); return error; + } RequestReleaser requestReleaser(port, reply); // process the reply - if (reply->error != B_OK) + if (reply->error != B_OK) { + _RemoveInvalidVNode(vnid); return reply->error; - - // everything went fine so far -- add the node to our map - VNode* vnode = new(std::nothrow) VNode(vnid, reply->node); - if (vnode == NULL) { - WriteVNode(reply->node, reenter); - RETURN_ERROR(B_NO_MEMORY); } - MutexLocker lock(fLock); - fVNodes->Insert(vnode); + // everything went fine -- mark the node valid + locker.Lock(); + vnode->clientNode = reply->node; + vnode->valid = true; *_node = vnode; *type = reply->type; @@ -4227,6 +4238,7 @@ Volume::_IncrementVNodeCount(ino_t vnid) //PRINT(("_IncrementVNodeCount(%Ld): count: %ld, fVNodeCountMap size: %ld\n", vnid, *count, fVNodeCountMap->Size())); } + // _DecrementVNodeCount void Volume::_DecrementVNodeCount(ino_t vnid) @@ -4247,6 +4259,31 @@ Volume::_DecrementVNodeCount(ino_t vnid) //PRINT(("_DecrementVNodeCount(%Ld): count: %ld, fVNodeCountMap size: %ld\n", vnid, tmpCount, fVNodeCountMap->Size())); } + +// _RemoveInvalidVNode +void +Volume::_RemoveInvalidVNode(ino_t vnid) +{ + MutexLocker locker(fLock); + + VNode* vnode = fVNodes->Lookup(vnid); + if (vnode == NULL) { + ERROR(("Volume::_RemoveInvalidVNode(): Node with ID %lld not known!\n", + vnid)); + return; + } + + fVNodes->Remove(vnode); + locker.Unlock(); + + // release all references acquired so far + for (; vnode->useCount > 0; vnode->useCount--) + put_vnode(fFSVolume, vnid); + + delete vnode; +} + + // _InternalIOCtl status_t Volume::_InternalIOCtl(userlandfs_ioctl* buffer, int32 bufferSize) diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h index 7bf920de03..2bccfb8a4a 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h @@ -257,6 +257,7 @@ private: void _IncrementVNodeCount(ino_t vnid); void _DecrementVNodeCount(ino_t vnid); + void _RemoveInvalidVNode(ino_t vnid); status_t _InternalIOCtl(userlandfs_ioctl* buffer, int32 bufferSize);