The Pedigree Project 0.1
VFS.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef VFS_H
21#define VFS_H
22#include "pedigree/kernel/linker/KernelElf.h"
23
24#include <config.h>
25
26#if THREADS
27#include "pedigree/kernel/Spinlock.h"
28#include "pedigree/kernel/process/WaitQueue.h"
29#endif
30#include "pedigree/kernel/LockGuard.h"
31#include "pedigree/kernel/compiler.h"
32#include "pedigree/kernel/process/FilesystemContext.h"
33#include "pedigree/kernel/process/FilesystemCredentials.h"
34#include "pedigree/kernel/process/Mutex.h"
35#include "pedigree/kernel/process/OperationBarrier.h"
36#include "pedigree/kernel/process/Rcu.h"
37#include "pedigree/kernel/processor/types.h"
38#include "pedigree/kernel/utilities/List.h"
39#include "pedigree/kernel/utilities/LruCache.h"
40#include "pedigree/kernel/utilities/String.h"
41#include "pedigree/kernel/utilities/Tree.h"
42#include "pedigree/kernel/utilities/Vector.h"
43#include "pedigree/kernel/utilities/utility.h"
44
45#include "Filesystem.h"
46
47class Process;
48class Disk;
49class File;
50class StringView;
51class VfsMountState;
53class VfsMountView;
54
58class EXPORTED_PUBLIC VFS {
59 public:
60 class EXPORTED_PUBLIC NamespaceMutation {
61 public:
62 explicit NamespaceMutation(VFS& vfs);
64 uint64_t generation() const;
65 bool protects(const VFS& vfs) const {
66 return &m_Vfs == &vfs;
67 }
68
69 private:
70 NamespaceMutation(const NamespaceMutation&) = delete;
71 NamespaceMutation& operator=(const NamespaceMutation&) = delete;
72 VFS& m_Vfs;
73 LockGuard<Mutex> m_Lock;
74 };
75
77 uint64_t namespaceGeneration() const;
78 VfsMountView* mountView() const;
79 VfsMountView* bootMountView() const;
81 bool shutdownMountView(Vector<Filesystem*>& ownedBackings);
82 bool initialiseMountView();
83
84 static Module::UnloadAdmission unloadAdmission(bool terminal);
85 class MountOperation;
86 class FilesystemPin;
87 class EXPORTED_PUBLIC MountIdentity {
88 public:
90 MountIdentity(const MountIdentity& other);
91 MountIdentity(MountIdentity&& other) noexcept;
93 MountIdentity& operator=(const MountIdentity& other);
94 MountIdentity& operator=(MountIdentity&& other) noexcept;
95 uint32_t id() const;
96 explicit operator bool() const;
97 bool acquire(MountOperation& operation) const;
98 bool pin(FilesystemPin& pin) const;
99 bool subscribeRetirement(const SharedPointer<FileEventObserver>& observer,
100 FileEventSubscription& subscription) const;
101
102 private:
103 friend class VFS;
104 friend class MountOperation;
105 friend class FilesystemPin;
107 };
108
109 class EXPORTED_PUBLIC MountOperation {
110 public:
112 MountOperation(MountOperation&& other) noexcept;
114 MountOperation& operator=(MountOperation&& other) noexcept;
115 Filesystem* filesystem() const;
116 uint32_t id() const;
117 MountIdentity identity() const;
118 explicit operator bool() const;
119 void reset();
120
121 private:
122 friend class VFS;
123 friend class MountIdentity;
124 MountOperation(const MountOperation&) = delete;
125 MountOperation& operator=(const MountOperation&) = delete;
126 TerminationDeferral m_Lifetime;
128 OperationBarrier::Lease m_Admission;
129 };
130
132 bool acquireMount(Filesystem* key, MountOperation& operation) const;
133
139 class EXPORTED_PUBLIC FilesystemPin {
140 public:
142 FilesystemPin(const FilesystemPin& other);
143 FilesystemPin(FilesystemPin&& other) noexcept;
145 FilesystemPin& operator=(const FilesystemPin& other);
146 FilesystemPin& operator=(FilesystemPin&& other) noexcept;
147 Filesystem* filesystem() const;
148 MountIdentity identity() const;
149 explicit operator bool() const;
150 void reset();
151
152 private:
153 friend class VFS;
154 friend class MountIdentity;
156 };
157
158#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
159 class EXPORTED_PUBLIC HostedRootViewScope {
160 public:
161 HostedRootViewScope();
162 ~HostedRootViewScope();
163 bool open(Filesystem* filesystem);
164 bool installContext(Process& process);
165 bool close();
166 VfsMountView* view() const {
167 return m_View;
168 }
169
170 private:
171 HostedRootViewScope(const HostedRootViewScope&) = delete;
172 HostedRootViewScope& operator=(const HostedRootViewScope&) = delete;
173 TerminationDeferral m_Lifetime;
174 VFS& m_Vfs;
175 Filesystem* m_Filesystem = nullptr;
176 Filesystem* m_PreviousRoot = nullptr;
177 VfsMountView* m_PreviousView = nullptr;
178 VfsMountView* m_View = nullptr;
179 FilesystemPin m_PreviousRootPin;
180 FilesystemContextRef m_PreviousContext;
181 bool m_Installed = false;
182 };
183#endif
184
185 bool pinFilesystem(Filesystem* key, FilesystemPin& pin) const;
186 bool diskMount(uint32_t id, MountIdentity& identity) const;
187 bool snapshotDiskMounts(Vector<MountIdentity>& mounts) const;
188
190 typedef void (*MountCallback)();
191
194 MountSnapshot() : hasDisk(false) {}
195 MountSnapshot(const String& stableName, const String& path, bool hasDisk,
196 const String& diskParentName, const String& diskName)
197 : stableName(stableName),
198 path(path),
199 hasDisk(hasDisk),
200 diskParentName(diskParentName),
201 diskName(diskName) {}
202
203 String stableName;
204 String path;
205 bool hasDisk;
206 String diskParentName;
207 String diskName;
208 };
209
211 VFS();
213 ~VFS();
214
216 static VFS& instance();
217
219 bool mount(Disk* pDisk, String& stableName, Filesystem** pMountedFs = nullptr);
220
222 String registerFilesystem(Filesystem* pFs, const String& preferredStableName);
223
231 // Terminal failures after admission closes leave the unregistered backend
232 // alive for diagnosis; callers must halt instead of resuming filesystem use.
233 bool unregisterFilesystem(Filesystem* pFs, bool canDelete = true, bool terminal = false);
236 bool retireOwnedFilesystem(Filesystem* filesystem);
238 bool removeDiskFilesystem(Filesystem* filesystem, bool deviceAvailable = false);
239
241 bool setRootFilesystem(Filesystem* pFs);
242
244 Filesystem* getRootFilesystem() const;
245
246#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
248 Filesystem* swapRootFilesystemForHostedTest(Filesystem* pFs);
249#endif
250
252 bool getMountPath(Filesystem* pFs, String& path) const;
253
258 Filesystem* getFilesystemAt(const String& path) const;
259
261 void getMounts(Vector<MountSnapshot>& mounts) const;
262
264 Filesystem::SyncStatus syncFilesystem(Filesystem* key);
265
267 Filesystem::SyncStatus syncAll();
268
270 bool removeEphemeralFiles();
271
273 File* find(const String& path, File* pStartNode = 0);
274
276 File* findRetained(const String& path, Directory::ChildLease& result, File* pStartNode = nullptr);
277
279 bool createFile(const String& path, uint32_t mask, File* pStartNode = 0);
280
282 bool createDirectory(const String& path, uint32_t mask, File* pStartNode = 0);
283
285 bool createSymlink(const String& path, const String& value, File* pStartNode = 0);
286
288 bool createLink(const String& path, File* target, File* pStartNode = 0);
289
292 bool remove(const String& path, File* pStartNode = 0);
293
295 bool remove(const String& path, File* pStartNode, File* expected);
296
297 bool rename(const String& oldPath, File* oldStart, const String& newPath, File* newStart,
298 bool noReplace = false);
299
303 void addProbeCallback(Filesystem::ProbeCallback callback);
304
306 bool removeProbeCallback(Filesystem::ProbeCallback callback);
307
311 void addMountCallback(MountCallback callback);
312
314 bool removeMountCallback(MountCallback callback);
315
317 static bool checkAccess(File* pFile, bool bRead, bool bWrite, bool bExecute);
318 static bool checkAccess(File* file, bool read, bool write, bool execute,
319 const FilesystemCredentials& credentials);
320
322 static bool checkAccess(File* pFile, bool bRead, bool bWrite, bool bExecute, int64_t userId,
323 int64_t groupId, const Vector<int64_t>& supplementalGroups);
324
333 void trackFile(File* pFile);
335 bool tryTrackFile(File* pFile);
336
338 MUST_USE_RESULT bool retainTrackedFile(File* pFile);
339
346 bool untrackFile(File* pFile, bool destroy = true);
347
348#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
349 using RetainTrackedFileHook = void (*)(File* pFile);
350 static void setRetainTrackedFileHookForHostedTest(RetainTrackedFileHook hook);
351#endif
352
353 private:
354 struct TrackedFile;
355 static constexpr size_t TrackedFileBuckets = 256;
356 RcuPointer<TrackedFile>& trackedFileBucket(File* file);
357 bool trackFileLocked(File* file);
358
359 struct MountInfo {
360 MountInfo(const String& stableName, const String& path,
361 const SharedPointer<VfsMountState>& state);
362 ~MountInfo();
363
364 String stableName;
365 String path;
367 };
368
370
372#if THREADS
373 size_t sequence = 0;
374 size_t inFlight = 0;
375 size_t removers = 0;
376 bool enabled = true;
377 bool draining = false;
378 uintptr_t debugAddress = 0;
379 WaitQueue drainWaiters;
380#endif
381 };
382
384 explicit ProbeCallbackItem(Filesystem::ProbeCallback callback) : callback(callback) {}
385
386 CallbackState state;
388 };
389
391 explicit MountCallbackItem(MountCallback callback) : callback(callback) {}
392
393 CallbackState state;
394 MountCallback callback;
395 };
396
397#if THREADS
399 CallbackState* state;
400 void* owner;
401 ActiveInvocation* next;
402 };
403
404 ProbeCallbackItem* acquireProbeCallback(size_t& afterSequence, size_t boundary,
405 ActiveInvocation& invocation);
406 MountCallbackItem* acquireMountCallback(size_t& afterSequence, size_t boundary,
407 ActiveInvocation& invocation);
408 void finishCallback(CallbackState* state, ActiveInvocation& invocation);
409 void drainProbeCallback(ProbeCallbackItem* item);
410 void drainMountCallback(MountCallbackItem* item);
411 void dispatchMountCallbacks(void* owner);
412 bool isCallbackInvocation(void* owner) const;
413#endif
414
415 File* resolveStartNode(const String& path, File* pStartNode);
416 String registerFilesystemLocked(Filesystem* pFs, const String& preferredStableName);
417 String getUniqueStableNameLocked(const String& preferredName) const;
418 bool attachFilesystem(Filesystem* pRootFs, Filesystem* pFs, const String& path);
419 void attachRegisteredFilesystemsLocked();
420 void getMountsLocked(Vector<MountSnapshot>& mounts) const;
421
424
427
428 mutable Mutex m_PathMutationLock;
429 uint64_t m_PathGeneration;
430 VfsMountView* m_MountView;
431 mutable Mutex m_MountMutationLock;
432 mutable Mutex m_MountTableLock;
433
434 Filesystem* m_pRootFilesystem;
435 MountTable m_Mounts;
436
437 List<ProbeCallbackItem*> m_ProbeCallbacks;
438 List<MountCallbackItem*> m_MountCallbacks;
439
440#if THREADS
441 Spinlock m_CallbackLock;
442 size_t m_NextCallbackSequence;
443 ActiveInvocation* m_pActiveCallbacks;
444 bool m_CallbacksClosing;
445#endif
446
447 LruCache<String, File*> m_FindCache;
448
449 Mutex m_TrackedFilesLock;
450 RcuPointer<TrackedFile> m_TrackedFiles[TrackedFileBuckets];
451
452#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
453 static RetainTrackedFileHook m_RetainTrackedFileHook;
454#endif
455};
456
457#endif
Definition Disk.h:35
Definition File.h:75
Filesystem *(* ProbeCallback)(Disk *)
Definition Filesystem.h:70
Definition List.h:61
LruCache provides a least-recently-used cache abstraction.
Definition LruCache.h:38
Definition Mutex.h:56
A key/value dictionary.
Definition Tree.h:33
Definition VFS.h:58
static VFS m_Instance
Definition VFS.h:423
static File * m_EmptyFile
Definition VFS.h:426
A vector / dynamic array.
Definition Vector.h:33