2#include "pedigree/kernel/syscallError.h"
4#include "MountView-internal.h"
16 auto* next = first->next;
26 auto* sourceView = fromPath(source);
27 auto* sourceState = sourceView ? sourceView->m_State :
nullptr;
28 auto* from = sourceState ? sourceState->path(source) :
nullptr;
29 auto* to = m_State->path(target);
30 if (fromContext(context) !=
this || !from || !to || !context->snapshot(snapshot) ||
31 !m_State->beneath(target, snapshot.root) ||
32 from->node()->isDirectory() != to->node()->isDirectory()) {
33 SYSCALL_ERROR(InvalidArgument);
36 if (!sourceState->contains(source) || !m_State->contains(target) || m_State->at(*to)) {
37 SYSCALL_ERROR(DeviceBusy);
40 if (!sourceState->snapshotRows(rows)) {
43 const size_t capacity = rows.
count() + 1;
44 if (!copies.tryReserve(capacity)) {
45 SYSCALL_ERROR(OutOfMemory);
49 primary.original = from->attachment->id;
52 primary.row->next = staged.first;
53 staged.first = primary.row;
56 if (!primary.row || !covered ||
57 !covered->retain(to->node(), to->attachment->backing->pin.filesystem()) ||
58 !m_State->makeAttachment(from->attachment->backing, from->node(), from->attachment->flags,
59 primary.row->attachment)) {
60 SYSCALL_ERROR(OutOfMemory);
63 primary.row->parent = to->attachment;
64 primary.row->attachment->lockedFlags = from->attachment->lockedFlags;
65 if (sourceView->ownerNamespace() != ownerNamespace()) {
66 primary.row->attachment->lockedFlags |= from->attachment->flags;
68 primary.row->covered = covered;
69 copies.
pushBack(pedigree_std::move(primary));
70 if (recursive && from->node()->isDirectory()) {
71 for (
auto& item : rows) {
73 if (row->attachment.get() == from->attachment.get()) {
77 if (!sourceState->makePath(row->attachment, row->attachment->root, mounted)) {
80 if (!sourceState->contains(mounted) || !sourceState->beneath(mounted, source)) {
84 copied.original = row->attachment->id;
87 copied.row->next = staged.first;
88 staged.first = copied.row;
90 if (!copied.row || !m_State->makeAttachment(row->attachment->backing, row->attachment->root,
91 row->attachment->flags, copied.row->attachment)) {
94 copied.row->covered = row->covered;
95 copied.row->attachment->lockedFlags = row->attachment->lockedFlags;
96 copied.row->attachment->lockedMount = row->attachment->lockedMount;
97 if (sourceView->ownerNamespace() != ownerNamespace()) {
98 copied.row->attachment->lockedFlags |= row->attachment->flags;
99 copied.row->attachment->lockedMount =
true;
101 copies.
pushBack(pedigree_std::move(copied));
103 for (
size_t i = 1; i < copies.
count(); ++i) {
105 for (
auto& row : rows) {
106 if (row.attachment->id == copies[i].original) {
111 for (
auto& parent : copies) {
112 if (original->parent && parent.original == original->parent->id) {
113 copies[i].row->parent = parent.row->attachment;
117 if (!copies[i].row->parent) {
118 SYSCALL_ERROR(InvalidArgument);
125 for (
auto& copy : copies) {
126 copy.row->next = m_State->attachments;
127 m_State->attachments = copy.row;
129 staged.first =
nullptr;
136 auto* selected = m_State ? m_State->path(path) :
nullptr;
137 return selected ? uint64_t(selected->attachment->flags) : 0;
140VfsMountView::WriteLease::~WriteLease() {
141 if (
auto* view = fromPath(m_Path)) {
142 auto* path = view->m_State->path(m_Path);
144 path->attachment->writers -= 1;
151 SYSCALL_ERROR(InvalidArgument);
154 auto* view = fromPath(reference);
156 SYSCALL_ERROR(InvalidArgument);
160 if (!view->writable(reference)) {
163 auto* path = view->m_State->path(reference);
165 path->attachment->writers += 1;
175 SYSCALL_ERROR(OutOfMemory);
178 if (!
static_cast<WriteLease*
>(lease.get())->acquire(path)) {
181 result = pedigree_std::move(lease);
186 if (!m_State || !m_State->nodePath(path)) {
187 SYSCALL_ERROR(InvalidArgument);
190 auto* filesystem = path->node()->getFilesystem();
191 if ((mountFlags(path) & ReadOnly) || (filesystem && filesystem->isReadOnly())) {
192 SYSCALL_ERROR(ReadOnlyFilesystem);
199 uint64_t flags,
bool recursive) {
200 if (flags & ~SupportedMountFlags) {
201 SYSCALL_ERROR(InvalidArgument);
208 auto* mounted = m_State->path(target);
209 if (fromContext(context) !=
this || !mounted || !context->snapshot(snapshot) ||
210 mounted->node() != mounted->attachment->root || !m_State->contains(target) ||
211 !m_State->beneath(target, snapshot.root)) {
212 SYSCALL_ERROR(InvalidArgument);
215 if (!m_State->snapshotRows(rows)) {
218 for (
auto& item : rows) {
220 bool included = row->attachment.get() == mounted->attachment.get();
221 if (recursive && !included) {
222 for (
auto* parent = row; parent && parent->parent;) {
223 if (parent->parent.get() == mounted->attachment.get()) {
228 for (
auto& candidate : rows) {
229 if (candidate.attachment.get() == parent->parent.get()) {
238 if (!selected.tryReserve(selected.
count() + 1)) {
239 SYSCALL_ERROR(OutOfMemory);
247 for (
auto& attachment : selected) {
248 if ((flags & attachment->lockedFlags) != attachment->lockedFlags) {
249 SYSCALL_ERROR(NotEnoughPermissions);
252 if ((flags & ReadOnly) && !(attachment->flags & ReadOnly) && attachment->writers) {
253 SYSCALL_ERROR(DeviceBusy);
257 for (
auto& attachment : selected) {
258 auto* mountedAttachment = attachment.get();
259 if (!mountedAttachment) {
260 FATAL(
"Missing prepared mount attachment");
262 mountedAttachment->flags = flags;
274 if (!pin.identity().acquire(operation)) {
275 SYSCALL_ERROR(DeviceDoesNotExist);
278 auto* point = path(covered);
279 if (!writer.protects(view.m_Vfs) || !point || !point->node()->isDirectory() || !pin) {
280 SYSCALL_ERROR(InvalidArgument);
284 SYSCALL_ERROR(DoesNotExist);
289 if (!contains(covered) || at(*point)) {
290 SYSCALL_ERROR(DeviceBusy);
297 !makeAttachment(backing, backing->pin.filesystem()->getRoot(), flags, attachment)) {
302 if (!attachment || !node || !row) {
303 SYSCALL_ERROR(OutOfMemory);
306 if (!node->retain(point->node(), point->attachment->backing->pin.filesystem())) {
307 SYSCALL_ERROR(DoesNotExist);
310 row.get()->attachment = attachment;
311 row.
get()->parent = point->attachment;
312 row.get()->covered = node;
315 attachment->backing->owningRegistry =
316 ownership == BackingOwnership::Attachment ? &view.m_Vfs :
nullptr;
317 row.get()->next = attachments;
318 attachments = row.releaseOwnership();
325 Filesystem* backing, BackingOwnership ownership, uint64_t flags) {
326 if (flags & ~SupportedMountFlags) {
327 SYSCALL_ERROR(InvalidArgument);
332 ERROR(
"VfsMountView::attach: no internal state");
333 SYSCALL_ERROR(DoesNotExist);
336 if (!m_Vfs.pinFilesystem(backing, pin)) {
337 ERROR(
"VfsMountView::attach: failed to pin filesystem");
338 SYSCALL_ERROR(DoesNotExist);
344 ERROR(
"VfsMountView::attach: no context");
345 SYSCALL_ERROR(InvalidArgument);
348 if (!context->snapshot(snapshot)) {
349 ERROR(
"VfsMountView::attach: failed to snapshot");
350 SYSCALL_ERROR(InvalidArgument);
353 if (!m_State->beneath(covered, snapshot.root)) {
354 ERROR(
"VfsMountView::attach: not an ancestor of " << snapshot.root->node()->getFullPath());
355 SYSCALL_ERROR(InvalidArgument);
359 if (!m_State->attach(covered, pedigree_std::move(pin), writer, ownership, flags)) {
360 ERROR(
"VfsMountView::attach: internal attach failed");
367void VfsMountView::State::reapDetached() {
368#if THREADS && !defined(STANDALONE_MUTEXES)
378 for (
auto* candidate = attachments; candidate; candidate = candidate->next) {
379 if (candidate->parent || candidate->attachment->id == rootId)
382 for (
auto* row = attachments; row && !used; row = row->next) {
383 auto* ancestor = row;
384 while (ancestor && ancestor != candidate)
385 ancestor = ancestor->parent ? find(ancestor->parent->id) : nullptr;
386 if (ancestor && row->attachment->paths)
390 detached = candidate;
400 for (
auto** link = &attachments; *link; link = &(*link)->next) {
402 auto* ancestor = row;
403 while (ancestor && ancestor != detached)
404 ancestor = ancestor->parent ? find(ancestor->parent->id) : nullptr;
408 for (
auto* check = attachments; check; check = check->next)
409 if (check->parent.get() == row->attachment.get())
417 FATAL(
"Cyclic detached attachment graph");
418 auto* row = *selected;
419 const bool last = row == detached;
420 *selected = row->next;
430 auto* next = retired->next;
437 if (!m_State || !context) {
438 SYSCALL_ERROR(InvalidArgument);
447 options.requireDirectory =
false;
448 if (!context->snapshot(snapshot) ||
449 !m_State->resolve(snapshot, snapshot.cwd, target,
options, mounted, &writer))
451 if (!m_State->cross(mounted, mounted)) {
454 auto* path = m_State->path(mounted);
457 auto* row = path ? m_State->find(path->attachment->id) :
nullptr;
458 if (!row || !m_State->contains(mounted) || path->node() != path->attachment->root) {
459 SYSCALL_ERROR(InvalidArgument);
462 if (row->attachment->id == m_State->rootId) {
463 SYSCALL_ERROR(DeviceBusy);
466 if (row->attachment->lockedMount) {
467 SYSCALL_ERROR(NotEnoughPermissions);
472 if (row->attachment->paths != 1 || mounted.
refcount() != 1) {
473 SYSCALL_ERROR(DeviceBusy);
476 for (
auto* child = m_State->attachments; child; child = child->next) {
477 if (child->parent.get() == row->attachment.get()) {
478 SYSCALL_ERROR(DeviceBusy);
483 retiredParent = pedigree_std::move(row->parent);
484 retiredCovered = pedigree_std::move(row->covered);
492 if (!m_State || !context) {
493 SYSCALL_ERROR(InvalidArgument);
505 options.requireDirectory =
true;
506 if (!context->snapshot(snapshot) ||
507 !m_State->resolve(snapshot, snapshot.cwd, newRoot,
options, newPath, &writer) ||
508 !m_State->resolve(snapshot, snapshot.cwd, putOld,
options, oldPath, &writer))
510 auto* callerRoot = m_State->path(snapshot.root);
511 auto* nextRoot = m_State->path(newPath);
512 auto* oldMountpoint = m_State->path(oldPath);
513 if (!callerRoot || !nextRoot || !oldMountpoint) {
514 SYSCALL_ERROR(InvalidArgument);
517 const bool stacked = samePath(newPath, oldPath);
518 if (callerRoot->node() != callerRoot->attachment->root ||
519 nextRoot->node() != nextRoot->attachment->root ||
520 callerRoot->attachment.get() == nextRoot->attachment.get() ||
521 oldMountpoint->attachment.get() == callerRoot->attachment.get() ||
522 !m_State->beneath(newPath, snapshot.root) || !m_State->beneath(oldPath, newPath)) {
523 SYSCALL_ERROR(InvalidArgument);
527 SYSCALL_ERROR(DoesNotExist);
530 if (!stacked && oldMountpoint->node() == oldMountpoint->attachment->root) {
531 SYSCALL_ERROR(OperationNotSupported);
537 count = m_State->contextCount;
538 auto* previous = m_State->find(callerRoot->attachment->id);
539 auto* next = m_State->find(nextRoot->attachment->id);
540 if (next && next->attachment->lockedMount) {
541 SYSCALL_ERROR(NotEnoughPermissions);
544 if (!previous || !next || !m_State->contains(newPath) || !m_State->contains(oldPath) ||
545 m_State->at(*oldMountpoint)) {
546 SYSCALL_ERROR(DeviceBusy);
550 if (count > ~
size_t(0) / 2 || !retiredPaths.tryReserve(count * 2)) {
551 SYSCALL_ERROR(OutOfMemory);
556 SYSCALL_ERROR(OutOfMemory);
559 if (!putOldNode->retain(oldMountpoint->node(),
560 oldMountpoint->attachment->backing->pin.filesystem())) {
561 SYSCALL_ERROR(DoesNotExist);
566 auto* previous = m_State->find(callerRoot->attachment->id);
567 auto* next = m_State->find(nextRoot->attachment->id);
570 retiredNewParent = pedigree_std::move(next->parent);
571 retiredNewCovered = pedigree_std::move(next->covered);
572 retiredOldParent = pedigree_std::move(previous->parent);
573 retiredOldCovered = pedigree_std::move(previous->covered);
574 next->parent = retiredOldParent;
575 next->covered = retiredOldCovered;
576 previous->parent = oldMountpoint->attachment;
577 previous->covered = putOldNode;
578 if (m_State->rootId == previous->attachment->id)
579 m_State->rootId = next->attachment->id;
580 for (
auto* row = m_State->contexts; row; row = row->next) {
582 bool changed =
false;
583 if (samePath(fs->root, snapshot.root)) {
584 retiredPaths.
pushBack(pedigree_std::move(fs->root));
588 if (samePath(fs->cwd, snapshot.root)) {
589 retiredPaths.
pushBack(pedigree_std::move(fs->cwd));
601bool VfsMountView::detachBackingForShutdown(
Filesystem* backing) {
602#if THREADS && !defined(STANDALONE_MUTEXES)
605 if (!m_State || !backing)
611 for (
auto* row = m_State->attachments; row; row = row->next) {
612 if (row->attachment->backing->pin.filesystem() != backing)
614 if (row->attachment->id == m_State->rootId || row->attachment->paths) {
615 SYSCALL_ERROR(DeviceBusy);
618 for (
auto* child = m_State->attachments; child; child = child->next) {
619 if (child->parent.get() == row->attachment.get() &&
620 child->attachment->backing->pin.filesystem() != backing) {
621 SYSCALL_ERROR(DeviceBusy);
626 for (
auto** link = &m_State->attachments; *link;) {
628 if (row->attachment->backing->pin.filesystem() != backing) {
639 auto* next = retired->next;
646bool VfsMountView::detachBackingForRemoval(
Filesystem* backing) {
652 for (
auto* row = m_State->attachments; row; row = row->next) {
653 if (row->attachment->backing->pin.filesystem() != backing) {
656 if (row->attachment->id == m_State->rootId) {
657 SYSCALL_ERROR(DeviceBusy);
660 parents.
pushBack(pedigree_std::move(row->parent));
661 covered.
pushBack(pedigree_std::move(row->covered));
662 row->attachment->backing->owningRegistry =
nullptr;
666 m_State->reapDetached();
675 if (m_State->contexts || m_State->anonymousPaths) {
676 SYSCALL_ERROR(DeviceBusy);
679 size_t ownedCount = 0;
680 for (
auto* row = m_State->attachments; row; row = row->next) {
681 if (row->attachment->paths) {
682 SYSCALL_ERROR(DeviceBusy);
685 size_t localOwners = 0;
686 for (
auto* other = m_State->attachments; other; other = other->next) {
687 if (other->attachment->backing.get() == row->attachment->backing.get()) {
691 if (row->attachment->backing.refcount() > localOwners) {
692 SYSCALL_ERROR(DeviceBusy);
695 if (row->attachment->backing->owningRegistry)
698 if (!ownedBackings.tryReserve(ownedBackings.
count() + ownedCount)) {
699 SYSCALL_ERROR(OutOfMemory);
702 for (
auto* row = m_State->attachments; row; row = row->next) {
703 if (row->attachment->backing->owningRegistry) {
704 ownedBackings.
pushBack(row->attachment->backing->pin.filesystem());
707 row->attachment->backing->owningRegistry =
nullptr;
710 retired = m_State->attachments;
711 m_State->attachments =
nullptr;
716 auto* next = retired->next;
static Directory * fromFile(File *pF)
static SharedPointer< T > tryAdopt(T *ptr)
static UniquePointer< T > adopt(T *pointer)
A vector / dynamic array.
void pushBack(const T &value)