The Pedigree Project 0.1
VFS-mount-view.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "pedigree/kernel/syscallError.h"
3#include "pedigree/kernel/utilities/Pointers.h"
4
5#include "MountView.h"
6#ifndef VFS_STANDALONE
7#include "pedigree/kernel/process/Process.h"
8#include "pedigree/kernel/process/Thread.h"
9#include "pedigree/kernel/processor/Processor.h"
10#include "pedigree/kernel/processor/ProcessorInformation.h"
11#endif
12
13VFS::NamespaceMutation::NamespaceMutation(VFS& vfs) : m_Vfs(vfs), m_Lock(vfs.m_PathMutationLock) {
14 __atomic_add_fetch(&m_Vfs.m_PathGeneration, 1, __ATOMIC_ACQ_REL);
15}
16VFS::NamespaceMutation::~NamespaceMutation() {
17 __atomic_add_fetch(&m_Vfs.m_PathGeneration, 1, __ATOMIC_RELEASE);
18}
19uint64_t VFS::NamespaceMutation::generation() const {
20 return m_Vfs.namespaceGeneration();
21}
22uint64_t VFS::namespaceGeneration() const {
23 return __atomic_load_n(&m_PathGeneration, __ATOMIC_ACQUIRE);
24}
25VfsMountView* VFS::mountView() const {
26#ifndef VFS_STANDALONE
27 auto* thread = Processor::information().getCurrentThread();
28 if (thread && thread->getParent()) {
29 auto context = thread->getParent()->acquireFilesystemContext();
30 if (auto* view = VfsMountView::fromContext(context)) {
31 return view;
32 }
33 }
34#endif
35 return bootMountView();
36}
37VfsMountView* VFS::bootMountView() const {
38 return __atomic_load_n(&m_MountView, __ATOMIC_ACQUIRE);
39}
41 auto* view = bootMountView();
42 if (!view)
43 return true;
44 if (!view->shutdown(ownedBackings))
45 return false;
46 __atomic_store_n(&m_MountView, static_cast<VfsMountView*>(nullptr), __ATOMIC_RELEASE);
47 delete view;
48 return true;
49}
50bool VFS::initialiseMountView() {
51 LockGuard<Mutex> mutation(m_MountMutationLock);
52 if (bootMountView())
53 return true;
55 if (!view || !view.get()->initialise(getRootFilesystem()))
56 return false;
57 FilesystemContextOwner bootstrap;
58 if (!view.get()->createBootContext(bootstrap))
59 return false;
60 auto context = bootstrap.reference();
62 Vector<FilesystemPathRef> importedPoints;
63 getMountsLocked(mounts);
64 if (!importedPoints.tryReserve(mounts.count())) {
65 SYSCALL_ERROR(OutOfMemory);
66 return false;
67 }
69 options.requireDirectory = true;
70 options.crossFinalMount = false;
71 for (const auto& mount : mounts) {
72 if (!mount.path.length() || mount.path == "/")
73 continue;
74 Filesystem* backing = getFilesystemAt(mount.path);
76 if (!backing ||
77 !view.get()->resolve(context, FilesystemPathRef(), mount.path, options, point) ||
78 !view.get()->attach(context, point, backing))
79 return false;
80 importedPoints.pushBack(pedigree_std::move(point));
81 }
82 bootstrap.reset();
83 context.reset();
84 {
85 NamespaceMutation writer(*this);
86 if (m_MountView) {
87 SYSCALL_ERROR(DeviceBusy);
88 return false;
89 }
90 // Once imported, mount edges have one authority; stale raw reparses must
91 // not survive backing retirement or offer a second lookup namespace.
92 for (const auto& point : importedPoints)
93 Directory::fromFile(point->node())->setReparsePoint(nullptr);
94 __atomic_store_n(&m_MountView, view.releaseOwnership(), __ATOMIC_RELEASE);
95 }
96 return true;
97}
static ProcessorInformation & information()
static UniquePointer< T > adopt(T *pointer)
Definition Pointers.h:101
Definition VFS.h:58
Filesystem * getFilesystemAt(const String &path) const
Definition VFS.cc:843
bool mount(Disk *pDisk, String &stableName, Filesystem **pMountedFs=nullptr)
Definition VFS.cc:419
bool shutdownMountView(Vector< Filesystem * > &ownedBackings)
Filesystem * getRootFilesystem() const
Definition VFS.cc:742
uint64_t namespaceGeneration() const
A vector / dynamic array.
Definition Vector.h:33
void pushBack(const T &value)
Definition Vector.h:275
size_t count() const
Definition Vector.h:270