xref: /haiku/src/system/kernel/fs/Vnode.h (revision 2f37cef1e414c296b7ee3ea2a1dc19554838d2d2)
18ccbb781SIngo Weinhold /*
24535495dSIngo Weinhold  * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
38ccbb781SIngo Weinhold  * Distributed under the terms of the MIT License.
48ccbb781SIngo Weinhold  */
58ccbb781SIngo Weinhold #ifndef VNODE_H
68ccbb781SIngo Weinhold #define VNODE_H
78ccbb781SIngo Weinhold 
88ccbb781SIngo Weinhold 
98ccbb781SIngo Weinhold #include <fs_interface.h>
108ccbb781SIngo Weinhold 
118ccbb781SIngo Weinhold #include <util/DoublyLinkedList.h>
128ccbb781SIngo Weinhold #include <util/list.h>
138ccbb781SIngo Weinhold 
148ccbb781SIngo Weinhold #include <lock.h>
158ccbb781SIngo Weinhold #include <thread.h>
168ccbb781SIngo Weinhold 
178ccbb781SIngo Weinhold 
188ccbb781SIngo Weinhold struct advisory_locking;
198ccbb781SIngo Weinhold struct file_descriptor;
208ccbb781SIngo Weinhold struct fs_mount;
218ccbb781SIngo Weinhold struct VMCache;
228ccbb781SIngo Weinhold 
238ccbb781SIngo Weinhold typedef struct vnode Vnode;
248ccbb781SIngo Weinhold 
258ccbb781SIngo Weinhold 
268ccbb781SIngo Weinhold struct vnode : fs_vnode, DoublyLinkedListLinkImpl<vnode> {
27*2f37cef1SAugustin Cavalier 			struct vnode*		hash_next;
288ccbb781SIngo Weinhold 			VMCache*			cache;
298ccbb781SIngo Weinhold 			struct fs_mount*	mount;
308ccbb781SIngo Weinhold 			struct vnode*		covered_by;
3102be66caSIngo Weinhold 			struct vnode*		covers;
328ccbb781SIngo Weinhold 			struct advisory_locking* advisory_locking;
338ccbb781SIngo Weinhold 			struct file_descriptor* mandatory_locked_by;
34*2f37cef1SAugustin Cavalier 			DoublyLinkedListLink<struct vnode> unused_link;
358ccbb781SIngo Weinhold 			ino_t				id;
368ccbb781SIngo Weinhold 			dev_t				device;
378ccbb781SIngo Weinhold 			int32				ref_count;
388ccbb781SIngo Weinhold 
398ccbb781SIngo Weinhold public:
408ccbb781SIngo Weinhold 	inline	bool				IsBusy() const;
418ccbb781SIngo Weinhold 	inline	void				SetBusy(bool busy);
428ccbb781SIngo Weinhold 
438ccbb781SIngo Weinhold 	inline	bool				IsRemoved() const;
448ccbb781SIngo Weinhold 	inline	void				SetRemoved(bool removed);
458ccbb781SIngo Weinhold 
468ccbb781SIngo Weinhold 	inline	bool				IsUnpublished() const;
478ccbb781SIngo Weinhold 	inline	void				SetUnpublished(bool unpublished);
488ccbb781SIngo Weinhold 
4954848900SIngo Weinhold 	inline	bool				IsUnused() const;
5054848900SIngo Weinhold 	inline	void				SetUnused(bool unused);
5154848900SIngo Weinhold 
5254848900SIngo Weinhold 	inline	bool				IsHot() const;
5354848900SIngo Weinhold 	inline	void				SetHot(bool hot);
5454848900SIngo Weinhold 
5547ea54c5SIngo Weinhold 	// setter requires sVnodeLock write-locked, getter is lockless
5647ea54c5SIngo Weinhold 	inline	bool				IsCovered() const;
5747ea54c5SIngo Weinhold 	inline	void				SetCovered(bool covered);
5847ea54c5SIngo Weinhold 
5947ea54c5SIngo Weinhold 	// setter requires sVnodeLock write-locked, getter is lockless
6047ea54c5SIngo Weinhold 	inline	bool				IsCovering() const;
6147ea54c5SIngo Weinhold 	inline	void				SetCovering(bool covering);
6247ea54c5SIngo Weinhold 
638ccbb781SIngo Weinhold 	inline	uint32				Type() const;
648ccbb781SIngo Weinhold 	inline	void				SetType(uint32 type);
658ccbb781SIngo Weinhold 
668ccbb781SIngo Weinhold 	inline	bool				Lock();
678ccbb781SIngo Weinhold 	inline	void				Unlock();
688ccbb781SIngo Weinhold 
698ccbb781SIngo Weinhold 	static	void				StaticInit();
708ccbb781SIngo Weinhold 
718ccbb781SIngo Weinhold private:
728ccbb781SIngo Weinhold 	static	const uint32		kFlagsLocked		= 0x00000001;
738ccbb781SIngo Weinhold 	static	const uint32		kFlagsWaitingLocker	= 0x00000002;
748ccbb781SIngo Weinhold 	static	const uint32		kFlagsBusy			= 0x00000004;
758ccbb781SIngo Weinhold 	static	const uint32		kFlagsRemoved		= 0x00000008;
768ccbb781SIngo Weinhold 	static	const uint32		kFlagsUnpublished	= 0x00000010;
7754848900SIngo Weinhold 	static	const uint32		kFlagsUnused		= 0x00000020;
7854848900SIngo Weinhold 	static	const uint32		kFlagsHot			= 0x00000040;
7947ea54c5SIngo Weinhold 	static	const uint32		kFlagsCovered		= 0x00000080;
8047ea54c5SIngo Weinhold 	static	const uint32		kFlagsCovering		= 0x00000100;
818ccbb781SIngo Weinhold 	static	const uint32		kFlagsType			= 0xfffff000;
828ccbb781SIngo Weinhold 
838ccbb781SIngo Weinhold 	static	const uint32		kBucketCount		= 32;
848ccbb781SIngo Weinhold 
858ccbb781SIngo Weinhold 			struct LockWaiter : DoublyLinkedListLinkImpl<LockWaiter> {
864535495dSIngo Weinhold 				Thread*			thread;
878ccbb781SIngo Weinhold 				struct vnode*	vnode;
888ccbb781SIngo Weinhold 			};
898ccbb781SIngo Weinhold 
908ccbb781SIngo Weinhold 			typedef DoublyLinkedList<LockWaiter> LockWaiterList;
918ccbb781SIngo Weinhold 
928ccbb781SIngo Weinhold 			struct Bucket {
938ccbb781SIngo Weinhold 				mutex			lock;
948ccbb781SIngo Weinhold 				LockWaiterList	waiters;
958ccbb781SIngo Weinhold 
968ccbb781SIngo Weinhold 				Bucket();
978ccbb781SIngo Weinhold 			};
988ccbb781SIngo Weinhold 
998ccbb781SIngo Weinhold private:
1008ccbb781SIngo Weinhold 	inline	Bucket&				_Bucket() const;
1018ccbb781SIngo Weinhold 
1028ccbb781SIngo Weinhold 			void				_WaitForLock();
1038ccbb781SIngo Weinhold 			void				_WakeUpLocker();
1048ccbb781SIngo Weinhold 
1058ccbb781SIngo Weinhold private:
10673ad2473SPawel Dziepak 			int32				fFlags;
1078ccbb781SIngo Weinhold 
1088ccbb781SIngo Weinhold 	static	Bucket				sBuckets[kBucketCount];
1098ccbb781SIngo Weinhold };
1108ccbb781SIngo Weinhold 
1118ccbb781SIngo Weinhold 
1128ccbb781SIngo Weinhold bool
IsBusy()1138ccbb781SIngo Weinhold vnode::IsBusy() const
1148ccbb781SIngo Weinhold {
1158ccbb781SIngo Weinhold 	return (fFlags & kFlagsBusy) != 0;
1168ccbb781SIngo Weinhold }
1178ccbb781SIngo Weinhold 
1188ccbb781SIngo Weinhold 
1198ccbb781SIngo Weinhold void
SetBusy(bool busy)1208ccbb781SIngo Weinhold vnode::SetBusy(bool busy)
1218ccbb781SIngo Weinhold {
1228ccbb781SIngo Weinhold 	if (busy)
1238ccbb781SIngo Weinhold 		atomic_or(&fFlags, kFlagsBusy);
1248ccbb781SIngo Weinhold 	else
1258ccbb781SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsBusy);
1268ccbb781SIngo Weinhold }
1278ccbb781SIngo Weinhold 
1288ccbb781SIngo Weinhold 
1298ccbb781SIngo Weinhold bool
IsRemoved()1308ccbb781SIngo Weinhold vnode::IsRemoved() const
1318ccbb781SIngo Weinhold {
1328ccbb781SIngo Weinhold 	return (fFlags & kFlagsRemoved) != 0;
1338ccbb781SIngo Weinhold }
1348ccbb781SIngo Weinhold 
1358ccbb781SIngo Weinhold 
1368ccbb781SIngo Weinhold void
SetRemoved(bool removed)1378ccbb781SIngo Weinhold vnode::SetRemoved(bool removed)
1388ccbb781SIngo Weinhold {
1398ccbb781SIngo Weinhold 	if (removed)
1408ccbb781SIngo Weinhold 		atomic_or(&fFlags, kFlagsRemoved);
1418ccbb781SIngo Weinhold 	else
1428ccbb781SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsRemoved);
1438ccbb781SIngo Weinhold }
1448ccbb781SIngo Weinhold 
1458ccbb781SIngo Weinhold 
1468ccbb781SIngo Weinhold bool
IsUnpublished()1478ccbb781SIngo Weinhold vnode::IsUnpublished() const
1488ccbb781SIngo Weinhold {
1498ccbb781SIngo Weinhold 	return (fFlags & kFlagsUnpublished) != 0;
1508ccbb781SIngo Weinhold }
1518ccbb781SIngo Weinhold 
1528ccbb781SIngo Weinhold 
1538ccbb781SIngo Weinhold void
SetUnpublished(bool unpublished)1548ccbb781SIngo Weinhold vnode::SetUnpublished(bool unpublished)
1558ccbb781SIngo Weinhold {
1568ccbb781SIngo Weinhold 	if (unpublished)
1578ccbb781SIngo Weinhold 		atomic_or(&fFlags, kFlagsUnpublished);
1588ccbb781SIngo Weinhold 	else
1598ccbb781SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsUnpublished);
1608ccbb781SIngo Weinhold }
1618ccbb781SIngo Weinhold 
1628ccbb781SIngo Weinhold 
16354848900SIngo Weinhold bool
IsUnused()16454848900SIngo Weinhold vnode::IsUnused() const
16554848900SIngo Weinhold {
16654848900SIngo Weinhold 	return (fFlags & kFlagsUnused) != 0;
16754848900SIngo Weinhold }
16854848900SIngo Weinhold 
16954848900SIngo Weinhold 
17054848900SIngo Weinhold void
SetUnused(bool unused)17154848900SIngo Weinhold vnode::SetUnused(bool unused)
17254848900SIngo Weinhold {
17354848900SIngo Weinhold 	if (unused)
17454848900SIngo Weinhold 		atomic_or(&fFlags, kFlagsUnused);
17554848900SIngo Weinhold 	else
17654848900SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsUnused);
17754848900SIngo Weinhold }
17854848900SIngo Weinhold 
17954848900SIngo Weinhold 
18054848900SIngo Weinhold bool
IsHot()18154848900SIngo Weinhold vnode::IsHot() const
18254848900SIngo Weinhold {
18354848900SIngo Weinhold 	return (fFlags & kFlagsHot) != 0;
18454848900SIngo Weinhold }
18554848900SIngo Weinhold 
18654848900SIngo Weinhold 
18754848900SIngo Weinhold void
SetHot(bool hot)18854848900SIngo Weinhold vnode::SetHot(bool hot)
18954848900SIngo Weinhold {
19054848900SIngo Weinhold 	if (hot)
19154848900SIngo Weinhold 		atomic_or(&fFlags, kFlagsHot);
19254848900SIngo Weinhold 	else
19354848900SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsHot);
19454848900SIngo Weinhold }
19554848900SIngo Weinhold 
19654848900SIngo Weinhold 
19747ea54c5SIngo Weinhold bool
IsCovered()19847ea54c5SIngo Weinhold vnode::IsCovered() const
19947ea54c5SIngo Weinhold {
20047ea54c5SIngo Weinhold 	return (fFlags & kFlagsCovered) != 0;
20147ea54c5SIngo Weinhold }
20247ea54c5SIngo Weinhold 
20347ea54c5SIngo Weinhold 
20447ea54c5SIngo Weinhold void
SetCovered(bool covered)20547ea54c5SIngo Weinhold vnode::SetCovered(bool covered)
20647ea54c5SIngo Weinhold {
20747ea54c5SIngo Weinhold 	if (covered)
20847ea54c5SIngo Weinhold 		atomic_or(&fFlags, kFlagsCovered);
20947ea54c5SIngo Weinhold 	else
21047ea54c5SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsCovered);
21147ea54c5SIngo Weinhold }
21247ea54c5SIngo Weinhold 
21347ea54c5SIngo Weinhold 
21447ea54c5SIngo Weinhold bool
IsCovering()21547ea54c5SIngo Weinhold vnode::IsCovering() const
21647ea54c5SIngo Weinhold {
21747ea54c5SIngo Weinhold 	return (fFlags & kFlagsCovering) != 0;
21847ea54c5SIngo Weinhold }
21947ea54c5SIngo Weinhold 
22047ea54c5SIngo Weinhold 
22147ea54c5SIngo Weinhold void
SetCovering(bool covering)22247ea54c5SIngo Weinhold vnode::SetCovering(bool covering)
22347ea54c5SIngo Weinhold {
22447ea54c5SIngo Weinhold 	if (covering)
22547ea54c5SIngo Weinhold 		atomic_or(&fFlags, kFlagsCovering);
22647ea54c5SIngo Weinhold 	else
22747ea54c5SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsCovering);
22847ea54c5SIngo Weinhold }
22947ea54c5SIngo Weinhold 
23047ea54c5SIngo Weinhold 
2318ccbb781SIngo Weinhold uint32
Type()2328ccbb781SIngo Weinhold vnode::Type() const
2338ccbb781SIngo Weinhold {
2348ccbb781SIngo Weinhold 	return (uint32)fFlags & kFlagsType;
2358ccbb781SIngo Weinhold }
2368ccbb781SIngo Weinhold 
2378ccbb781SIngo Weinhold 
2388ccbb781SIngo Weinhold void
SetType(uint32 type)2398ccbb781SIngo Weinhold vnode::SetType(uint32 type)
2408ccbb781SIngo Weinhold {
2418ccbb781SIngo Weinhold 	atomic_and(&fFlags, ~kFlagsType);
2428ccbb781SIngo Weinhold 	atomic_or(&fFlags, type & kFlagsType);
2438ccbb781SIngo Weinhold }
2448ccbb781SIngo Weinhold 
2458ccbb781SIngo Weinhold 
2468ccbb781SIngo Weinhold /*!	Locks the vnode.
2478ccbb781SIngo Weinhold 	The caller must hold sVnodeLock (at least read locked) and must continue to
2488ccbb781SIngo Weinhold 	hold it until calling Unlock(). After acquiring the lock the caller is
2498ccbb781SIngo Weinhold 	allowed to write access the vnode's mutable fields, if it hasn't been marked
2508ccbb781SIngo Weinhold 	busy by someone else.
2518ccbb781SIngo Weinhold 	Due to the condition of holding sVnodeLock at least read locked, write
2528ccbb781SIngo Weinhold 	locking it grants the same write access permission to *any* vnode.
2538ccbb781SIngo Weinhold 
2548ccbb781SIngo Weinhold 	The vnode's lock should be held only for a short time. It can be held over
2558ccbb781SIngo Weinhold 	sUnusedVnodesLock.
2568ccbb781SIngo Weinhold 
2578ccbb781SIngo Weinhold 	\return Always \c true.
2588ccbb781SIngo Weinhold */
2598ccbb781SIngo Weinhold bool
Lock()2608ccbb781SIngo Weinhold vnode::Lock()
2618ccbb781SIngo Weinhold {
2628ccbb781SIngo Weinhold 	if ((atomic_or(&fFlags, kFlagsLocked)
2638ccbb781SIngo Weinhold 			& (kFlagsLocked | kFlagsWaitingLocker)) != 0) {
2648ccbb781SIngo Weinhold 		_WaitForLock();
2658ccbb781SIngo Weinhold 	}
2668ccbb781SIngo Weinhold 
2678ccbb781SIngo Weinhold 	return true;
2688ccbb781SIngo Weinhold }
2698ccbb781SIngo Weinhold 
2708ccbb781SIngo Weinhold void
Unlock()2718ccbb781SIngo Weinhold vnode::Unlock()
2728ccbb781SIngo Weinhold {
2738ccbb781SIngo Weinhold 	if ((atomic_and(&fFlags, ~kFlagsLocked) & kFlagsWaitingLocker) != 0)
2748ccbb781SIngo Weinhold 		_WakeUpLocker();
2758ccbb781SIngo Weinhold }
2768ccbb781SIngo Weinhold 
2778ccbb781SIngo Weinhold 
2788ccbb781SIngo Weinhold vnode::Bucket&
_Bucket()2798ccbb781SIngo Weinhold vnode::_Bucket() const
2808ccbb781SIngo Weinhold {
2818ccbb781SIngo Weinhold 	return sBuckets[((addr_t)this / 64) % kBucketCount];
2828ccbb781SIngo Weinhold 		// The vnode structure is somewhat larger than 64 bytes (on 32 bit
2838ccbb781SIngo Weinhold 		// archs), so subsequently allocated vnodes fall into different
2848ccbb781SIngo Weinhold 		// buckets. How exactly the vnodes are distributed depends on the
2858ccbb781SIngo Weinhold 		// allocator -- a dedicated slab would be perfect.
2868ccbb781SIngo Weinhold }
2878ccbb781SIngo Weinhold 
2888ccbb781SIngo Weinhold 
2898ccbb781SIngo Weinhold #endif	// VNODE_H
290