mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:47:46 +00:00
Kernel: Added unmount ability to VFS
It is now possible to unmount file systems from the VFS via `umount`. It works via looking up the `fsid` of the filesystem from the `Inode`'s metatdata so I'm not sure how fragile it is. It seems to work for now though as something to get us going.
This commit is contained in:
parent
f7251c74a9
commit
bc22456f89
13 changed files with 98 additions and 3 deletions
|
@ -1395,3 +1395,16 @@ unsigned Ext2FS::free_inode_count() const
|
||||||
LOCKER(m_lock);
|
LOCKER(m_lock);
|
||||||
return super_block().s_free_inodes_count;
|
return super_block().s_free_inodes_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KResult Ext2FS::prepare_to_unmount() const
|
||||||
|
{
|
||||||
|
LOCKER(m_lock); // Acquire lock for this FS
|
||||||
|
for (auto it = m_inode_cache.begin(); it != m_inode_cache.end(); ++it) {
|
||||||
|
if (it->value.ptr()->ref_count() > 1)
|
||||||
|
return KResult(-EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg() << "here!";
|
||||||
|
m_inode_cache.clear();
|
||||||
|
return KSuccess;
|
||||||
|
}
|
||||||
|
|
|
@ -69,6 +69,8 @@ public:
|
||||||
virtual unsigned total_inode_count() const override;
|
virtual unsigned total_inode_count() const override;
|
||||||
virtual unsigned free_inode_count() const override;
|
virtual unsigned free_inode_count() const override;
|
||||||
|
|
||||||
|
virtual KResult prepare_to_unmount() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef unsigned BlockIndex;
|
typedef unsigned BlockIndex;
|
||||||
typedef unsigned GroupIndex;
|
typedef unsigned GroupIndex;
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/RefPtr.h>
|
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <AK/kstdio.h>
|
#include <AK/kstdio.h>
|
||||||
#include <Kernel/Devices/DiskDevice.h>
|
#include <Kernel/Devices/DiskDevice.h>
|
||||||
|
@ -45,6 +45,8 @@ public:
|
||||||
virtual unsigned total_inode_count() const { return 0; }
|
virtual unsigned total_inode_count() const { return 0; }
|
||||||
virtual unsigned free_inode_count() const { return 0; }
|
virtual unsigned free_inode_count() const { return 0; }
|
||||||
|
|
||||||
|
virtual KResult prepare_to_unmount() const { return KSuccess; }
|
||||||
|
|
||||||
struct DirectoryEntry {
|
struct DirectoryEntry {
|
||||||
DirectoryEntry(const char* name, InodeIdentifier, u8 file_type);
|
DirectoryEntry(const char* name, InodeIdentifier, u8 file_type);
|
||||||
DirectoryEntry(const char* name, int name_length, InodeIdentifier, u8 file_type);
|
DirectoryEntry(const char* name, int name_length, InodeIdentifier, u8 file_type);
|
||||||
|
|
|
@ -49,6 +49,7 @@ KResult VFS::mount(NonnullRefPtr<FS>&& file_system, Custody& mount_point)
|
||||||
|
|
||||||
KResult VFS::mount(NonnullRefPtr<FS>&& file_system, StringView path)
|
KResult VFS::mount(NonnullRefPtr<FS>&& file_system, StringView path)
|
||||||
{
|
{
|
||||||
|
LOCKER(m_lock);
|
||||||
auto result = resolve_path(path, root_custody());
|
auto result = resolve_path(path, root_custody());
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
dbg() << "VFS: mount can't resolve mount point '" << path << "'";
|
dbg() << "VFS: mount can't resolve mount point '" << path << "'";
|
||||||
|
@ -57,6 +58,28 @@ KResult VFS::mount(NonnullRefPtr<FS>&& file_system, StringView path)
|
||||||
return mount(move(file_system), result.value());
|
return mount(move(file_system), result.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KResult VFS::unmount(NonnullRefPtr<FS>&& file_system)
|
||||||
|
{
|
||||||
|
LOCKER(m_lock);
|
||||||
|
dbg() << "VFS: unmount called with fsid " << file_system.ptr()->fsid();
|
||||||
|
|
||||||
|
for (auto i = 0; i < m_mounts.size(); i++) {
|
||||||
|
auto mount = m_mounts.at(i);
|
||||||
|
if (mount.guest_fs().fsid() == file_system.ptr()->fsid()) {
|
||||||
|
if (mount.guest_fs().prepare_to_unmount() != KSuccess) {
|
||||||
|
dbg() << "VFS: Failed to unmount! Device busy";
|
||||||
|
return KResult(-EBUSY);
|
||||||
|
}
|
||||||
|
dbg() << "VFS: found fs " << file_system.ptr()->fsid() << " at mount " << i << "! Unmounting...";
|
||||||
|
m_mounts.remove(i);
|
||||||
|
return KSuccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg() << "VFS: unmount unable to find fsid in m_mounts!";
|
||||||
|
return KResult(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
bool VFS::mount_root(NonnullRefPtr<FS>&& file_system)
|
bool VFS::mount_root(NonnullRefPtr<FS>&& file_system)
|
||||||
{
|
{
|
||||||
if (m_root_inode) {
|
if (m_root_inode) {
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
bool mount_root(NonnullRefPtr<FS>&&);
|
bool mount_root(NonnullRefPtr<FS>&&);
|
||||||
KResult mount(NonnullRefPtr<FS>&&, StringView path);
|
KResult mount(NonnullRefPtr<FS>&&, StringView path);
|
||||||
KResult mount(NonnullRefPtr<FS>&&, Custody& mount_point);
|
KResult mount(NonnullRefPtr<FS>&&, Custody& mount_point);
|
||||||
|
KResult unmount(NonnullRefPtr<FS>&&);
|
||||||
|
|
||||||
KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base);
|
KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base);
|
||||||
KResultOr<NonnullRefPtr<FileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody);
|
KResultOr<NonnullRefPtr<FileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody);
|
||||||
|
@ -105,6 +106,8 @@ private:
|
||||||
Mount* find_mount_for_host(InodeIdentifier);
|
Mount* find_mount_for_host(InodeIdentifier);
|
||||||
Mount* find_mount_for_guest(InodeIdentifier);
|
Mount* find_mount_for_guest(InodeIdentifier);
|
||||||
|
|
||||||
|
Lock m_lock { "VFSLock" };
|
||||||
|
|
||||||
RefPtr<Inode> m_root_inode;
|
RefPtr<Inode> m_root_inode;
|
||||||
NonnullOwnPtrVector<Mount> m_mounts;
|
NonnullOwnPtrVector<Mount> m_mounts;
|
||||||
HashMap<u32, Device*> m_devices;
|
HashMap<u32, Device*> m_devices;
|
||||||
|
|
|
@ -2786,6 +2786,25 @@ int Process::sys$mount(const char* device_path, const char* mountpoint)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Process::sys$umount(const char* mountpoint)
|
||||||
|
{
|
||||||
|
if (!is_superuser())
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (!validate_read_str(mountpoint))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
auto metadata_or_error = VFS::the().lookup_metadata(mountpoint, current_directory());
|
||||||
|
if (metadata_or_error.is_error())
|
||||||
|
return metadata_or_error.error();
|
||||||
|
|
||||||
|
auto fsid = metadata_or_error.value().inode.fsid();
|
||||||
|
auto fs = Ext2FS::from_fsid(fsid);
|
||||||
|
auto ret = VFS::the().unmount(*fs);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ProcessTracer& Process::ensure_tracer()
|
ProcessTracer& Process::ensure_tracer()
|
||||||
{
|
{
|
||||||
if (!m_tracer)
|
if (!m_tracer)
|
||||||
|
|
|
@ -187,6 +187,7 @@ public:
|
||||||
int sys$symlink(const char* target, const char* linkpath);
|
int sys$symlink(const char* target, const char* linkpath);
|
||||||
int sys$rmdir(const char* pathname);
|
int sys$rmdir(const char* pathname);
|
||||||
int sys$mount(const char* device, const char* mountpoint);
|
int sys$mount(const char* device, const char* mountpoint);
|
||||||
|
int sys$umount(const char* mountpoint);
|
||||||
int sys$read_tsc(u32* lsw, u32* msw);
|
int sys$read_tsc(u32* lsw, u32* msw);
|
||||||
int sys$chmod(const char* pathname, mode_t);
|
int sys$chmod(const char* pathname, mode_t);
|
||||||
int sys$fchmod(int fd, mode_t);
|
int sys$fchmod(int fd, mode_t);
|
||||||
|
|
|
@ -189,7 +189,7 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3
|
||||||
case Syscall::SC_sigprocmask:
|
case Syscall::SC_sigprocmask:
|
||||||
return current->process().sys$sigprocmask((int)arg1, (const sigset_t*)arg2, (sigset_t*)arg3);
|
return current->process().sys$sigprocmask((int)arg1, (const sigset_t*)arg2, (sigset_t*)arg3);
|
||||||
case Syscall::SC_pipe:
|
case Syscall::SC_pipe:
|
||||||
return current->process().sys$pipe((int*)arg1, (int) arg2);
|
return current->process().sys$pipe((int*)arg1, (int)arg2);
|
||||||
case Syscall::SC_killpg:
|
case Syscall::SC_killpg:
|
||||||
return current->process().sys$killpg((int)arg1, (int)arg2);
|
return current->process().sys$killpg((int)arg1, (int)arg2);
|
||||||
case Syscall::SC_setuid:
|
case Syscall::SC_setuid:
|
||||||
|
@ -297,6 +297,8 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3
|
||||||
case Syscall::SC_reboot: {
|
case Syscall::SC_reboot: {
|
||||||
return current->process().sys$reboot();
|
return current->process().sys$reboot();
|
||||||
}
|
}
|
||||||
|
case Syscall::SC_umount:
|
||||||
|
return current->process().sys$umount((const char*)arg1);
|
||||||
case Syscall::SC_dump_backtrace:
|
case Syscall::SC_dump_backtrace:
|
||||||
return current->process().sys$dump_backtrace();
|
return current->process().sys$dump_backtrace();
|
||||||
case Syscall::SC_watch_file:
|
case Syscall::SC_watch_file:
|
||||||
|
|
|
@ -117,6 +117,7 @@ struct timeval;
|
||||||
__ENUMERATE_SYSCALL(halt) \
|
__ENUMERATE_SYSCALL(halt) \
|
||||||
__ENUMERATE_SYSCALL(reboot) \
|
__ENUMERATE_SYSCALL(reboot) \
|
||||||
__ENUMERATE_SYSCALL(mount) \
|
__ENUMERATE_SYSCALL(mount) \
|
||||||
|
__ENUMERATE_SYSCALL(umount) \
|
||||||
__ENUMERATE_SYSCALL(dump_backtrace) \
|
__ENUMERATE_SYSCALL(dump_backtrace) \
|
||||||
__ENUMERATE_SYSCALL(dbgputch) \
|
__ENUMERATE_SYSCALL(dbgputch) \
|
||||||
__ENUMERATE_SYSCALL(dbgputstr) \
|
__ENUMERATE_SYSCALL(dbgputstr) \
|
||||||
|
|
|
@ -15,7 +15,7 @@ if [ $(id -u) != 0 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "creating initial filesystem structure... "
|
echo -n "creating initial filesystem structure... "
|
||||||
mkdir -p mnt/{bin,etc,proc,tmp}
|
mkdir -p mnt/{bin,etc,proc,mnt,tmp}
|
||||||
chmod 1777 mnt/tmp
|
chmod 1777 mnt/tmp
|
||||||
echo "done"
|
echo "done"
|
||||||
|
|
||||||
|
|
|
@ -557,6 +557,12 @@ int mount(const char* device, const char* mountpoint)
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int umount(const char* mountpoint)
|
||||||
|
{
|
||||||
|
int rc = syscall(SC_umount, mountpoint);
|
||||||
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
|
}
|
||||||
|
|
||||||
void dump_backtrace()
|
void dump_backtrace()
|
||||||
{
|
{
|
||||||
syscall(SC_dump_backtrace);
|
syscall(SC_dump_backtrace);
|
||||||
|
|
|
@ -101,6 +101,7 @@ int ftruncate(int fd, off_t length);
|
||||||
int halt();
|
int halt();
|
||||||
int reboot();
|
int reboot();
|
||||||
int mount(const char* device, const char* mountpoint);
|
int mount(const char* device, const char* mountpoint);
|
||||||
|
int umount(const char* mountpoint);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
_PC_NAME_MAX,
|
_PC_NAME_MAX,
|
||||||
|
|
22
Userland/umount.cpp
Normal file
22
Userland/umount.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <LibCore/CArgsParser.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
CArgsParser args_parser("umount");
|
||||||
|
args_parser.add_arg("mountpoint", "mount point");
|
||||||
|
CArgsParserResult args = args_parser.parse(argc, argv);
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
if (umount(argv[1]) < 0) {
|
||||||
|
perror("umount");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args_parser.print_usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue