btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / fs / Vnode.h
blob6efe921a5c541dd67efba32c408b381dbe7543da
1 /*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5 #ifndef VNODE_H
6 #define VNODE_H
9 #include <fs_interface.h>
11 #include <util/DoublyLinkedList.h>
12 #include <util/list.h>
14 #include <lock.h>
15 #include <thread.h>
18 struct advisory_locking;
19 struct file_descriptor;
20 struct fs_mount;
21 struct VMCache;
23 typedef struct vnode Vnode;
26 struct vnode : fs_vnode, DoublyLinkedListLinkImpl<vnode> {
27 struct vnode* next;
28 VMCache* cache;
29 struct fs_mount* mount;
30 struct vnode* covered_by;
31 struct vnode* covers;
32 struct advisory_locking* advisory_locking;
33 struct file_descriptor* mandatory_locked_by;
34 list_link unused_link;
35 ino_t id;
36 dev_t device;
37 int32 ref_count;
39 public:
40 inline bool IsBusy() const;
41 inline void SetBusy(bool busy);
43 inline bool IsRemoved() const;
44 inline void SetRemoved(bool removed);
46 inline bool IsUnpublished() const;
47 inline void SetUnpublished(bool unpublished);
49 inline bool IsUnused() const;
50 inline void SetUnused(bool unused);
52 inline bool IsHot() const;
53 inline void SetHot(bool hot);
55 // setter requires sVnodeLock write-locked, getter is lockless
56 inline bool IsCovered() const;
57 inline void SetCovered(bool covered);
59 // setter requires sVnodeLock write-locked, getter is lockless
60 inline bool IsCovering() const;
61 inline void SetCovering(bool covering);
63 inline uint32 Type() const;
64 inline void SetType(uint32 type);
66 inline bool Lock();
67 inline void Unlock();
69 static void StaticInit();
71 private:
72 static const uint32 kFlagsLocked = 0x00000001;
73 static const uint32 kFlagsWaitingLocker = 0x00000002;
74 static const uint32 kFlagsBusy = 0x00000004;
75 static const uint32 kFlagsRemoved = 0x00000008;
76 static const uint32 kFlagsUnpublished = 0x00000010;
77 static const uint32 kFlagsUnused = 0x00000020;
78 static const uint32 kFlagsHot = 0x00000040;
79 static const uint32 kFlagsCovered = 0x00000080;
80 static const uint32 kFlagsCovering = 0x00000100;
81 static const uint32 kFlagsType = 0xfffff000;
83 static const uint32 kBucketCount = 32;
85 struct LockWaiter : DoublyLinkedListLinkImpl<LockWaiter> {
86 LockWaiter* next;
87 Thread* thread;
88 struct vnode* vnode;
91 typedef DoublyLinkedList<LockWaiter> LockWaiterList;
93 struct Bucket {
94 mutex lock;
95 LockWaiterList waiters;
97 Bucket();
100 private:
101 inline Bucket& _Bucket() const;
103 void _WaitForLock();
104 void _WakeUpLocker();
106 private:
107 int32 fFlags;
109 static Bucket sBuckets[kBucketCount];
113 bool
114 vnode::IsBusy() const
116 return (fFlags & kFlagsBusy) != 0;
120 void
121 vnode::SetBusy(bool busy)
123 if (busy)
124 atomic_or(&fFlags, kFlagsBusy);
125 else
126 atomic_and(&fFlags, ~kFlagsBusy);
130 bool
131 vnode::IsRemoved() const
133 return (fFlags & kFlagsRemoved) != 0;
137 void
138 vnode::SetRemoved(bool removed)
140 if (removed)
141 atomic_or(&fFlags, kFlagsRemoved);
142 else
143 atomic_and(&fFlags, ~kFlagsRemoved);
147 bool
148 vnode::IsUnpublished() const
150 return (fFlags & kFlagsUnpublished) != 0;
154 void
155 vnode::SetUnpublished(bool unpublished)
157 if (unpublished)
158 atomic_or(&fFlags, kFlagsUnpublished);
159 else
160 atomic_and(&fFlags, ~kFlagsUnpublished);
164 bool
165 vnode::IsUnused() const
167 return (fFlags & kFlagsUnused) != 0;
171 void
172 vnode::SetUnused(bool unused)
174 if (unused)
175 atomic_or(&fFlags, kFlagsUnused);
176 else
177 atomic_and(&fFlags, ~kFlagsUnused);
181 bool
182 vnode::IsHot() const
184 return (fFlags & kFlagsHot) != 0;
188 void
189 vnode::SetHot(bool hot)
191 if (hot)
192 atomic_or(&fFlags, kFlagsHot);
193 else
194 atomic_and(&fFlags, ~kFlagsHot);
198 bool
199 vnode::IsCovered() const
201 return (fFlags & kFlagsCovered) != 0;
205 void
206 vnode::SetCovered(bool covered)
208 if (covered)
209 atomic_or(&fFlags, kFlagsCovered);
210 else
211 atomic_and(&fFlags, ~kFlagsCovered);
215 bool
216 vnode::IsCovering() const
218 return (fFlags & kFlagsCovering) != 0;
222 void
223 vnode::SetCovering(bool covering)
225 if (covering)
226 atomic_or(&fFlags, kFlagsCovering);
227 else
228 atomic_and(&fFlags, ~kFlagsCovering);
232 uint32
233 vnode::Type() const
235 return (uint32)fFlags & kFlagsType;
239 void
240 vnode::SetType(uint32 type)
242 atomic_and(&fFlags, ~kFlagsType);
243 atomic_or(&fFlags, type & kFlagsType);
247 /*! Locks the vnode.
248 The caller must hold sVnodeLock (at least read locked) and must continue to
249 hold it until calling Unlock(). After acquiring the lock the caller is
250 allowed to write access the vnode's mutable fields, if it hasn't been marked
251 busy by someone else.
252 Due to the condition of holding sVnodeLock at least read locked, write
253 locking it grants the same write access permission to *any* vnode.
255 The vnode's lock should be held only for a short time. It can be held over
256 sUnusedVnodesLock.
258 \return Always \c true.
260 bool
261 vnode::Lock()
263 if ((atomic_or(&fFlags, kFlagsLocked)
264 & (kFlagsLocked | kFlagsWaitingLocker)) != 0) {
265 _WaitForLock();
268 return true;
271 void
272 vnode::Unlock()
274 if ((atomic_and(&fFlags, ~kFlagsLocked) & kFlagsWaitingLocker) != 0)
275 _WakeUpLocker();
279 vnode::Bucket&
280 vnode::_Bucket() const
282 return sBuckets[((addr_t)this / 64) % kBucketCount];
283 // The vnode structure is somewhat larger than 64 bytes (on 32 bit
284 // archs), so subsequently allocated vnodes fall into different
285 // buckets. How exactly the vnodes are distributed depends on the
286 // allocator -- a dedicated slab would be perfect.
290 #endif // VNODE_H