xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/ClientVolume.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
15a1d355fSStephan Aßmus // ClientVolume.cpp
25a1d355fSStephan Aßmus 
35a1d355fSStephan Aßmus #include <new>
45a1d355fSStephan Aßmus 
55a1d355fSStephan Aßmus #include <AutoDeleter.h>
65a1d355fSStephan Aßmus #include <AutoLocker.h>
75a1d355fSStephan Aßmus #include <HashMap.h>
85a1d355fSStephan Aßmus #include <Path.h>
95a1d355fSStephan Aßmus 
105a1d355fSStephan Aßmus #include "ClientVolume.h"
115a1d355fSStephan Aßmus #include "DebugSupport.h"
125a1d355fSStephan Aßmus #include "Directory.h"
135a1d355fSStephan Aßmus #include "Entry.h"
145a1d355fSStephan Aßmus #include "GlobalBlockerPool.h"
155a1d355fSStephan Aßmus #include "NodeHandle.h"
165a1d355fSStephan Aßmus #include "NodeHandleMap.h"
175a1d355fSStephan Aßmus #include "NodeMonitoringEvent.h"
185a1d355fSStephan Aßmus #include "SecurityContext.h"
195a1d355fSStephan Aßmus #include "StatisticsManager.h"
205a1d355fSStephan Aßmus #include "UserSecurityContext.h"
215a1d355fSStephan Aßmus #include "Volume.h"
225a1d355fSStephan Aßmus #include "VolumeManager.h"
235a1d355fSStephan Aßmus 
245a1d355fSStephan Aßmus // constructor
ClientVolume(Locker & securityContextLocker,NodeMonitoringProcessor * nodeMonitoringProcessor)255a1d355fSStephan Aßmus ClientVolume::ClientVolume(Locker& securityContextLocker,
265a1d355fSStephan Aßmus 	NodeMonitoringProcessor* nodeMonitoringProcessor)
275a1d355fSStephan Aßmus 	: FSObject(),
285a1d355fSStephan Aßmus 	  fID(_NextVolumeID()),
295a1d355fSStephan Aßmus 	  fSecurityContext(NULL),
305a1d355fSStephan Aßmus 	  fSecurityContextLock(securityContextLocker),
315a1d355fSStephan Aßmus 	  fNodeMonitoringProcessor(nodeMonitoringProcessor),
325a1d355fSStephan Aßmus 	  fNodeHandles(NULL),
335a1d355fSStephan Aßmus 	  fShare(NULL),
345a1d355fSStephan Aßmus 	  fRootNodeRef(),
355a1d355fSStephan Aßmus 	  fSharePermissions(),
365a1d355fSStephan Aßmus 	  fMounted(false)
375a1d355fSStephan Aßmus {
385a1d355fSStephan Aßmus }
395a1d355fSStephan Aßmus 
405a1d355fSStephan Aßmus // destructor
~ClientVolume()415a1d355fSStephan Aßmus ClientVolume::~ClientVolume()
425a1d355fSStephan Aßmus {
435a1d355fSStephan Aßmus 	Unmount();
445a1d355fSStephan Aßmus 
455a1d355fSStephan Aßmus 	if (fShare)
4688e38c17SIngo Weinhold 		fShare->ReleaseReference();
475a1d355fSStephan Aßmus 
485a1d355fSStephan Aßmus 	delete fNodeHandles;
495a1d355fSStephan Aßmus 	delete fSecurityContext;
505a1d355fSStephan Aßmus }
515a1d355fSStephan Aßmus 
525a1d355fSStephan Aßmus // Init
535a1d355fSStephan Aßmus status_t
Init()545a1d355fSStephan Aßmus ClientVolume::Init()
555a1d355fSStephan Aßmus {
565a1d355fSStephan Aßmus 	// create the node handle map
575a1d355fSStephan Aßmus 	fNodeHandles = new(std::nothrow) NodeHandleMap("node handles");
585a1d355fSStephan Aßmus 	if (!fNodeHandles)
595a1d355fSStephan Aßmus 		return B_NO_MEMORY;
605a1d355fSStephan Aßmus 	status_t error = fNodeHandles->Init();
615a1d355fSStephan Aßmus 	if (error != B_OK)
625a1d355fSStephan Aßmus 		return error;
635a1d355fSStephan Aßmus 
645a1d355fSStephan Aßmus 	return B_OK;
655a1d355fSStephan Aßmus }
665a1d355fSStephan Aßmus 
675a1d355fSStephan Aßmus // GetID
685a1d355fSStephan Aßmus int32
GetID() const695a1d355fSStephan Aßmus ClientVolume::GetID() const
705a1d355fSStephan Aßmus {
715a1d355fSStephan Aßmus 	return fID;
725a1d355fSStephan Aßmus }
735a1d355fSStephan Aßmus 
745a1d355fSStephan Aßmus // Mount
755a1d355fSStephan Aßmus status_t
Mount(UserSecurityContext * securityContext,Share * share)765a1d355fSStephan Aßmus ClientVolume::Mount(UserSecurityContext* securityContext, Share* share)
775a1d355fSStephan Aßmus {
785a1d355fSStephan Aßmus 	if (!securityContext || !share)
795a1d355fSStephan Aßmus 		return B_BAD_VALUE;
805a1d355fSStephan Aßmus 	ObjectDeleter<UserSecurityContext> securityContextDeleter(securityContext);
815a1d355fSStephan Aßmus 	if (IsMounted())
825a1d355fSStephan Aßmus 		return B_BAD_VALUE;
835a1d355fSStephan Aßmus 	fSecurityContext = securityContext;
845a1d355fSStephan Aßmus 	securityContextDeleter.Detach();
855a1d355fSStephan Aßmus 
865a1d355fSStephan Aßmus 	fShare = share;
8788e38c17SIngo Weinhold 	fShare->AcquireReference();
885a1d355fSStephan Aßmus 	dev_t volumeID = share->GetVolumeID();
895a1d355fSStephan Aßmus 	ino_t nodeID = share->GetNodeID();
905a1d355fSStephan Aßmus 
915a1d355fSStephan Aßmus 	// into root node ref
925a1d355fSStephan Aßmus 	fRootNodeRef.device = volumeID;
935a1d355fSStephan Aßmus 	fRootNodeRef.node = nodeID;
945a1d355fSStephan Aßmus 
955a1d355fSStephan Aßmus 	// get the share permissions
965a1d355fSStephan Aßmus 	fSharePermissions = securityContext->GetNodePermissions(volumeID, nodeID);
975a1d355fSStephan Aßmus 
985a1d355fSStephan Aßmus 	// get the root directory
995a1d355fSStephan Aßmus 	VolumeManager* volumeManager = VolumeManager::GetDefault();
1005a1d355fSStephan Aßmus 	Directory* rootDir;
1015a1d355fSStephan Aßmus 	status_t error = volumeManager->LoadDirectory(volumeID, nodeID, &rootDir);
1025a1d355fSStephan Aßmus 	if (error != B_OK)
1035a1d355fSStephan Aßmus 		return error;
1045a1d355fSStephan Aßmus 
1055a1d355fSStephan Aßmus 	// register with the volume manager
1065a1d355fSStephan Aßmus 	error = volumeManager->AddClientVolume(this);
1075a1d355fSStephan Aßmus 	if (error != B_OK) {
1085a1d355fSStephan Aßmus 		Unmount();
1095a1d355fSStephan Aßmus 		return error;
1105a1d355fSStephan Aßmus 	}
1115a1d355fSStephan Aßmus 	fMounted = true;
1125a1d355fSStephan Aßmus 
1135a1d355fSStephan Aßmus 	// notify the statistics manager
1145a1d355fSStephan Aßmus 	StatisticsManager::GetDefault()->ShareMounted(fShare,
1155a1d355fSStephan Aßmus 		fSecurityContext->GetUser());
1165a1d355fSStephan Aßmus 
1175a1d355fSStephan Aßmus 	return B_OK;
1185a1d355fSStephan Aßmus }
1195a1d355fSStephan Aßmus 
1205a1d355fSStephan Aßmus // Unmount
1215a1d355fSStephan Aßmus void
Unmount()1225a1d355fSStephan Aßmus ClientVolume::Unmount()
1235a1d355fSStephan Aßmus {
1245a1d355fSStephan Aßmus 	PRINT(("ClientVolume::Unmount()\n"));
1255a1d355fSStephan Aßmus 
1265a1d355fSStephan Aßmus 	if (fMounted) {
1275a1d355fSStephan Aßmus 		fMounted = false;
1285a1d355fSStephan Aßmus 
1295a1d355fSStephan Aßmus 		// notify the statistics manager
1305a1d355fSStephan Aßmus 		StatisticsManager::GetDefault()->ShareUnmounted(fShare,
1315a1d355fSStephan Aßmus 			fSecurityContext->GetUser());
1325a1d355fSStephan Aßmus 	}
1335a1d355fSStephan Aßmus 
1345a1d355fSStephan Aßmus 	// remove ourselves from the volume manager
1355a1d355fSStephan Aßmus 	VolumeManager::GetDefault()->RemoveClientVolume(this);
1365a1d355fSStephan Aßmus 
1375a1d355fSStephan Aßmus 	// close all node handles
1385a1d355fSStephan Aßmus //	while (true) {
1395a1d355fSStephan Aßmus //		// get a cookie
1405a1d355fSStephan Aßmus //		int32 cookie;
1415a1d355fSStephan Aßmus //		{
1425a1d355fSStephan Aßmus //			NodeHandleMap::Iterator it = fNodeHandles->GetIterator();
1435a1d355fSStephan Aßmus //			if (!it.HasNext())
1445a1d355fSStephan Aßmus //				break;
1455a1d355fSStephan Aßmus //			cookie = it.Next().key.value;
1465a1d355fSStephan Aßmus //		}
1475a1d355fSStephan Aßmus //
1485a1d355fSStephan Aßmus //		// get the handle
1495a1d355fSStephan Aßmus //		NodeHandle* handle;
1505a1d355fSStephan Aßmus //		status_t error = LockNodeHandle(cookie, &handle);
1515a1d355fSStephan Aßmus //		if (error == B_OK) {
1525a1d355fSStephan Aßmus //			// close the node handle
1535a1d355fSStephan Aßmus //			ClientNodeUnlocker _(handle->GetClientNode());
1545a1d355fSStephan Aßmus //			Close(handle);
1555a1d355fSStephan Aßmus //		} else {
1565a1d355fSStephan Aßmus //			ClientVolumeLocker _(this);
1575a1d355fSStephan Aßmus //			if (fNodeHandles->ContainsKey(cookie)) {
1585a1d355fSStephan Aßmus //				// something went seriously wrong
1595a1d355fSStephan Aßmus //				ERROR(("ClientVolume::Unmount(): ERROR: Failed to lock "
1605a1d355fSStephan Aßmus //					"existing node handle! Can't continue Unmount().\n"));
1615a1d355fSStephan Aßmus //				return;
1625a1d355fSStephan Aßmus //			}
1635a1d355fSStephan Aßmus //		}
1645a1d355fSStephan Aßmus //	}
1655a1d355fSStephan Aßmus }
1665a1d355fSStephan Aßmus 
1675a1d355fSStephan Aßmus 
1685a1d355fSStephan Aßmus // IsMounted
1695a1d355fSStephan Aßmus bool
IsMounted() const1705a1d355fSStephan Aßmus ClientVolume::IsMounted() const
1715a1d355fSStephan Aßmus {
1725a1d355fSStephan Aßmus 	return fMounted;
1735a1d355fSStephan Aßmus }
1745a1d355fSStephan Aßmus 
1755a1d355fSStephan Aßmus // GetSecurityContext
1765a1d355fSStephan Aßmus //
1775a1d355fSStephan Aßmus // Caller must hold fSecurityContextLock. Only the ClientConnection should
1785a1d355fSStephan Aßmus // do this.
1795a1d355fSStephan Aßmus UserSecurityContext*
GetSecurityContext() const1805a1d355fSStephan Aßmus ClientVolume::GetSecurityContext() const
1815a1d355fSStephan Aßmus {
1825a1d355fSStephan Aßmus 	return fSecurityContext;
1835a1d355fSStephan Aßmus }
1845a1d355fSStephan Aßmus 
1855a1d355fSStephan Aßmus // SetSecurityContext
1865a1d355fSStephan Aßmus void
SetSecurityContext(UserSecurityContext * securityContext)1875a1d355fSStephan Aßmus ClientVolume::SetSecurityContext(UserSecurityContext* securityContext)
1885a1d355fSStephan Aßmus {
1895a1d355fSStephan Aßmus 	AutoLocker<Locker> locker(fSecurityContextLock);
1905a1d355fSStephan Aßmus 
1915a1d355fSStephan Aßmus 	// unset old
1925a1d355fSStephan Aßmus 	delete fSecurityContext;
1935a1d355fSStephan Aßmus 
1945a1d355fSStephan Aßmus 	// set new
1955a1d355fSStephan Aßmus 	fSecurityContext = securityContext;
1965a1d355fSStephan Aßmus 	fSharePermissions = fSecurityContext->GetNodePermissions(fRootNodeRef);
1975a1d355fSStephan Aßmus }
1985a1d355fSStephan Aßmus 
1995a1d355fSStephan Aßmus // GetShare
2005a1d355fSStephan Aßmus Share*
GetShare() const2015a1d355fSStephan Aßmus ClientVolume::GetShare() const
2025a1d355fSStephan Aßmus {
2035a1d355fSStephan Aßmus 	return fShare;
2045a1d355fSStephan Aßmus }
2055a1d355fSStephan Aßmus 
2065a1d355fSStephan Aßmus // GetRootDirectory
2075a1d355fSStephan Aßmus Directory*
GetRootDirectory() const2085a1d355fSStephan Aßmus ClientVolume::GetRootDirectory() const
2095a1d355fSStephan Aßmus {
2105a1d355fSStephan Aßmus 	return VolumeManager::GetDefault()->GetDirectory(
2115a1d355fSStephan Aßmus 		fRootNodeRef.device, fRootNodeRef.node);
2125a1d355fSStephan Aßmus }
2135a1d355fSStephan Aßmus 
2145a1d355fSStephan Aßmus // GetRootNodeRef
2155a1d355fSStephan Aßmus const NodeRef&
GetRootNodeRef() const2165a1d355fSStephan Aßmus ClientVolume::GetRootNodeRef() const
2175a1d355fSStephan Aßmus {
2185a1d355fSStephan Aßmus 	return fRootNodeRef;
2195a1d355fSStephan Aßmus }
2205a1d355fSStephan Aßmus 
2215a1d355fSStephan Aßmus // GetSharePermissions
2225a1d355fSStephan Aßmus Permissions
GetSharePermissions() const2235a1d355fSStephan Aßmus ClientVolume::GetSharePermissions() const
2245a1d355fSStephan Aßmus {
2255a1d355fSStephan Aßmus 	return fSharePermissions;
2265a1d355fSStephan Aßmus }
2275a1d355fSStephan Aßmus 
2285a1d355fSStephan Aßmus // GetNodePermissions
2295a1d355fSStephan Aßmus Permissions
GetNodePermissions(dev_t volumeID,ino_t nodeID)2305a1d355fSStephan Aßmus ClientVolume::GetNodePermissions(dev_t volumeID, ino_t nodeID)
2315a1d355fSStephan Aßmus {
2325a1d355fSStephan Aßmus 	return fSharePermissions;
2335a1d355fSStephan Aßmus }
2345a1d355fSStephan Aßmus 
2355a1d355fSStephan Aßmus // GetNodePermissions
2365a1d355fSStephan Aßmus Permissions
GetNodePermissions(Node * node)2375a1d355fSStephan Aßmus ClientVolume::GetNodePermissions(Node* node)
2385a1d355fSStephan Aßmus {
2395a1d355fSStephan Aßmus // TODO: We should also check whether the node is located on the client volume
2405a1d355fSStephan Aßmus // in the first place. Otherwise someone with access to a low-security share
2415a1d355fSStephan Aßmus // could get access to arbitrary nodes on the server.
2425a1d355fSStephan Aßmus 	return fSharePermissions;
2435a1d355fSStephan Aßmus }
2445a1d355fSStephan Aßmus 
2455a1d355fSStephan Aßmus // GetNode
2465a1d355fSStephan Aßmus Node*
GetNode(dev_t volumeID,ino_t nodeID)2475a1d355fSStephan Aßmus ClientVolume::GetNode(dev_t volumeID, ino_t nodeID)
2485a1d355fSStephan Aßmus {
2495a1d355fSStephan Aßmus 	VolumeManager* volumeManager = VolumeManager::GetDefault();
2505a1d355fSStephan Aßmus 
2515a1d355fSStephan Aßmus 	// get the node
2525a1d355fSStephan Aßmus 	Node* node = volumeManager->GetNode(volumeID, nodeID);
2535a1d355fSStephan Aßmus 	if (!node)
2545a1d355fSStephan Aßmus 		return NULL;
2555a1d355fSStephan Aßmus 
2565a1d355fSStephan Aßmus 	// check, if the node is contained by the root dir of the client volume
2575a1d355fSStephan Aßmus 	if (volumeManager->DirectoryContains(GetRootDirectory(), node, true))
2585a1d355fSStephan Aßmus 		return node;
2595a1d355fSStephan Aßmus 
2605a1d355fSStephan Aßmus 	return NULL;
2615a1d355fSStephan Aßmus }
2625a1d355fSStephan Aßmus 
2635a1d355fSStephan Aßmus // GetNode
2645a1d355fSStephan Aßmus Node*
GetNode(NodeID nodeID)2655a1d355fSStephan Aßmus ClientVolume::GetNode(NodeID nodeID)
2665a1d355fSStephan Aßmus {
2675a1d355fSStephan Aßmus 	return GetNode(nodeID.volumeID, nodeID.nodeID);
2685a1d355fSStephan Aßmus }
2695a1d355fSStephan Aßmus 
2705a1d355fSStephan Aßmus // GetNode
2715a1d355fSStephan Aßmus Node*
GetNode(const node_ref & nodeRef)2725a1d355fSStephan Aßmus ClientVolume::GetNode(const node_ref& nodeRef)
2735a1d355fSStephan Aßmus {
2745a1d355fSStephan Aßmus 	return GetNode(nodeRef.device, nodeRef.node);
2755a1d355fSStephan Aßmus }
2765a1d355fSStephan Aßmus 
2775a1d355fSStephan Aßmus // GetDirectory
2785a1d355fSStephan Aßmus Directory*
GetDirectory(dev_t volumeID,ino_t nodeID)2795a1d355fSStephan Aßmus ClientVolume::GetDirectory(dev_t volumeID, ino_t nodeID)
2805a1d355fSStephan Aßmus {
2815a1d355fSStephan Aßmus 	VolumeManager* volumeManager = VolumeManager::GetDefault();
2825a1d355fSStephan Aßmus 
2835a1d355fSStephan Aßmus 	// get the directory
2845a1d355fSStephan Aßmus 	Directory* dir = GetDirectory(volumeID, nodeID);
2855a1d355fSStephan Aßmus 	if (!dir)
2865a1d355fSStephan Aßmus 		return NULL;
2875a1d355fSStephan Aßmus 
2885a1d355fSStephan Aßmus 	// check, if the dir is contained by the root dir of the client volume
2895a1d355fSStephan Aßmus 	if (volumeManager->DirectoryContains(GetRootDirectory(), dir, true))
2905a1d355fSStephan Aßmus 		return dir;
2915a1d355fSStephan Aßmus 
2925a1d355fSStephan Aßmus 	return NULL;
2935a1d355fSStephan Aßmus }
2945a1d355fSStephan Aßmus 
2955a1d355fSStephan Aßmus // GetDirectory
2965a1d355fSStephan Aßmus Directory*
GetDirectory(NodeID nodeID)2975a1d355fSStephan Aßmus ClientVolume::GetDirectory(NodeID nodeID)
2985a1d355fSStephan Aßmus {
2995a1d355fSStephan Aßmus 	return GetDirectory(nodeID.volumeID, nodeID.nodeID);
3005a1d355fSStephan Aßmus }
3015a1d355fSStephan Aßmus 
3025a1d355fSStephan Aßmus // LoadDirectory
3035a1d355fSStephan Aßmus status_t
LoadDirectory(dev_t volumeID,ino_t nodeID,Directory ** _directory)3045a1d355fSStephan Aßmus ClientVolume::LoadDirectory(dev_t volumeID, ino_t nodeID,
3055a1d355fSStephan Aßmus 	Directory** _directory)
3065a1d355fSStephan Aßmus {
3075a1d355fSStephan Aßmus 	if (!_directory)
3085a1d355fSStephan Aßmus 		return B_BAD_VALUE;
3095a1d355fSStephan Aßmus 
3105a1d355fSStephan Aßmus 	VolumeManager* volumeManager = VolumeManager::GetDefault();
3115a1d355fSStephan Aßmus 
3125a1d355fSStephan Aßmus 	// load the directory
3135a1d355fSStephan Aßmus 	Directory* dir;
3145a1d355fSStephan Aßmus 	status_t error = volumeManager->LoadDirectory(volumeID, nodeID, &dir);
3155a1d355fSStephan Aßmus 	if (error != B_OK)
3165a1d355fSStephan Aßmus 		return error;
3175a1d355fSStephan Aßmus 
3185a1d355fSStephan Aßmus 	// check, if the dir is contained by the root dir of the client volume
3195a1d355fSStephan Aßmus 	if (!volumeManager->DirectoryContains(GetRootDirectory(), dir, true))
3205a1d355fSStephan Aßmus 		return B_ENTRY_NOT_FOUND;
3215a1d355fSStephan Aßmus 
3225a1d355fSStephan Aßmus 	*_directory = dir;
3235a1d355fSStephan Aßmus 	return B_OK;
3245a1d355fSStephan Aßmus }
3255a1d355fSStephan Aßmus 
3265a1d355fSStephan Aßmus // GetEntry
3275a1d355fSStephan Aßmus Entry*
GetEntry(dev_t volumeID,ino_t dirID,const char * name)3285a1d355fSStephan Aßmus ClientVolume::GetEntry(dev_t volumeID, ino_t dirID, const char* name)
3295a1d355fSStephan Aßmus {
3305a1d355fSStephan Aßmus 	VolumeManager* volumeManager = VolumeManager::GetDefault();
3315a1d355fSStephan Aßmus 
3325a1d355fSStephan Aßmus 	// get the entry
3335a1d355fSStephan Aßmus 	Entry* entry = volumeManager->GetEntry(volumeID, dirID, name);
3345a1d355fSStephan Aßmus 	if (!entry)
3355a1d355fSStephan Aßmus 		return NULL;
3365a1d355fSStephan Aßmus 
3375a1d355fSStephan Aßmus 	// check, if the entry is contained by the root dir of the client volume
3385a1d355fSStephan Aßmus 	if (volumeManager->DirectoryContains(GetRootDirectory(), entry))
3395a1d355fSStephan Aßmus 		return entry;
3405a1d355fSStephan Aßmus 
3415a1d355fSStephan Aßmus 	return NULL;
3425a1d355fSStephan Aßmus }
3435a1d355fSStephan Aßmus 
3445a1d355fSStephan Aßmus // GetEntry
3455a1d355fSStephan Aßmus Entry*
GetEntry(Directory * directory,const char * name)3465a1d355fSStephan Aßmus ClientVolume::GetEntry(Directory* directory, const char* name)
3475a1d355fSStephan Aßmus {
3485a1d355fSStephan Aßmus 	if (!directory)
3495a1d355fSStephan Aßmus 		return NULL;
3505a1d355fSStephan Aßmus 
3515a1d355fSStephan Aßmus 	return GetEntry(directory->GetVolumeID(), directory->GetID(), name);
3525a1d355fSStephan Aßmus }
3535a1d355fSStephan Aßmus 
3545a1d355fSStephan Aßmus // LoadEntry
3555a1d355fSStephan Aßmus status_t
LoadEntry(dev_t volumeID,ino_t dirID,const char * name,Entry ** _entry)3565a1d355fSStephan Aßmus ClientVolume::LoadEntry(dev_t volumeID, ino_t dirID, const char* name,
3575a1d355fSStephan Aßmus 	Entry** _entry)
3585a1d355fSStephan Aßmus {
3595a1d355fSStephan Aßmus 	if (!name || !_entry)
3605a1d355fSStephan Aßmus 		return B_BAD_VALUE;
3615a1d355fSStephan Aßmus 
3625a1d355fSStephan Aßmus 	VolumeManager* volumeManager = VolumeManager::GetDefault();
3635a1d355fSStephan Aßmus 
3645a1d355fSStephan Aßmus 	// get the entry
3655a1d355fSStephan Aßmus 	Entry* entry;
3665a1d355fSStephan Aßmus 	status_t error = VolumeManager::GetDefault()->LoadEntry(volumeID, dirID,
3675a1d355fSStephan Aßmus 		name, true, &entry);
3685a1d355fSStephan Aßmus 	if (error != B_OK)
3695a1d355fSStephan Aßmus 		return error;
3705a1d355fSStephan Aßmus 
3715a1d355fSStephan Aßmus 	// check, if the entry is contained by the root dir of the client volume
3725a1d355fSStephan Aßmus 	if (!volumeManager->DirectoryContains(GetRootDirectory(), entry))
3735a1d355fSStephan Aßmus 		return B_ENTRY_NOT_FOUND;
3745a1d355fSStephan Aßmus 
3755a1d355fSStephan Aßmus 	*_entry = entry;
3765a1d355fSStephan Aßmus 	return B_OK;
3775a1d355fSStephan Aßmus }
3785a1d355fSStephan Aßmus 
3795a1d355fSStephan Aßmus // LoadEntry
3805a1d355fSStephan Aßmus status_t
LoadEntry(Directory * directory,const char * name,Entry ** entry)3815a1d355fSStephan Aßmus ClientVolume::LoadEntry(Directory* directory, const char* name, Entry** entry)
3825a1d355fSStephan Aßmus {
3835a1d355fSStephan Aßmus 	if (!directory)
3845a1d355fSStephan Aßmus 		return B_BAD_VALUE;
3855a1d355fSStephan Aßmus 
3865a1d355fSStephan Aßmus 	return LoadEntry(directory->GetVolumeID(), directory->GetID(), name, entry);
3875a1d355fSStephan Aßmus }
3885a1d355fSStephan Aßmus 
3895a1d355fSStephan Aßmus // Open
3905a1d355fSStephan Aßmus //
3915a1d355fSStephan Aßmus // The caller gets a lock to the returned node handle.
3925a1d355fSStephan Aßmus status_t
Open(Node * node,int openMode,FileHandle ** _handle)3935a1d355fSStephan Aßmus ClientVolume::Open(Node* node, int openMode, FileHandle** _handle)
3945a1d355fSStephan Aßmus {
3955a1d355fSStephan Aßmus 	if (!node || !_handle)
3965a1d355fSStephan Aßmus 		return B_BAD_VALUE;
3975a1d355fSStephan Aßmus 
3985a1d355fSStephan Aßmus 	// open the node
3995a1d355fSStephan Aßmus 	FileHandle* handle = NULL;
4005a1d355fSStephan Aßmus 	status_t error = node->Open(openMode, &handle);
4015a1d355fSStephan Aßmus 	if (error != B_OK)
4025a1d355fSStephan Aßmus 		return error;
40388e38c17SIngo Weinhold 	BReference<NodeHandle> handleReference(handle, true);
4045a1d355fSStephan Aßmus 
4055a1d355fSStephan Aßmus 	// lock the handle
4065a1d355fSStephan Aßmus 	handle->Lock();
4075a1d355fSStephan Aßmus 
4085a1d355fSStephan Aßmus 	// add the handle
4095a1d355fSStephan Aßmus 	error = fNodeHandles->AddNodeHandle(handle);
4105a1d355fSStephan Aßmus 	if (error != B_OK)
4115a1d355fSStephan Aßmus 		return error;
4125a1d355fSStephan Aßmus 
4135a1d355fSStephan Aßmus 	handleReference.Detach();
4145a1d355fSStephan Aßmus 	*_handle = handle;
4155a1d355fSStephan Aßmus 	return B_OK;
4165a1d355fSStephan Aßmus }
4175a1d355fSStephan Aßmus 
4185a1d355fSStephan Aßmus // OpenDir
4195a1d355fSStephan Aßmus //
4205a1d355fSStephan Aßmus // The caller gets a lock to the returned node handle.
4215a1d355fSStephan Aßmus status_t
OpenDir(Directory * directory,DirIterator ** _iterator)4225a1d355fSStephan Aßmus ClientVolume::OpenDir(Directory* directory, DirIterator** _iterator)
4235a1d355fSStephan Aßmus {
4245a1d355fSStephan Aßmus 	if (!directory || !_iterator)
4255a1d355fSStephan Aßmus 		return B_BAD_VALUE;
4265a1d355fSStephan Aßmus 
4275a1d355fSStephan Aßmus 	// open the directory
4285a1d355fSStephan Aßmus 	DirIterator* iterator = NULL;
4295a1d355fSStephan Aßmus 	status_t error = directory->OpenDir(&iterator);
4305a1d355fSStephan Aßmus 	if (error != B_OK)
4315a1d355fSStephan Aßmus 		return error;
43288e38c17SIngo Weinhold 	BReference<NodeHandle> handleReference(iterator, true);
4335a1d355fSStephan Aßmus 
4345a1d355fSStephan Aßmus 	// lock the handle
4355a1d355fSStephan Aßmus 	iterator->Lock();
4365a1d355fSStephan Aßmus 
4375a1d355fSStephan Aßmus 	// add the handle
4385a1d355fSStephan Aßmus 	error = fNodeHandles->AddNodeHandle(iterator);
4395a1d355fSStephan Aßmus 	if (error != B_OK)
4405a1d355fSStephan Aßmus 		return error;
4415a1d355fSStephan Aßmus 
4425a1d355fSStephan Aßmus 	handleReference.Detach();
4435a1d355fSStephan Aßmus 	*_iterator = iterator;
4445a1d355fSStephan Aßmus 	return B_OK;
4455a1d355fSStephan Aßmus }
4465a1d355fSStephan Aßmus 
4475a1d355fSStephan Aßmus // OpenAttrDir
4485a1d355fSStephan Aßmus //
4495a1d355fSStephan Aßmus // The caller gets a lock to the returned node handle.
4505a1d355fSStephan Aßmus status_t
OpenAttrDir(Node * node,AttrDirIterator ** _iterator)4515a1d355fSStephan Aßmus ClientVolume::OpenAttrDir(Node* node, AttrDirIterator** _iterator)
4525a1d355fSStephan Aßmus {
4535a1d355fSStephan Aßmus 	if (!node || !_iterator)
4545a1d355fSStephan Aßmus 		return B_BAD_VALUE;
4555a1d355fSStephan Aßmus 
4565a1d355fSStephan Aßmus 	// open the attribut directory
4575a1d355fSStephan Aßmus 	AttrDirIterator* iterator = NULL;
4585a1d355fSStephan Aßmus 	status_t error = node->OpenAttrDir(&iterator);
4595a1d355fSStephan Aßmus 	if (error != B_OK)
4605a1d355fSStephan Aßmus 		return error;
46188e38c17SIngo Weinhold 	BReference<NodeHandle> handleReference(iterator, true);
4625a1d355fSStephan Aßmus 
4635a1d355fSStephan Aßmus 	// lock the handle
4645a1d355fSStephan Aßmus 	iterator->Lock();
4655a1d355fSStephan Aßmus 
4665a1d355fSStephan Aßmus 	// add the handle
4675a1d355fSStephan Aßmus 	error = fNodeHandles->AddNodeHandle(iterator);
4685a1d355fSStephan Aßmus 	if (error != B_OK)
4695a1d355fSStephan Aßmus 		return error;
4705a1d355fSStephan Aßmus 
4715a1d355fSStephan Aßmus 	handleReference.Detach();
4725a1d355fSStephan Aßmus 	*_iterator = iterator;
4735a1d355fSStephan Aßmus 	return B_OK;
4745a1d355fSStephan Aßmus }
4755a1d355fSStephan Aßmus 
4765a1d355fSStephan Aßmus // Close
4775a1d355fSStephan Aßmus //
4785a1d355fSStephan Aßmus // VolumeManager MUST be locked. After closing the handle must still be
4795a1d355fSStephan Aßmus // unlocked. When the last reference is surrendered it will finally be deleted.
4805a1d355fSStephan Aßmus status_t
Close(NodeHandle * handle)4815a1d355fSStephan Aßmus ClientVolume::Close(NodeHandle* handle)
4825a1d355fSStephan Aßmus {
4835a1d355fSStephan Aßmus 	if (!handle || !fNodeHandles->RemoveNodeHandle(handle))
4845a1d355fSStephan Aßmus 		return B_BAD_VALUE;
4855a1d355fSStephan Aßmus 
4865a1d355fSStephan Aßmus 	return B_OK;
4875a1d355fSStephan Aßmus }
4885a1d355fSStephan Aßmus 
4895a1d355fSStephan Aßmus // LockNodeHandle
4905a1d355fSStephan Aßmus //
4915a1d355fSStephan Aßmus // VolumeManager must NOT be locked.
4925a1d355fSStephan Aßmus status_t
LockNodeHandle(int32 cookie,NodeHandle ** _handle)4935a1d355fSStephan Aßmus ClientVolume::LockNodeHandle(int32 cookie, NodeHandle** _handle)
4945a1d355fSStephan Aßmus {
4955a1d355fSStephan Aßmus 	return fNodeHandles->LockNodeHandle(cookie, _handle);
4965a1d355fSStephan Aßmus }
4975a1d355fSStephan Aßmus 
4985a1d355fSStephan Aßmus // UnlockNodeHandle
4995a1d355fSStephan Aßmus //
5005a1d355fSStephan Aßmus // VolumeManager may or may not be locked.
5015a1d355fSStephan Aßmus void
UnlockNodeHandle(NodeHandle * nodeHandle)5025a1d355fSStephan Aßmus ClientVolume::UnlockNodeHandle(NodeHandle* nodeHandle)
5035a1d355fSStephan Aßmus {
5045a1d355fSStephan Aßmus 	fNodeHandles->UnlockNodeHandle(nodeHandle);
5055a1d355fSStephan Aßmus }
5065a1d355fSStephan Aßmus 
5075a1d355fSStephan Aßmus // ProcessNodeMonitoringEvent
5085a1d355fSStephan Aßmus void
ProcessNodeMonitoringEvent(NodeMonitoringEvent * event)5095a1d355fSStephan Aßmus ClientVolume::ProcessNodeMonitoringEvent(NodeMonitoringEvent* event)
5105a1d355fSStephan Aßmus {
5115a1d355fSStephan Aßmus 	if (fNodeMonitoringProcessor)
5125a1d355fSStephan Aßmus 		fNodeMonitoringProcessor->ProcessNodeMonitoringEvent(fID, event);
5135a1d355fSStephan Aßmus }
5145a1d355fSStephan Aßmus 
5155a1d355fSStephan Aßmus // _NextVolumeID
5165a1d355fSStephan Aßmus int32
_NextVolumeID()5175a1d355fSStephan Aßmus ClientVolume::_NextVolumeID()
5185a1d355fSStephan Aßmus {
5195a1d355fSStephan Aßmus 	return atomic_add(&sNextVolumeID, 1);
5205a1d355fSStephan Aßmus }
5215a1d355fSStephan Aßmus 
5225a1d355fSStephan Aßmus // sNextVolumeID
523*83b1a68cSAdrien Destugues int32 ClientVolume::sNextVolumeID = 0;
5245a1d355fSStephan Aßmus 
5255a1d355fSStephan Aßmus 
5265a1d355fSStephan Aßmus // #pragma -
5275a1d355fSStephan Aßmus 
5285a1d355fSStephan Aßmus // destructor
~NodeMonitoringProcessor()5295a1d355fSStephan Aßmus ClientVolume::NodeMonitoringProcessor::~NodeMonitoringProcessor()
5305a1d355fSStephan Aßmus {
5315a1d355fSStephan Aßmus }
5325a1d355fSStephan Aßmus 
533