kernel: Move get_mount_point from VMUtils to KPartition.

There's nothing VM-specific about it; it just builds paths
that partitions should be mounted at.

Also move the tests.
This commit is contained in:
Augustin Cavalier 2024-10-16 14:25:17 -04:00
parent b0b1b524f8
commit 0a5c9ef0a4
12 changed files with 227 additions and 334 deletions

View File

@ -115,15 +115,14 @@ public:
virtual status_t GetPath(KPath *path) const;
// no setter (see BDiskDevice) -- built on the fly
status_t GetMountPoint(KPath* mountPoint) const;
void SetVolumeID(dev_t volumeID);
dev_t VolumeID() const;
void SetMountCookie(void *cookie);
void *MountCookie() const;
virtual status_t Mount(uint32 mountFlags, const char *parameters);
virtual status_t Unmount();
// Parameters
status_t SetParameters(const char *parameters);

View File

@ -20,6 +20,7 @@
#include <Errors.h>
#include <fs_volume.h>
#include <KernelExport.h>
#include <StackOrHeapArray.h>
#include <ddm_userland_interface.h>
#include <fs/devfs.h>
@ -729,6 +730,52 @@ KPartition::GetPath(KPath* path) const
}
status_t
KPartition::GetMountPoint(KPath* mountPoint) const
{
if (!mountPoint || !ContainsFileSystem())
return B_BAD_VALUE;
ASSERT(!IsMounted());
// fetching the actual mounted point isn't implemented (yet)
int nameLength = 0;
const char* volumeName = ContentName();
if (volumeName != NULL)
nameLength = strlen(volumeName);
if (nameLength == 0) {
volumeName = Name();
if (volumeName != NULL)
nameLength = strlen(volumeName);
if (nameLength == 0) {
volumeName = "unnamed volume";
nameLength = strlen(volumeName);
}
}
BStackOrHeapArray<char, 128> basePath(nameLength + 2);
if (!basePath.IsValid())
return B_NO_MEMORY;
int32 len = snprintf(basePath, nameLength + 2, "/%s", volumeName);
for (int32 i = 1; i < len; i++)
if (basePath[i] == '/')
basePath[i] = '-';
char* path = mountPoint->LockBuffer();
int32 pathLen = mountPoint->BufferSize();
strncpy(path, basePath, pathLen);
struct stat dummy;
for (int i = 1; ; i++) {
if (stat(path, &dummy) != 0)
break;
snprintf(path, pathLen, "%s%d", (char*)basePath, i);
}
mountPoint->UnlockBuffer();
return B_OK;
}
void
KPartition::SetVolumeID(dev_t volumeID)
{
@ -781,22 +828,6 @@ KPartition::MountCookie() const
}
status_t
KPartition::Mount(uint32 mountFlags, const char* parameters)
{
// not implemented
return B_ERROR;
}
status_t
KPartition::Unmount()
{
// not implemented
return B_ERROR;
}
status_t
KPartition::SetParameters(const char* parameters)
{

View File

@ -24,7 +24,6 @@ KernelMergeObject kernel_vm.o :
VMTranslationMap.cpp
VMUserAddressSpace.cpp
VMUserArea.cpp
VMUtils.cpp
: $(TARGET_KERNEL_PIC_CCFLAGS)
;

View File

@ -58,7 +58,6 @@
#include <vm/VMAddressSpace.h>
#include "IORequest.h"
#include "VMUtils.h"
#if ENABLE_SWAP_SUPPORT
@ -1691,7 +1690,7 @@ swap_init_post_modules()
else {
KPath devPath, mountPoint;
visitor.fBestPartition->GetPath(&devPath);
get_mount_point(visitor.fBestPartition, &mountPoint);
visitor.fBestPartition->GetMountPoint(&mountPoint);
const char* mountPath = mountPoint.Path();
mkdir(mountPath, S_IRWXU | S_IRWXG | S_IRWXO);
swapDeviceID = _kern_mount(mountPath, devPath.Path(),

View File

@ -1,58 +0,0 @@
/*
* Copyright 2011-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hamish Morrison, hamish@lavabit.com
* Alexander von Gluck IV, kallisti5@unixzen.com
*/
#include "VMUtils.h"
#include <stdio.h>
#include <StackOrHeapArray.h>
status_t
get_mount_point(KPartition* partition, KPath* mountPoint)
{
if (!mountPoint || !partition->ContainsFileSystem())
return B_BAD_VALUE;
int nameLength = 0;
const char* volumeName = partition->ContentName();
if (volumeName != NULL)
nameLength = strlen(volumeName);
if (nameLength == 0) {
volumeName = partition->Name();
if (volumeName != NULL)
nameLength = strlen(volumeName);
if (nameLength == 0) {
volumeName = "unnamed volume";
nameLength = strlen(volumeName);
}
}
BStackOrHeapArray<char, 128> basePath(nameLength + 2);
if (!basePath.IsValid())
return B_NO_MEMORY;
int32 len = snprintf(basePath, nameLength + 2, "/%s", volumeName);
for (int32 i = 1; i < len; i++)
if (basePath[i] == '/')
basePath[i] = '-';
char* path = mountPoint->LockBuffer();
int32 pathLen = mountPoint->BufferSize();
strncpy(path, basePath, pathLen);
struct stat dummy;
for (int i = 1; ; i++) {
if (stat(path, &dummy) != 0)
break;
snprintf(path, pathLen, "%s%d", (char*)basePath, i);
}
mountPoint->UnlockBuffer();
return B_OK;
}

View File

@ -1,17 +0,0 @@
/*
* Copyright 2018 Kacper Kasper <kacperkasper@gmail.com>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _KERNEL_VM_UTILS_H
#define _KERNEL_VM_UTILS_H
#include <disk_device_manager/KPartition.h>
#include <fs/KPath.h>
status_t
get_mount_point(KPartition* partition, KPath* mountPoint);
#endif // _KERNEL_VM_UTILS_H

View File

@ -0,0 +1,13 @@
#include <TestSuite.h>
#include <TestSuiteAddon.h>
#include "KPartitionTest.h"
BTestSuite*
getTestSuite()
{
BTestSuite *suite = new BTestSuite("DiskDeviceManager");
suite->addTest("KPartitionGetMountPointTest", KPartitionGetMountPointTest::Suite());
return suite;
}

View File

@ -44,6 +44,12 @@ SharedLibrary test_disk_device_manager.so :
: be libkernelland_emu.so [ TargetLibsupc++ ]
;
UnitTestLib libkerneldiskdevicemanagertest.so :
DiskDeviceManagerTestAddon.cpp
KPartitionTest.cpp
: test_disk_device_manager.so [ TargetLibstdc++ ]
;
SimpleTest DiskDeviceManagerTest :
DiskDeviceManagerTest.cpp
: test_disk_device_manager.so be

View File

@ -0,0 +1,153 @@
/*
* Copyright 2018 Kacper Kasper <kacperkasper@gmail.com>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "KPartitionTest.h"
#include <string.h>
#include <fs/KPath.h>
#include <disk_device_manager/KPartition.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestSuite.h>
#include <TestUtils.h>
struct stat;
extern "C" int
stat(const char* path, struct stat* s)
{
if(strcmp(path, "/testduplicate") == 0)
return 0;
else
return -1;
}
using BPrivate::DiskDevice::KPartition;
// #pragma mark -
KPartitionGetMountPointTest::KPartitionGetMountPointTest(std::string name)
: BTestCase(name)
{
}
#define ADD_TEST(s, cls, m) \
s->addTest(new CppUnit::TestCaller<cls>(#cls "::" #m, &cls::m));
CppUnit::Test*
KPartitionGetMountPointTest::Suite()
{
CppUnit::TestSuite *suite = new CppUnit::TestSuite("KPartitionGetMountPointTest");
ADD_TEST(suite, KPartitionGetMountPointTest, TestPartitionWithoutFilesystemReturnsBadValue);
ADD_TEST(suite, KPartitionGetMountPointTest, TestPartitionContentNameUsedFirst);
ADD_TEST(suite, KPartitionGetMountPointTest, TestPartitionNameUsedSecond);
ADD_TEST(suite, KPartitionGetMountPointTest, TestPartitionWithoutAnyNameIsNotRoot);
ADD_TEST(suite, KPartitionGetMountPointTest, TestPartitionNameWithSlashesRemoved);
ADD_TEST(suite, KPartitionGetMountPointTest, TestPartitionMountPointExists);
return suite;
}
void
KPartitionGetMountPointTest::TestPartitionWithoutFilesystemReturnsBadValue()
{
KPartition partition;
partition.SetName("");
partition.SetContentName("");
partition.SetFlags(0);
KPath path;
status_t status = partition.GetMountPoint(&path);
CPPUNIT_ASSERT_EQUAL(status, B_BAD_VALUE);
}
void
KPartitionGetMountPointTest::TestPartitionContentNameUsedFirst()
{
KPartition partition;
partition.SetName("test1");
partition.SetContentName("test2");
partition.SetFlags(B_PARTITION_FILE_SYSTEM);
KPath path;
status_t status = partition.GetMountPoint(&path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/test2") == 0);
}
void
KPartitionGetMountPointTest::TestPartitionNameUsedSecond()
{
KPartition partition;
partition.SetName("test1");
partition.SetContentName("");
partition.SetFlags(B_PARTITION_FILE_SYSTEM);
KPath path;
status_t status = partition.GetMountPoint(&path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/test1") == 0);
}
void
KPartitionGetMountPointTest::TestPartitionWithoutAnyNameIsNotRoot()
{
KPartition partition;
partition.SetName("");
partition.SetContentName("");
partition.SetFlags(B_PARTITION_FILE_SYSTEM);
KPath path;
status_t status = partition.GetMountPoint(&path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/") != 0);
}
void
KPartitionGetMountPointTest::TestPartitionNameWithSlashesRemoved()
{
KPartition partition;
partition.SetName("");
partition.SetContentName("testing/slashes");
partition.SetFlags(B_PARTITION_FILE_SYSTEM);
KPath path;
status_t status = partition.GetMountPoint(&path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/testing/slashes") != 0);
}
void
KPartitionGetMountPointTest::TestPartitionMountPointExists()
{
KPartition partition;
partition.SetName("");
partition.SetContentName("testduplicate");
partition.SetFlags(B_PARTITION_FILE_SYSTEM);
KPath path;
status_t status = partition.GetMountPoint(&path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/testduplicate") != 0);
}

View File

@ -2,19 +2,18 @@
* Copyright 2018 Kacper Kasper <kacperkasper@gmail.com>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef _VM_GET_MOUNT_POINT_TEST_H_
#define _VM_GET_MOUNT_POINT_TEST_H_
#ifndef _KPARTITION_TEST_H_
#define _KPARTITION_TEST_H_
#include <TestCase.h>
class VMGetMountPointTest : public BTestCase {
class KPartitionGetMountPointTest : public BTestCase {
public:
VMGetMountPointTest(std::string name = "");
KPartitionGetMountPointTest(std::string name = "");
static CppUnit::Test *Suite();
void TestNullMountPointReturnsBadValue();
void TestPartitionWithoutFilesystemReturnsBadValue();
void TestPartitionContentNameUsedFirst();
void TestPartitionNameUsedSecond();
@ -23,4 +22,4 @@ class VMGetMountPointTest : public BTestCase {
void TestPartitionMountPointExists();
};
#endif /* _VM_GET_MOUNT_POINT_TEST_H_ */
#endif /* _KPARTITION_TEST_H_ */

View File

@ -1,13 +0,0 @@
#include <TestSuite.h>
#include <TestSuiteAddon.h>
#include "VMGetMountPointTest.h"
BTestSuite*
getTestSuite()
{
BTestSuite *suite = new BTestSuite("KernelVM");
suite->addTest("VMGetMountPointTest", VMGetMountPointTest::Suite());
return suite;
}

View File

@ -1,218 +0,0 @@
/*
* Copyright 2018 Kacper Kasper <kacperkasper@gmail.com>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "VMGetMountPointTest.h"
#include <string.h>
#include <fs/KPath.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestSuite.h>
#include <TestUtils.h>
// Kernel stubs
extern "C" team_id
team_get_kernel_team_id(void)
{
return 0;
}
extern "C" team_id
team_get_current_team_id(void)
{
return 0;
}
extern "C" status_t
vfs_normalize_path(const char* path, char* buffer, size_t bufferSize,
bool traverseLink, bool kernel)
{
return B_NOT_SUPPORTED;
}
struct stat;
extern "C" int
stat(const char* path, struct stat* s)
{
if(strcmp(path, "/testduplicate") == 0)
return 0;
else
return -1;
}
namespace BPrivate {
namespace DiskDevice {
class KPartition {
public:
KPartition(std::string name, std::string contentName, bool containsFilesystem)
: fName(name), fContentName(contentName), fContainsFilesystem(containsFilesystem)
{}
const char *Name() const;
const char *ContentName() const;
bool ContainsFileSystem() const;
private:
std::string fName;
std::string fContentName;
bool fContainsFilesystem;
};
const char *
KPartition::Name() const
{
return fName.c_str();
}
const char *
KPartition::ContentName() const
{
return fContentName.c_str();
}
bool
KPartition::ContainsFileSystem() const
{
return fContainsFilesystem;
}
}
}
using BPrivate::DiskDevice::KPartition;
status_t
get_mount_point(KPartition* partition, KPath* mountPoint);
// #pragma mark -
VMGetMountPointTest::VMGetMountPointTest(std::string name)
: BTestCase(name)
{
}
#define ADD_TEST(s, cls, m) \
s->addTest(new CppUnit::TestCaller<cls>(#cls "::" #m, &cls::m));
CppUnit::Test*
VMGetMountPointTest::Suite()
{
CppUnit::TestSuite *suite = new CppUnit::TestSuite("VMGetMountPointTest");
ADD_TEST(suite, VMGetMountPointTest, TestNullMountPointReturnsBadValue);
ADD_TEST(suite, VMGetMountPointTest, TestPartitionWithoutFilesystemReturnsBadValue);
ADD_TEST(suite, VMGetMountPointTest, TestPartitionContentNameUsedFirst);
ADD_TEST(suite, VMGetMountPointTest, TestPartitionNameUsedSecond);
ADD_TEST(suite, VMGetMountPointTest, TestPartitionWithoutAnyNameIsNotRoot);
ADD_TEST(suite, VMGetMountPointTest, TestPartitionNameWithSlashesRemoved);
ADD_TEST(suite, VMGetMountPointTest, TestPartitionMountPointExists);
return suite;
}
void
VMGetMountPointTest::TestNullMountPointReturnsBadValue()
{
status_t status = get_mount_point(NULL, NULL);
CPPUNIT_ASSERT_EQUAL(status, B_BAD_VALUE);
}
void
VMGetMountPointTest::TestPartitionWithoutFilesystemReturnsBadValue()
{
KPartition partition("", "", false);
KPath path;
status_t status = get_mount_point(&partition, &path);
CPPUNIT_ASSERT_EQUAL(status, B_BAD_VALUE);
}
void
VMGetMountPointTest::TestPartitionContentNameUsedFirst()
{
KPartition partition("test1", "test2", true);
KPath path;
status_t status = get_mount_point(&partition, &path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/test2") == 0);
}
void
VMGetMountPointTest::TestPartitionNameUsedSecond()
{
KPartition partition("test1", "", true);
KPath path;
status_t status = get_mount_point(&partition, &path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/test1") == 0);
}
void
VMGetMountPointTest::TestPartitionWithoutAnyNameIsNotRoot()
{
KPartition partition("", "", true);
KPath path;
status_t status = get_mount_point(&partition, &path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/") != 0);
}
void
VMGetMountPointTest::TestPartitionNameWithSlashesRemoved()
{
KPartition partition("", "testing/slashes", true);
KPath path;
status_t status = get_mount_point(&partition, &path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/testing/slashes") != 0);
}
void
VMGetMountPointTest::TestPartitionMountPointExists()
{
KPartition partition("", "testduplicate", true);
KPath path;
status_t status = get_mount_point(&partition, &path);
CPPUNIT_ASSERT_EQUAL(status, B_OK);
CPPUNIT_ASSERT(strcmp(path.Path(), "/testduplicate") != 0);
}