mirror of
https://github.com/SerenityOS/serenity
synced 2026-04-25 17:15:42 +02:00
That functionality seems to be too much complicated. We shouldn't overengineer how the copy_mount syscall works, so instead of allowing replacement of the root filesystem, let's make the unshare file descriptor to be configured via a special ioctl call before we initialize a new VFSRootContext object. The special ioctl can either set a new root filesystem for the upcoming VFSRootContext object, or remove it (by passing fd of -1). If there's no specified root filesystem, a new RAMFS instance will be created automatically when invoking the unshare_create syscall. This also simplifies the code in the boot process, hence making it much more readable. It should be noted, that we assumed during pivot_root that the first mountpoint in a context is the root mountpoint, which is probably a fair assumption, but we don't assume this anywhere else in the VFSRootContext code. If this functionality ever comes back, we should ensure that we make some effort to not assume this again.
117 lines
4.1 KiB
C++
117 lines
4.1 KiB
C++
/*
|
|
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/IntrusiveList.h>
|
|
#include <AK/Noncopyable.h>
|
|
#include <AK/RefPtr.h>
|
|
#include <AK/SetOnce.h>
|
|
#include <Kernel/FileSystem/Custody.h>
|
|
#include <Kernel/FileSystem/FileBackedFileSystem.h>
|
|
#include <Kernel/FileSystem/FileSystem.h>
|
|
#include <Kernel/FileSystem/Mount.h>
|
|
#include <Kernel/Forward.h>
|
|
#include <Kernel/Locking/SpinlockProtected.h>
|
|
|
|
namespace Kernel {
|
|
|
|
class VFSRootContext : public AtomicRefCounted<VFSRootContext> {
|
|
AK_MAKE_NONCOPYABLE(VFSRootContext);
|
|
AK_MAKE_NONMOVABLE(VFSRootContext);
|
|
|
|
public:
|
|
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, IndexID);
|
|
|
|
static VFSRootContext const& empty_context_for_kernel_processes();
|
|
static Custody const& empty_context_custody_for_kernel_processes();
|
|
static void initialize_empty_ramfs_root_context_for_kernel_processes();
|
|
|
|
enum class AddToGlobalContextList {
|
|
Yes,
|
|
No,
|
|
};
|
|
static ErrorOr<NonnullRefPtr<VFSRootContext>> create_with_empty_ramfs(AddToGlobalContextList);
|
|
static ErrorOr<NonnullRefPtr<VFSRootContext>> create_with_filesystem(AddToGlobalContextList, FileSystem&);
|
|
static ErrorOr<NonnullRefPtr<VFSRootContext>> create_empty();
|
|
|
|
SpinlockProtected<NonnullRefPtr<Custody>, LockRank::None>& root_custody() { return m_root_custody; }
|
|
SpinlockProtected<NonnullRefPtr<Custody>, LockRank::None> const& root_custody() const { return m_root_custody; }
|
|
|
|
enum class DoBindMount {
|
|
Yes,
|
|
No,
|
|
};
|
|
ErrorOr<void> add_new_mount(DoBindMount, Inode& source, Custody& mount_point, int flags);
|
|
|
|
ErrorOr<void> do_full_teardown(Badge<PowerStateSwitchTask>);
|
|
|
|
ErrorOr<void> unmount(FileBackedFileSystem::List& file_backed_file_systems_list, Inode& guest_inode, StringView custody_path);
|
|
|
|
ErrorOr<void> apply_to_mount_for_host_custody(Custody const& current_custody, Function<void(Mount&)>);
|
|
|
|
ErrorOr<NonnullRefPtr<FileSystem>> mount_point_to_guest_filesystem(Custody const& custody);
|
|
|
|
struct CurrentMountState {
|
|
Mount::Details details;
|
|
int flags { 0 };
|
|
};
|
|
ErrorOr<CurrentMountState> current_mount_state_for_host_custody(Custody const& current_custody) const;
|
|
|
|
IndexID id() const { return m_id; }
|
|
|
|
void attach(Badge<Process>);
|
|
void detach(Badge<Process>);
|
|
|
|
ErrorOr<void> for_each_mount(Function<ErrorOr<void>(Mount const&)>) const;
|
|
|
|
private:
|
|
VFSRootContext(NonnullRefPtr<Custody> custody);
|
|
|
|
enum class ValidateImmutableFlag {
|
|
Yes,
|
|
No,
|
|
};
|
|
ErrorOr<void> do_on_mount_for_host_custody(ValidateImmutableFlag validate_immutable_flag, Custody const& current_custody, Function<void(Mount&)> callback) const;
|
|
|
|
static void add_to_mounts_list_and_increment_fs_mounted_count(DoBindMount do_bind_mount, IntrusiveList<&Mount::m_vfs_list_node>&, NonnullOwnPtr<Mount>);
|
|
|
|
struct Details {
|
|
SetOnce attached_by_process;
|
|
size_t attach_count { 0 };
|
|
IntrusiveList<&Mount::m_vfs_list_node> mounts;
|
|
};
|
|
|
|
bool mount_point_exists_at_custody(Custody& mount_point, Details& details);
|
|
|
|
static inline ErrorOr<void> validate_mount_not_immutable_while_being_used(Details& details, Mount& mount)
|
|
{
|
|
if (mount.is_immutable() && details.attach_count > 0)
|
|
return Error::from_errno(EPERM);
|
|
return {};
|
|
}
|
|
|
|
mutable SpinlockProtected<Details, LockRank::None> m_details {};
|
|
|
|
SpinlockProtected<NonnullRefPtr<Custody>, LockRank::None> m_root_custody;
|
|
|
|
IntrusiveListNode<VFSRootContext, NonnullRefPtr<VFSRootContext>> m_list_node;
|
|
|
|
IndexID m_id;
|
|
|
|
// NOTE: This method is implemented in Kernel/FileSystem/VirtualFileSystem.cpp
|
|
static SpinlockProtected<IntrusiveList<&VFSRootContext::m_list_node>, LockRank::FileSystem>& all_root_contexts_list();
|
|
|
|
public:
|
|
using List = IntrusiveList<&VFSRootContext::m_list_node>;
|
|
|
|
// NOTE: These methods are implemented in Kernel/FileSystem/VirtualFileSystem.cpp
|
|
static SpinlockProtected<VFSRootContext::List, LockRank::FileSystem>& all_root_contexts_list(Badge<PowerStateSwitchTask>);
|
|
static SpinlockProtected<VFSRootContext::List, LockRank::FileSystem>& all_root_contexts_list(Badge<Process>);
|
|
};
|
|
|
|
}
|