2#include "pedigree/kernel/Log.h"
3#include "pedigree/kernel/syscallError.h"
5#include "MountView-internal.h"
6#if THREADS && !defined(STANDALONE_MUTEXES)
7#include "pedigree/kernel/process/Thread.h"
8#include "pedigree/kernel/processor/Processor.h"
9#include "pedigree/kernel/processor/ProcessorInformation.h"
13 : m_Node(other.m_Node), m_Tracked(other.m_Tracked) {
14 other.m_Node =
nullptr;
15 other.m_Tracked =
false;
20 m_Node = other.m_Node;
21 m_Tracked = other.m_Tracked;
22 other.m_Node =
nullptr;
23 other.m_Tracked =
false;
27VfsNodeReference::~VfsNodeReference() {
30void VfsNodeReference::reset() {
31#if THREADS && !defined(STANDALONE_MUTEXES)
35 const bool tracked = m_Tracked;
39 node->releaseVfsReference();
42 if (m_Node || !node || !backing || node->getFilesystem() != backing)
44 m_Tracked = node->retainVfsReference();
45 if (!m_Tracked && node != backing->
getRoot())
51bool VfsNodeReference::retainAnonymous(
File* node) {
52 if (m_Node || !node || node->isDirectory() || !node->retainVfsReference())
59VfsAttachment::~VfsAttachment() {
60#if THREADS && !defined(STANDALONE_MUTEXES)
66 FATAL(
"Owned attachment lost its backing registration");
71 : kind(Kind::Mounted), view(owner), attachment(mounted), file(pedigree_std::move(retained)) {
72 attachment->paths += 1;
75 : kind(Kind::Anonymous), view(owner), attachment(), file(pedigree_std::move(retained)) {
76 view.m_State->anonymousPaths += 1;
79#if THREADS && !defined(STANDALONE_MUTEXES)
82 const size_t error = thread ? thread->
getErrno() : 0;
85 if (kind == Kind::Mounted) {
86 if ((attachment->paths -= 1) == 0)
87 view.m_State->reapDetached();
89 view.m_State->anonymousPaths -= 1;
92#if THREADS && !defined(STANDALONE_MUTEXES)
98VfsMountView::VfsMountView(
VFS& vfs) : m_State(new State(*this)), m_Vfs(vfs) {}
99VfsMountView::~VfsMountView() {
102VfsMountView::State::~State() {
103 if (contexts || anonymousPaths)
104 FATAL(
"Mount view destroyed with retained filesystem owners");
105 auto* row = attachments;
106 attachments =
nullptr;
108 if (row->attachment->paths)
109 FATAL(
"Mount view destroyed with retained paths");
110 auto* next = row->next;
117 for (
auto* row = attachments; row; row = row->next)
118 if (row->attachment->id ==
id)
123 for (
auto* row = attachments; row; row = row->next)
124 if (row->parent.get() == path.attachment.
get() && row->covered &&
125 row->covered->get() == path.node())
130 auto* result = reference && reference->provider() == &view
133 return result && &result->view == &view ? result :
nullptr;
136 auto* selected = nodePath(reference);
137 return selected && selected->kind == VfsPath::Kind::Mounted ? selected :
nullptr;
140 auto* p = path(reference);
143 auto* row = find(p->attachment->id);
144 size_t remaining = 1;
145 for (
auto* entry = attachments; entry; entry = entry->next)
147 while (row && remaining--) {
148 if (row->attachment->id == rootId)
150 row = row->parent ? find(row->parent->id) : nullptr;
156 for (
auto* row = contexts; row; row = row->next) {
157 if (row->context.get() == reference.
get()) {
167 if (!attachment || !retained.retain(node, attachment->backing.filesystem())) {
168 SYSCALL_ERROR(DoesNotExist);
174 SYSCALL_ERROR(OutOfMemory);
177 result = pedigree_std::move(path);
181bool VfsMountView::initialise(
Filesystem* bootRoot) {
182 if (!m_State || !bootRoot) {
183 SYSCALL_ERROR(OutOfMemory);
187 if (!m_Vfs.pinFilesystem(bootRoot, pin)) {
188 SYSCALL_ERROR(DoesNotExist);
193 if (!attachment || !row) {
194 SYSCALL_ERROR(OutOfMemory);
197 row.get()->attachment = attachment;
200 if (m_State->rootId) {
201 SYSCALL_ERROR(DeviceBusy);
206 m_State->attachments = row.releaseOwnership();
210#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
211bool VfsMountView::quiescentForHostedTest()
const {
215 if (m_State->contexts || m_State->anonymousPaths)
217 for (
auto* row = m_State->attachments; row; row = row->next)
218 if (row->attachment->paths)
230 auto* row = m_State->find(m_State->rootId);
233 attachment = row->attachment;
235 return m_State->makePath(attachment, attachment->root, result);
238 return m_State && m_State->createContext(
nullptr, result);
242#if THREADS && !defined(STANDALONE_MUTEXES)
246 SYSCALL_ERROR(InvalidArgument);
251 if (!reference || !row) {
252 SYSCALL_ERROR(OutOfMemory);
256 row.get()->context = reference;
265 auto* root = find(rootId);
267 SYSCALL_ERROR(DoesNotExist);
270 attachment = root->attachment;
272 if (!makePath(attachment, attachment->root, initial))
277 if (parent && !parent->registration) {
278 SYSCALL_ERROR(DoesNotExist);
281 created->root = parent ? parent->root : initial;
282 created->cwd = parent ? parent->cwd : initial;
283 created->registration = row.get();
284 row.get()->next = contexts;
285 contexts = row.releaseOwnership();
288 result = FilesystemContextOwner::adopt(pedigree_std::move(reference));
292VfsFilesystemContext::~VfsFilesystemContext() {
294 FATAL(
"Filesystem context destroyed before owner retirement");
302 replacement.root = root;
303 replacement.cwd = cwd;
304 replacement.contextGeneration = generation;
305 replacement.topologyGeneration = view.m_State->topology;
307 result = pedigree_std::move(replacement);
311 return view.m_State->createContext(
this, result);
313void VfsFilesystemContext::retireProcessOwner() {
314#if THREADS && !defined(STANDALONE_MUTEXES)
324 auto** link = &view.m_State->contexts;
325 while (*link && *link != registration)
326 link = &(*link)->next;
328 FATAL(
"Missing filesystem context enrollment");
330 *link = retired->next;
331 registration =
nullptr;
332 --view.m_State->contextCount;
333 retiredRoot = pedigree_std::move(root);
334 retiredCwd = pedigree_std::move(cwd);
340 if (!m_State->path(path) || !path->node()->
isDirectory()) {
341 SYSCALL_ERROR(NotADirectory);
351 if (!m_State->context(context, target)) {
352 SYSCALL_ERROR(DoesNotExist);
355 retired = pedigree_std::move(target->cwd);
357 ++target->generation;
362 if (!m_State->path(path) || !path->node()->
isDirectory()) {
363 SYSCALL_ERROR(NotADirectory);
373 if (!m_State->context(context, target)) {
374 SYSCALL_ERROR(DoesNotExist);
377 retired = pedigree_std::move(target->root);
379 ++target->generation;
384 auto* concrete = m_State ? m_State->path(path) :
nullptr;
385 return concrete ? concrete->attachment->id : 0;
388 auto* first = m_State ? m_State->nodePath(a) :
nullptr;
389 auto* second = m_State ? m_State->nodePath(b) :
nullptr;
390 return first && second && first->kind == second->kind &&
391 first->attachment.get() == second->attachment.get() && first->node() == second->node();
395 if (!m_State || !retained.retainAnonymous(node)) {
396 SYSCALL_ERROR(NotADirectory);
401 SYSCALL_ERROR(OutOfMemory);
404 result = pedigree_std::move(path);
409 auto* path = m_State ? m_State->path(sameAttachment) :
nullptr;
411 SYSCALL_ERROR(InvalidArgument);
414 return m_State->makePath(path->attachment, node, result);
virtual bool isDirectory()
virtual File * getRoot() const =0
static ProcessorInformation & information()
static SharedPointer< FilesystemPath > tryAdopt(FilesystemPath *ptr)
void setErrno(size_t err)
static UniquePointer< T > adopt(T *pointer)
bool retireOwnedFilesystem(Filesystem *filesystem)
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)