2#include "pedigree/kernel/syscallError.h"
4#include "MountView-internal.h"
8 auto* point = path(covered);
9 if (!writer.protects(view.m_Vfs) || !point || !point->node()->isDirectory() || !pin) {
10 SYSCALL_ERROR(InvalidArgument);
13 if (point->node() == point->attachment->root) {
14 SYSCALL_ERROR(OperationNotSupported);
18 SYSCALL_ERROR(DoesNotExist);
24 if (!contains(covered) || at(*point)) {
25 SYSCALL_ERROR(DeviceBusy);
28 if (nextId > 0x7fffffffU) {
29 SYSCALL_ERROR(OutOfMemory);
37 if (!attachment || !node || !row) {
38 SYSCALL_ERROR(OutOfMemory);
41 if (!node->retain(point->node(), point->attachment->backing.filesystem())) {
42 SYSCALL_ERROR(DoesNotExist);
45 row.get()->attachment = attachment;
46 row.get()->parent = point->attachment;
47 row.get()->covered = node;
50 attachment->owningRegistry = ownership == BackingOwnership::Attachment ? &view.m_Vfs :
nullptr;
51 row.get()->next = attachments;
52 attachments = row.releaseOwnership();
59 Filesystem* backing, BackingOwnership ownership) {
62 ERROR(
"VfsMountView::attach: no internal state");
63 SYSCALL_ERROR(DoesNotExist);
66 if (!m_Vfs.pinFilesystem(backing, pin)) {
67 ERROR(
"VfsMountView::attach: failed to pin filesystem");
68 SYSCALL_ERROR(DoesNotExist);
74 ERROR(
"VfsMountView::attach: no context");
75 SYSCALL_ERROR(InvalidArgument);
78 if (!context->snapshot(snapshot)) {
79 ERROR(
"VfsMountView::attach: failed to snapshot");
80 SYSCALL_ERROR(InvalidArgument);
83 if (!m_State->beneath(covered, snapshot.root)) {
84 ERROR(
"VfsMountView::attach: not an ancestor of " << snapshot.root->node()->getFullPath());
85 SYSCALL_ERROR(InvalidArgument);
89 if (!m_State->attach(covered, pedigree_std::move(pin), writer, ownership)) {
90 ERROR(
"VfsMountView::attach: internal attach failed");
97void VfsMountView::State::reapDetached() {
98#if THREADS && !defined(STANDALONE_MUTEXES)
108 for (
auto* candidate = attachments; candidate; candidate = candidate->next) {
109 if (candidate->parent || candidate->attachment->id == rootId)
112 for (
auto* row = attachments; row && !used; row = row->next) {
113 auto* ancestor = row;
114 while (ancestor && ancestor != candidate)
115 ancestor = ancestor->parent ? find(ancestor->parent->id) : nullptr;
116 if (ancestor && row->attachment->paths)
120 detached = candidate;
130 for (
auto** link = &attachments; *link; link = &(*link)->next) {
132 auto* ancestor = row;
133 while (ancestor && ancestor != detached)
134 ancestor = ancestor->parent ? find(ancestor->parent->id) : nullptr;
138 for (
auto* check = attachments; check; check = check->next)
139 if (check->parent.get() == row->attachment.get())
147 FATAL(
"Cyclic detached attachment graph");
148 auto* row = *selected;
149 const bool last = row == detached;
150 *selected = row->next;
160 auto* next = retired->next;
167 if (!m_State || !context) {
168 SYSCALL_ERROR(InvalidArgument);
177 options.requireDirectory =
true;
178 if (!context->snapshot(snapshot) ||
179 !m_State->resolve(snapshot, snapshot.cwd, target,
options, mounted, &writer))
181 auto* path = m_State->path(mounted);
184 auto* row = path ? m_State->find(path->attachment->id) :
nullptr;
185 if (!row || !m_State->contains(mounted) || path->node() != path->attachment->root) {
186 SYSCALL_ERROR(InvalidArgument);
189 if (row->attachment->id == m_State->rootId) {
190 SYSCALL_ERROR(DeviceBusy);
195 if (row->attachment->paths != 1 || mounted.
refcount() != 1) {
196 SYSCALL_ERROR(DeviceBusy);
199 for (
auto* child = m_State->attachments; child; child = child->next) {
200 if (child->parent.get() == row->attachment.get()) {
201 SYSCALL_ERROR(DeviceBusy);
206 retiredParent = pedigree_std::move(row->parent);
207 retiredCovered = pedigree_std::move(row->covered);
215 if (!m_State || !context) {
216 SYSCALL_ERROR(InvalidArgument);
228 options.requireDirectory =
true;
229 if (!context->snapshot(snapshot) ||
230 !m_State->resolve(snapshot, snapshot.cwd, newRoot,
options, newPath, &writer) ||
231 !m_State->resolve(snapshot, snapshot.cwd, putOld,
options, oldPath, &writer))
233 auto* callerRoot = m_State->path(snapshot.root);
234 auto* nextRoot = m_State->path(newPath);
235 auto* oldMountpoint = m_State->path(oldPath);
236 if (!callerRoot || !nextRoot || !oldMountpoint) {
237 SYSCALL_ERROR(InvalidArgument);
240 if (samePath(newPath, oldPath)) {
241 SYSCALL_ERROR(OperationNotSupported);
244 if (callerRoot->node() != callerRoot->attachment->root ||
245 nextRoot->node() != nextRoot->attachment->root ||
246 callerRoot->attachment.get() == nextRoot->attachment.get() ||
247 oldMountpoint->attachment.get() == callerRoot->attachment.get() ||
248 !m_State->beneath(newPath, snapshot.root) || !m_State->beneath(oldPath, newPath)) {
249 SYSCALL_ERROR(InvalidArgument);
253 SYSCALL_ERROR(DoesNotExist);
256 if (oldMountpoint->node() == oldMountpoint->attachment->root) {
257 SYSCALL_ERROR(OperationNotSupported);
263 count = m_State->contextCount;
264 auto* previous = m_State->find(callerRoot->attachment->id);
265 auto* next = m_State->find(nextRoot->attachment->id);
266 if (!previous || !next || !m_State->contains(newPath) || !m_State->contains(oldPath) ||
267 m_State->at(*oldMountpoint)) {
268 SYSCALL_ERROR(DeviceBusy);
272 if (count > ~
size_t(0) / 2 || !retiredPaths.tryReserve(count * 2)) {
273 SYSCALL_ERROR(OutOfMemory);
278 SYSCALL_ERROR(OutOfMemory);
281 if (!putOldNode->retain(oldMountpoint->node(), oldMountpoint->attachment->backing.filesystem())) {
282 SYSCALL_ERROR(DoesNotExist);
287 auto* previous = m_State->find(callerRoot->attachment->id);
288 auto* next = m_State->find(nextRoot->attachment->id);
291 retiredNewParent = pedigree_std::move(next->parent);
292 retiredNewCovered = pedigree_std::move(next->covered);
293 retiredOldParent = pedigree_std::move(previous->parent);
294 retiredOldCovered = pedigree_std::move(previous->covered);
295 next->parent = retiredOldParent;
296 next->covered = retiredOldCovered;
297 previous->parent = oldMountpoint->attachment;
298 previous->covered = putOldNode;
299 if (m_State->rootId == previous->attachment->id)
300 m_State->rootId = next->attachment->id;
301 for (
auto* row = m_State->contexts; row; row = row->next) {
303 bool changed =
false;
304 if (samePath(fs->root, snapshot.root)) {
305 retiredPaths.
pushBack(pedigree_std::move(fs->root));
309 if (samePath(fs->cwd, snapshot.root)) {
310 retiredPaths.
pushBack(pedigree_std::move(fs->cwd));
322bool VfsMountView::detachBackingForShutdown(
Filesystem* backing) {
323#if THREADS && !defined(STANDALONE_MUTEXES)
326 if (!m_State || !backing)
332 for (
auto* row = m_State->attachments; row; row = row->next) {
333 if (row->attachment->backing.filesystem() != backing)
335 if (row->attachment->id == m_State->rootId || row->attachment->paths) {
336 SYSCALL_ERROR(DeviceBusy);
339 for (
auto* child = m_State->attachments; child; child = child->next) {
340 if (child->parent.get() == row->attachment.get() &&
341 child->attachment->backing.filesystem() != backing) {
342 SYSCALL_ERROR(DeviceBusy);
347 for (
auto** link = &m_State->attachments; *link;) {
349 if (row->attachment->backing.filesystem() != backing) {
360 auto* next = retired->next;
372 if (m_State->contexts || m_State->anonymousPaths) {
373 SYSCALL_ERROR(DeviceBusy);
376 size_t ownedCount = 0;
377 for (
auto* row = m_State->attachments; row; row = row->next) {
378 if (row->attachment->paths) {
379 SYSCALL_ERROR(DeviceBusy);
382 if (row->attachment->owningRegistry)
385 if (!ownedBackings.tryReserve(ownedBackings.
count() + ownedCount)) {
386 SYSCALL_ERROR(OutOfMemory);
389 for (
auto* row = m_State->attachments; row; row = row->next) {
390 if (row->attachment->owningRegistry) {
391 ownedBackings.
pushBack(row->attachment->backing.filesystem());
394 row->attachment->owningRegistry =
nullptr;
397 retired = m_State->attachments;
398 m_State->attachments =
nullptr;
403 auto* next = retired->next;
static Directory * fromFile(File *pF)
static SharedPointer< VfsAttachment > tryAdopt(VfsAttachment *ptr)
static UniquePointer< T > adopt(T *pointer)
A vector / dynamic array.
void pushBack(const T &value)