xref: /haiku/src/system/kernel/fs/Vnode.h (revision 02be66ca1093b26d538f9aa56ede8564c910acdd)
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> {
278ccbb781SIngo Weinhold 			struct vnode*		next;
288ccbb781SIngo Weinhold 			VMCache*			cache;
298ccbb781SIngo Weinhold 			struct fs_mount*	mount;
308ccbb781SIngo Weinhold 			struct vnode*		covered_by;
31*02be66caSIngo Weinhold 			struct vnode*		covers;
328ccbb781SIngo Weinhold 			struct advisory_locking* advisory_locking;
338ccbb781SIngo Weinhold 			struct file_descriptor* mandatory_locked_by;
348ccbb781SIngo Weinhold 			list_link			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 
558ccbb781SIngo Weinhold 	inline	uint32				Type() const;
568ccbb781SIngo Weinhold 	inline	void				SetType(uint32 type);
578ccbb781SIngo Weinhold 
588ccbb781SIngo Weinhold 	inline	bool				Lock();
598ccbb781SIngo Weinhold 	inline	void				Unlock();
608ccbb781SIngo Weinhold 
618ccbb781SIngo Weinhold 	static	void				StaticInit();
628ccbb781SIngo Weinhold 
638ccbb781SIngo Weinhold private:
648ccbb781SIngo Weinhold 	static	const uint32		kFlagsLocked		= 0x00000001;
658ccbb781SIngo Weinhold 	static	const uint32		kFlagsWaitingLocker	= 0x00000002;
668ccbb781SIngo Weinhold 	static	const uint32		kFlagsBusy			= 0x00000004;
678ccbb781SIngo Weinhold 	static	const uint32		kFlagsRemoved		= 0x00000008;
688ccbb781SIngo Weinhold 	static	const uint32		kFlagsUnpublished	= 0x00000010;
6954848900SIngo Weinhold 	static	const uint32		kFlagsUnused		= 0x00000020;
7054848900SIngo Weinhold 	static	const uint32		kFlagsHot			= 0x00000040;
718ccbb781SIngo Weinhold 	static	const uint32		kFlagsType			= 0xfffff000;
728ccbb781SIngo Weinhold 
738ccbb781SIngo Weinhold 	static	const uint32		kBucketCount		 = 32;
748ccbb781SIngo Weinhold 
758ccbb781SIngo Weinhold 			struct LockWaiter : DoublyLinkedListLinkImpl<LockWaiter> {
768ccbb781SIngo Weinhold 				LockWaiter*		next;
774535495dSIngo Weinhold 				Thread*			thread;
788ccbb781SIngo Weinhold 				struct vnode*	vnode;
798ccbb781SIngo Weinhold 			};
808ccbb781SIngo Weinhold 
818ccbb781SIngo Weinhold 			typedef DoublyLinkedList<LockWaiter> LockWaiterList;
828ccbb781SIngo Weinhold 
838ccbb781SIngo Weinhold 			struct Bucket {
848ccbb781SIngo Weinhold 				mutex			lock;
858ccbb781SIngo Weinhold 				LockWaiterList	waiters;
868ccbb781SIngo Weinhold 
878ccbb781SIngo Weinhold 				Bucket();
888ccbb781SIngo Weinhold 			};
898ccbb781SIngo Weinhold 
908ccbb781SIngo Weinhold private:
918ccbb781SIngo Weinhold 	inline	Bucket&				_Bucket() const;
928ccbb781SIngo Weinhold 
938ccbb781SIngo Weinhold 			void				_WaitForLock();
948ccbb781SIngo Weinhold 			void				_WakeUpLocker();
958ccbb781SIngo Weinhold 
968ccbb781SIngo Weinhold private:
978ccbb781SIngo Weinhold 			vint32				fFlags;
988ccbb781SIngo Weinhold 
998ccbb781SIngo Weinhold 	static	Bucket				sBuckets[kBucketCount];
1008ccbb781SIngo Weinhold };
1018ccbb781SIngo Weinhold 
1028ccbb781SIngo Weinhold 
1038ccbb781SIngo Weinhold bool
1048ccbb781SIngo Weinhold vnode::IsBusy() const
1058ccbb781SIngo Weinhold {
1068ccbb781SIngo Weinhold 	return (fFlags & kFlagsBusy) != 0;
1078ccbb781SIngo Weinhold }
1088ccbb781SIngo Weinhold 
1098ccbb781SIngo Weinhold 
1108ccbb781SIngo Weinhold void
1118ccbb781SIngo Weinhold vnode::SetBusy(bool busy)
1128ccbb781SIngo Weinhold {
1138ccbb781SIngo Weinhold 	if (busy)
1148ccbb781SIngo Weinhold 		atomic_or(&fFlags, kFlagsBusy);
1158ccbb781SIngo Weinhold 	else
1168ccbb781SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsBusy);
1178ccbb781SIngo Weinhold }
1188ccbb781SIngo Weinhold 
1198ccbb781SIngo Weinhold 
1208ccbb781SIngo Weinhold bool
1218ccbb781SIngo Weinhold vnode::IsRemoved() const
1228ccbb781SIngo Weinhold {
1238ccbb781SIngo Weinhold 	return (fFlags & kFlagsRemoved) != 0;
1248ccbb781SIngo Weinhold }
1258ccbb781SIngo Weinhold 
1268ccbb781SIngo Weinhold 
1278ccbb781SIngo Weinhold void
1288ccbb781SIngo Weinhold vnode::SetRemoved(bool removed)
1298ccbb781SIngo Weinhold {
1308ccbb781SIngo Weinhold 	if (removed)
1318ccbb781SIngo Weinhold 		atomic_or(&fFlags, kFlagsRemoved);
1328ccbb781SIngo Weinhold 	else
1338ccbb781SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsRemoved);
1348ccbb781SIngo Weinhold }
1358ccbb781SIngo Weinhold 
1368ccbb781SIngo Weinhold 
1378ccbb781SIngo Weinhold bool
1388ccbb781SIngo Weinhold vnode::IsUnpublished() const
1398ccbb781SIngo Weinhold {
1408ccbb781SIngo Weinhold 	return (fFlags & kFlagsUnpublished) != 0;
1418ccbb781SIngo Weinhold }
1428ccbb781SIngo Weinhold 
1438ccbb781SIngo Weinhold 
1448ccbb781SIngo Weinhold void
1458ccbb781SIngo Weinhold vnode::SetUnpublished(bool unpublished)
1468ccbb781SIngo Weinhold {
1478ccbb781SIngo Weinhold 	if (unpublished)
1488ccbb781SIngo Weinhold 		atomic_or(&fFlags, kFlagsUnpublished);
1498ccbb781SIngo Weinhold 	else
1508ccbb781SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsUnpublished);
1518ccbb781SIngo Weinhold }
1528ccbb781SIngo Weinhold 
1538ccbb781SIngo Weinhold 
15454848900SIngo Weinhold bool
15554848900SIngo Weinhold vnode::IsUnused() const
15654848900SIngo Weinhold {
15754848900SIngo Weinhold 	return (fFlags & kFlagsUnused) != 0;
15854848900SIngo Weinhold }
15954848900SIngo Weinhold 
16054848900SIngo Weinhold 
16154848900SIngo Weinhold void
16254848900SIngo Weinhold vnode::SetUnused(bool unused)
16354848900SIngo Weinhold {
16454848900SIngo Weinhold 	if (unused)
16554848900SIngo Weinhold 		atomic_or(&fFlags, kFlagsUnused);
16654848900SIngo Weinhold 	else
16754848900SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsUnused);
16854848900SIngo Weinhold }
16954848900SIngo Weinhold 
17054848900SIngo Weinhold 
17154848900SIngo Weinhold bool
17254848900SIngo Weinhold vnode::IsHot() const
17354848900SIngo Weinhold {
17454848900SIngo Weinhold 	return (fFlags & kFlagsHot) != 0;
17554848900SIngo Weinhold }
17654848900SIngo Weinhold 
17754848900SIngo Weinhold 
17854848900SIngo Weinhold void
17954848900SIngo Weinhold vnode::SetHot(bool hot)
18054848900SIngo Weinhold {
18154848900SIngo Weinhold 	if (hot)
18254848900SIngo Weinhold 		atomic_or(&fFlags, kFlagsHot);
18354848900SIngo Weinhold 	else
18454848900SIngo Weinhold 		atomic_and(&fFlags, ~kFlagsHot);
18554848900SIngo Weinhold }
18654848900SIngo Weinhold 
18754848900SIngo Weinhold 
1888ccbb781SIngo Weinhold uint32
1898ccbb781SIngo Weinhold vnode::Type() const
1908ccbb781SIngo Weinhold {
1918ccbb781SIngo Weinhold 	return (uint32)fFlags & kFlagsType;
1928ccbb781SIngo Weinhold }
1938ccbb781SIngo Weinhold 
1948ccbb781SIngo Weinhold 
1958ccbb781SIngo Weinhold void
1968ccbb781SIngo Weinhold vnode::SetType(uint32 type)
1978ccbb781SIngo Weinhold {
1988ccbb781SIngo Weinhold 	atomic_and(&fFlags, ~kFlagsType);
1998ccbb781SIngo Weinhold 	atomic_or(&fFlags, type & kFlagsType);
2008ccbb781SIngo Weinhold }
2018ccbb781SIngo Weinhold 
2028ccbb781SIngo Weinhold 
2038ccbb781SIngo Weinhold /*!	Locks the vnode.
2048ccbb781SIngo Weinhold 	The caller must hold sVnodeLock (at least read locked) and must continue to
2058ccbb781SIngo Weinhold 	hold it until calling Unlock(). After acquiring the lock the caller is
2068ccbb781SIngo Weinhold 	allowed to write access the vnode's mutable fields, if it hasn't been marked
2078ccbb781SIngo Weinhold 	busy by someone else.
2088ccbb781SIngo Weinhold 	Due to the condition of holding sVnodeLock at least read locked, write
2098ccbb781SIngo Weinhold 	locking it grants the same write access permission to *any* vnode.
2108ccbb781SIngo Weinhold 
2118ccbb781SIngo Weinhold 	The vnode's lock should be held only for a short time. It can be held over
2128ccbb781SIngo Weinhold 	sUnusedVnodesLock.
2138ccbb781SIngo Weinhold 
2148ccbb781SIngo Weinhold 	\return Always \c true.
2158ccbb781SIngo Weinhold */
2168ccbb781SIngo Weinhold bool
2178ccbb781SIngo Weinhold vnode::Lock()
2188ccbb781SIngo Weinhold {
2198ccbb781SIngo Weinhold 	if ((atomic_or(&fFlags, kFlagsLocked)
2208ccbb781SIngo Weinhold 			& (kFlagsLocked | kFlagsWaitingLocker)) != 0) {
2218ccbb781SIngo Weinhold 		_WaitForLock();
2228ccbb781SIngo Weinhold 	}
2238ccbb781SIngo Weinhold 
2248ccbb781SIngo Weinhold 	return true;
2258ccbb781SIngo Weinhold }
2268ccbb781SIngo Weinhold 
2278ccbb781SIngo Weinhold void
2288ccbb781SIngo Weinhold vnode::Unlock()
2298ccbb781SIngo Weinhold {
2308ccbb781SIngo Weinhold 	if ((atomic_and(&fFlags, ~kFlagsLocked) & kFlagsWaitingLocker) != 0)
2318ccbb781SIngo Weinhold 		_WakeUpLocker();
2328ccbb781SIngo Weinhold }
2338ccbb781SIngo Weinhold 
2348ccbb781SIngo Weinhold 
2358ccbb781SIngo Weinhold vnode::Bucket&
2368ccbb781SIngo Weinhold vnode::_Bucket() const
2378ccbb781SIngo Weinhold {
2388ccbb781SIngo Weinhold 	return sBuckets[((addr_t)this / 64) % kBucketCount];
2398ccbb781SIngo Weinhold 		// The vnode structure is somewhat larger than 64 bytes (on 32 bit
2408ccbb781SIngo Weinhold 		// archs), so subsequently allocated vnodes fall into different
2418ccbb781SIngo Weinhold 		// buckets. How exactly the vnodes are distributed depends on the
2428ccbb781SIngo Weinhold 		// allocator -- a dedicated slab would be perfect.
2438ccbb781SIngo Weinhold }
2448ccbb781SIngo Weinhold 
2458ccbb781SIngo Weinhold 
2468ccbb781SIngo Weinhold #endif	// VNODE_H
247