Added a level of indirection in the FileSystem management
(FileSystemInitializer). This will allow for subclassing FileSystem later. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20328 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fd7339329f
commit
5a5aacca23
|
@ -8,7 +8,6 @@
|
||||||
#include "KernelRequestHandler.h"
|
#include "KernelRequestHandler.h"
|
||||||
#include "PortReleaser.h"
|
#include "PortReleaser.h"
|
||||||
#include "RequestAllocator.h"
|
#include "RequestAllocator.h"
|
||||||
#include "RequestPort.h"
|
|
||||||
#include "Requests.h"
|
#include "Requests.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "SingleReplyRequestHandler.h"
|
#include "SingleReplyRequestHandler.h"
|
||||||
|
@ -25,34 +24,32 @@ struct FileSystem::SelectSyncMap
|
||||||
};
|
};
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
FileSystem::FileSystem(const char* name, RequestPort* initPort, status_t* error)
|
FileSystem::FileSystem()
|
||||||
: LazyInitializable(),
|
: fVolumes(),
|
||||||
Referencable(),
|
|
||||||
fVolumes(),
|
|
||||||
fVolumeLock(),
|
fVolumeLock(),
|
||||||
fName(name),
|
fName(),
|
||||||
fInitPort(initPort),
|
|
||||||
fNotificationPort(NULL),
|
fNotificationPort(NULL),
|
||||||
fNotificationThread(-1),
|
fNotificationThread(-1),
|
||||||
fPortPool(),
|
fPortPool(),
|
||||||
fSelectSyncs(NULL),
|
fSelectSyncs(NULL),
|
||||||
fSettings(NULL),
|
fSettings(NULL),
|
||||||
fUserlandServerTeam(-1),
|
fUserlandServerTeam(-1),
|
||||||
|
fInitialized(false),
|
||||||
fTerminating(false)
|
fTerminating(false)
|
||||||
{
|
{
|
||||||
if (error)
|
|
||||||
*error = (fName.GetLength() == 0 ? B_NO_MEMORY : B_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
FileSystem::~FileSystem()
|
FileSystem::~FileSystem()
|
||||||
{
|
{
|
||||||
fTerminating = true;
|
fTerminating = true;
|
||||||
|
|
||||||
// wait for the notification thread to terminate
|
// wait for the notification thread to terminate
|
||||||
if (fNotificationThread >= 0) {
|
if (fNotificationThread >= 0) {
|
||||||
int32 result;
|
int32 result;
|
||||||
wait_for_thread(fNotificationThread, &result);
|
wait_for_thread(fNotificationThread, &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete our data structures
|
// delete our data structures
|
||||||
if (fSelectSyncs) {
|
if (fSelectSyncs) {
|
||||||
for (SelectSyncMap::Iterator it = fSelectSyncs->GetIterator();
|
for (SelectSyncMap::Iterator it = fSelectSyncs->GetIterator();
|
||||||
|
@ -65,6 +62,96 @@ FileSystem::~FileSystem()
|
||||||
delete fSettings;
|
delete fSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
status_t
|
||||||
|
FileSystem::Init(const char* name, Port::Info* infos, int32 count)
|
||||||
|
{
|
||||||
|
PRINT(("FileSystem::Init(\"%s\", %p, %ld)\n", name, infos, infoCount));
|
||||||
|
|
||||||
|
// check parameters
|
||||||
|
if (!name || !infos || count < 2)
|
||||||
|
RETURN_ERROR(B_BAD_VALUE);
|
||||||
|
|
||||||
|
// set the name
|
||||||
|
if (!fName.SetTo(name))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// create the select sync entry map
|
||||||
|
fSelectSyncs = new(nothrow) SelectSyncMap;
|
||||||
|
if (!fSelectSyncs)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// create the request ports
|
||||||
|
// the notification port
|
||||||
|
fNotificationPort = new(nothrow) RequestPort(infos);
|
||||||
|
if (!fNotificationPort)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
status_t error = fNotificationPort->InitCheck();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// the other request ports
|
||||||
|
for (int32 i = 1; i < count; i++) {
|
||||||
|
RequestPort* port = new(nothrow) RequestPort(infos + i);
|
||||||
|
if (!port)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
error = port->InitCheck();
|
||||||
|
if (error == B_OK)
|
||||||
|
error = fPortPool.AddPort(port);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete port;
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the userland team
|
||||||
|
port_info portInfo;
|
||||||
|
error = get_port_info(infos[0].owner_port, &portInfo);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
fUserlandServerTeam = portInfo.team;
|
||||||
|
|
||||||
|
// print some info about the userland team
|
||||||
|
D(
|
||||||
|
PRINT((" userland team is: %ld\n", fUserlandServerTeam));
|
||||||
|
int32 cookie = 0;
|
||||||
|
thread_info threadInfo;
|
||||||
|
while (get_next_thread_info(fUserlandServerTeam, &cookie, &threadInfo)
|
||||||
|
== B_OK) {
|
||||||
|
PRINT((" userland thread: %ld: `%s'\n", threadInfo.thread,
|
||||||
|
threadInfo.name));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// load the settings
|
||||||
|
fSettings = new(nothrow) Settings;
|
||||||
|
if (fSettings) {
|
||||||
|
status_t settingsError = fSettings->SetTo(fName.GetString());
|
||||||
|
if (settingsError != B_OK) {
|
||||||
|
PRINT(("Failed to load settings: %s\n", strerror(settingsError)));
|
||||||
|
delete fSettings;
|
||||||
|
fSettings = NULL;
|
||||||
|
} else
|
||||||
|
fSettings->Dump();
|
||||||
|
} else
|
||||||
|
ERROR(("Failed to allocate settings.\n"));
|
||||||
|
|
||||||
|
// spawn the notification thread
|
||||||
|
#if USER
|
||||||
|
fNotificationThread = spawn_thread(_NotificationThreadEntry,
|
||||||
|
"UFS notification thread", B_NORMAL_PRIORITY, this);
|
||||||
|
#else
|
||||||
|
fNotificationThread = spawn_kernel_thread(_NotificationThreadEntry,
|
||||||
|
"UFS notification thread", B_NORMAL_PRIORITY, this);
|
||||||
|
#endif
|
||||||
|
if (fNotificationThread < 0)
|
||||||
|
RETURN_ERROR(fNotificationThread);
|
||||||
|
resume_thread(fNotificationThread);
|
||||||
|
|
||||||
|
fInitialized = (error == B_OK);
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
// GetName
|
// GetName
|
||||||
const char*
|
const char*
|
||||||
FileSystem::GetName() const
|
FileSystem::GetName() const
|
||||||
|
@ -85,9 +172,7 @@ FileSystem::Mount(mount_id id, const char* device, uint32 flags,
|
||||||
const char* parameters, Volume** _volume)
|
const char* parameters, Volume** _volume)
|
||||||
{
|
{
|
||||||
// check initialization and parameters
|
// check initialization and parameters
|
||||||
if (InitCheck() != B_OK)
|
if (!fInitialized || !_volume)
|
||||||
return InitCheck();
|
|
||||||
if (!_volume)
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// create volume
|
// create volume
|
||||||
|
@ -232,107 +317,6 @@ FileSystem::IsUserlandServerThread() const
|
||||||
return (info.team == fUserlandServerTeam);
|
return (info.team == fUserlandServerTeam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstTimeInit
|
|
||||||
status_t
|
|
||||||
FileSystem::FirstTimeInit()
|
|
||||||
{
|
|
||||||
if (fName.GetLength() == 0)
|
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
|
||||||
PRINT(("FileSystem::FirstTimeInit(): %s\n", fName.GetString()));
|
|
||||||
// create the select sync entry map
|
|
||||||
fSelectSyncs = new(nothrow) SelectSyncMap;
|
|
||||||
if (!fSelectSyncs)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
// prepare the request
|
|
||||||
RequestAllocator allocator(fInitPort->GetPort());
|
|
||||||
FSConnectRequest* request;
|
|
||||||
status_t error = AllocateRequest(allocator, &request);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
error = allocator.AllocateString(request->fsName, fName.GetString());
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
// send the request
|
|
||||||
SingleReplyRequestHandler handler(FS_CONNECT_REPLY);
|
|
||||||
FSConnectReply* reply;
|
|
||||||
error = fInitPort->SendRequest(&allocator, &handler, (Request**)&reply);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
RequestReleaser requestReleaser(fInitPort, reply);
|
|
||||||
// process the reply
|
|
||||||
if (reply->error != B_OK)
|
|
||||||
RETURN_ERROR(reply->error);
|
|
||||||
// get the port infos
|
|
||||||
int32 count = reply->portInfoCount;
|
|
||||||
if (count < 2)
|
|
||||||
RETURN_ERROR(B_BAD_DATA);
|
|
||||||
if (reply->portInfos.GetSize() != count * (int32)sizeof(Port::Info))
|
|
||||||
RETURN_ERROR(B_BAD_DATA);
|
|
||||||
Port::Info* infos = (Port::Info*)reply->portInfos.GetData();
|
|
||||||
// create the request ports
|
|
||||||
// the notification port
|
|
||||||
fNotificationPort = new(nothrow) RequestPort(infos);
|
|
||||||
if (!fNotificationPort)
|
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
|
||||||
error = fNotificationPort->InitCheck();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
// the other request ports
|
|
||||||
for (int32 i = 1; i < count; i++) {
|
|
||||||
RequestPort* port = new(nothrow) RequestPort(infos + i);
|
|
||||||
if (!port)
|
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
|
||||||
error = port->InitCheck();
|
|
||||||
if (error == B_OK)
|
|
||||||
error = fPortPool.AddPort(port);
|
|
||||||
if (error != B_OK) {
|
|
||||||
delete port;
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get the userland team
|
|
||||||
port_info portInfo;
|
|
||||||
error = get_port_info(infos[0].owner_port, &portInfo);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
fUserlandServerTeam = portInfo.team;
|
|
||||||
// print some info about the userland team
|
|
||||||
D(
|
|
||||||
PRINT((" userland team is: %ld\n", fUserlandServerTeam));
|
|
||||||
int32 cookie = 0;
|
|
||||||
thread_info threadInfo;
|
|
||||||
while (get_next_thread_info(fUserlandServerTeam, &cookie, &threadInfo)
|
|
||||||
== B_OK) {
|
|
||||||
PRINT((" userland thread: %ld: `%s'\n", threadInfo.thread,
|
|
||||||
threadInfo.name));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// load the settings
|
|
||||||
fSettings = new(nothrow) Settings;
|
|
||||||
if (fSettings) {
|
|
||||||
status_t settingsError = fSettings->SetTo(fName.GetString());
|
|
||||||
if (settingsError != B_OK) {
|
|
||||||
PRINT(("Failed to load settings: %s\n", strerror(settingsError)));
|
|
||||||
delete fSettings;
|
|
||||||
fSettings = NULL;
|
|
||||||
} else
|
|
||||||
fSettings->Dump();
|
|
||||||
} else
|
|
||||||
ERROR(("Failed to allocate settings.\n"));
|
|
||||||
// spawn the notification thread
|
|
||||||
#if USER
|
|
||||||
fNotificationThread = spawn_thread(_NotificationThreadEntry,
|
|
||||||
"UFS notification thread", B_NORMAL_PRIORITY, this);
|
|
||||||
#else
|
|
||||||
fNotificationThread = spawn_kernel_thread(_NotificationThreadEntry,
|
|
||||||
"UFS notification thread", B_NORMAL_PRIORITY, this);
|
|
||||||
#endif
|
|
||||||
if (fNotificationThread < 0)
|
|
||||||
RETURN_ERROR(fNotificationThread);
|
|
||||||
resume_thread(fNotificationThread);
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _NotificationThreadEntry
|
// _NotificationThreadEntry
|
||||||
int32
|
int32
|
||||||
FileSystem::_NotificationThreadEntry(void* data)
|
FileSystem::_NotificationThreadEntry(void* data)
|
||||||
|
|
|
@ -8,29 +8,24 @@
|
||||||
#include "LazyInitializable.h"
|
#include "LazyInitializable.h"
|
||||||
#include "Locker.h"
|
#include "Locker.h"
|
||||||
#include "Referencable.h"
|
#include "Referencable.h"
|
||||||
|
#include "RequestPort.h"
|
||||||
#include "RequestPortPool.h"
|
#include "RequestPortPool.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
namespace UserlandFSUtil {
|
|
||||||
|
|
||||||
class RequestPort;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
using UserlandFSUtil::RequestPort;
|
|
||||||
|
|
||||||
struct IOCtlInfo;
|
struct IOCtlInfo;
|
||||||
class Settings;
|
class Settings;
|
||||||
class Volume;
|
class Volume;
|
||||||
|
|
||||||
class FileSystem : public LazyInitializable, public Referencable {
|
class FileSystem {
|
||||||
public:
|
public:
|
||||||
FileSystem(const char* name,
|
FileSystem();
|
||||||
RequestPort* initPort,
|
|
||||||
status_t* error);
|
|
||||||
~FileSystem();
|
~FileSystem();
|
||||||
|
|
||||||
|
status_t Init(const char* name, Port::Info* infos,
|
||||||
|
int32 infoCount);
|
||||||
|
|
||||||
const char* GetName() const;
|
const char* GetName() const;
|
||||||
|
|
||||||
RequestPortPool* GetPortPool();
|
RequestPortPool* GetPortPool();
|
||||||
|
@ -52,9 +47,6 @@ public:
|
||||||
|
|
||||||
bool IsUserlandServerThread() const;
|
bool IsUserlandServerThread() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual status_t FirstTimeInit();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int32 _NotificationThreadEntry(void* data);
|
static int32 _NotificationThreadEntry(void* data);
|
||||||
int32 _NotificationThread();
|
int32 _NotificationThread();
|
||||||
|
@ -67,13 +59,13 @@ private:
|
||||||
Vector<Volume*> fVolumes;
|
Vector<Volume*> fVolumes;
|
||||||
Locker fVolumeLock;
|
Locker fVolumeLock;
|
||||||
String fName;
|
String fName;
|
||||||
RequestPort* fInitPort;
|
|
||||||
RequestPort* fNotificationPort;
|
RequestPort* fNotificationPort;
|
||||||
thread_id fNotificationThread;
|
thread_id fNotificationThread;
|
||||||
RequestPortPool fPortPool;
|
RequestPortPool fPortPool;
|
||||||
SelectSyncMap* fSelectSyncs;
|
SelectSyncMap* fSelectSyncs;
|
||||||
Settings* fSettings;
|
Settings* fSettings;
|
||||||
team_id fUserlandServerTeam;
|
team_id fUserlandServerTeam;
|
||||||
|
bool fInitialized;
|
||||||
volatile bool fTerminating;
|
volatile bool fTerminating;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
// FileSystemInitializer.cpp
|
||||||
|
|
||||||
|
#include "FileSystemInitializer.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "RequestAllocator.h"
|
||||||
|
#include "RequestPort.h"
|
||||||
|
#include "Requests.h"
|
||||||
|
#include "SingleReplyRequestHandler.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
FileSystemInitializer::FileSystemInitializer(const char* name,
|
||||||
|
RequestPort* initPort)
|
||||||
|
: fName(name),
|
||||||
|
fInitPort(initPort),
|
||||||
|
fFileSystem(NULL)
|
||||||
|
{
|
||||||
|
// Note: We don't copy the name. It's only needed in FirstTimeInit() and
|
||||||
|
// the UserlandFS makes sure it is valid until then.
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
FileSystemInitializer::~FileSystemInitializer()
|
||||||
|
{
|
||||||
|
delete fFileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FirstTimeInit
|
||||||
|
status_t
|
||||||
|
FileSystemInitializer::FirstTimeInit()
|
||||||
|
{
|
||||||
|
// prepare the request
|
||||||
|
RequestAllocator allocator(fInitPort->GetPort());
|
||||||
|
FSConnectRequest* request;
|
||||||
|
status_t error = AllocateRequest(allocator, &request);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
error = allocator.AllocateString(request->fsName, fName);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// send the request
|
||||||
|
SingleReplyRequestHandler handler(FS_CONNECT_REPLY);
|
||||||
|
FSConnectReply* reply;
|
||||||
|
error = fInitPort->SendRequest(&allocator, &handler, (Request**)&reply);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
RequestReleaser requestReleaser(fInitPort, reply);
|
||||||
|
|
||||||
|
// process the reply
|
||||||
|
if (reply->error != B_OK)
|
||||||
|
RETURN_ERROR(reply->error);
|
||||||
|
|
||||||
|
// get the port infos
|
||||||
|
int32 count = reply->portInfoCount;
|
||||||
|
if (count < 2)
|
||||||
|
RETURN_ERROR(B_BAD_DATA);
|
||||||
|
if (reply->portInfos.GetSize() != count * (int32)sizeof(Port::Info))
|
||||||
|
RETURN_ERROR(B_BAD_DATA);
|
||||||
|
Port::Info* infos = (Port::Info*)reply->portInfos.GetData();
|
||||||
|
|
||||||
|
// create and init the FileSystem
|
||||||
|
fFileSystem = new(nothrow) FileSystem();
|
||||||
|
if (!fFileSystem)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
error = fFileSystem->Init(fName, infos, count);
|
||||||
|
if (error != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
// FileSystemInitializer.h
|
||||||
|
|
||||||
|
#ifndef USERLAND_FS_FILE_SYSTEM_INITIALIZER_H
|
||||||
|
#define USERLAND_FS_FILE_SYSTEM_INITIALIZER_H
|
||||||
|
|
||||||
|
#include "LazyInitializable.h"
|
||||||
|
#include "Referencable.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace UserlandFSUtil {
|
||||||
|
|
||||||
|
class RequestPort;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using UserlandFSUtil::RequestPort;
|
||||||
|
|
||||||
|
class FileSystem;
|
||||||
|
|
||||||
|
class FileSystemInitializer : public LazyInitializable, public Referencable {
|
||||||
|
public:
|
||||||
|
FileSystemInitializer(const char* name,
|
||||||
|
RequestPort* initPort);
|
||||||
|
~FileSystemInitializer();
|
||||||
|
|
||||||
|
inline FileSystem* GetFileSystem() { return fFileSystem; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual status_t FirstTimeInit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* fName; // valid only until FirstTimeInit()
|
||||||
|
RequestPort* fInitPort;
|
||||||
|
FileSystem* fFileSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // USERLAND_FS_FILE_SYSTEM_INITIALIZER_H
|
|
@ -32,6 +32,7 @@ KernelAddon userlandfs
|
||||||
userlandfs_ioctl.cpp
|
userlandfs_ioctl.cpp
|
||||||
|
|
||||||
FileSystem.cpp
|
FileSystem.cpp
|
||||||
|
FileSystemInitializer.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
KernelDebug.cpp
|
KernelDebug.cpp
|
||||||
KernelRequestHandler.cpp
|
KernelRequestHandler.cpp
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
// KernelDebug.cpp
|
// KernelDebug.cpp
|
||||||
|
|
||||||
|
#include "KernelDebug.h"
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "KernelDebug.h"
|
#include "FileSystemInitializer.h"
|
||||||
#include "RequestPort.h"
|
#include "RequestPort.h"
|
||||||
#include "RequestPortPool.h"
|
#include "RequestPortPool.h"
|
||||||
#include "UserlandFS.h"
|
#include "UserlandFS.h"
|
||||||
|
@ -16,19 +18,23 @@ static vint32 sCommandsAdded = 0;
|
||||||
int
|
int
|
||||||
KernelDebug::DebugUFS(int argc, char** argv)
|
KernelDebug::DebugUFS(int argc, char** argv)
|
||||||
{
|
{
|
||||||
typedef HashMap<String, FileSystem*> KDebugFSMap;
|
typedef HashMap<String, FileSystemInitializer*> KDebugFSMap;
|
||||||
UserlandFS* userlandFS = UserlandFS::GetUserlandFS();
|
UserlandFS* userlandFS = UserlandFS::GetUserlandFS();
|
||||||
KDebugFSMap& fileSystems = userlandFS->fFileSystems->GetUnsynchronizedMap();
|
KDebugFSMap& fileSystems = userlandFS->fFileSystems->GetUnsynchronizedMap();
|
||||||
|
|
||||||
for (KDebugFSMap::Iterator it = fileSystems.GetIterator();
|
for (KDebugFSMap::Iterator it = fileSystems.GetIterator();
|
||||||
it.HasNext();) {
|
it.HasNext();) {
|
||||||
KDebugFSMap::Entry entry = it.Next();
|
KDebugFSMap::Entry entry = it.Next();
|
||||||
FileSystem* fs = entry.value;
|
FileSystemInitializer* fsInitializer = entry.value;
|
||||||
kprintf("file system %p: %s\n", fs, fs->GetName());
|
FileSystem* fs = fsInitializer->GetFileSystem();
|
||||||
kprintf(" port pool %p\n", fs->GetPortPool());
|
kprintf("file system %p: %s\n", fs, (fs ? fs->GetName() : NULL));
|
||||||
int32 volumeCount = fs->fVolumes.Count();
|
if (fs) {
|
||||||
for (int32 i = 0; i < volumeCount; i++) {
|
kprintf(" port pool %p\n", fs->GetPortPool());
|
||||||
Volume* volume = fs->fVolumes.ElementAt(i);
|
int32 volumeCount = fs->fVolumes.Count();
|
||||||
kprintf(" volume %p: %ld\n", volume, volume->GetID());
|
for (int32 i = 0; i < volumeCount; i++) {
|
||||||
|
Volume* volume = fs->fVolumes.ElementAt(i);
|
||||||
|
kprintf(" volume %p: %ld\n", volume, volume->GetID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
// UserlandFS.cpp
|
// UserlandFS.cpp
|
||||||
|
|
||||||
|
#include "UserlandFS.h"
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include "Compatibility.h"
|
#include "Compatibility.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "DispatcherDefs.h"
|
#include "DispatcherDefs.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
#include "FileSystemInitializer.h"
|
||||||
#include "KernelDebug.h"
|
#include "KernelDebug.h"
|
||||||
#include "RequestPort.h"
|
#include "RequestPort.h"
|
||||||
#include "Requests.h"
|
#include "Requests.h"
|
||||||
#include "UserlandFS.h"
|
|
||||||
|
|
||||||
|
|
||||||
UserlandFS* UserlandFS::sUserlandFS = NULL;
|
UserlandFS* UserlandFS::sUserlandFS = NULL;
|
||||||
|
@ -90,34 +92,34 @@ UserlandFS::RegisterFileSystem(const char* name, FileSystem** _fileSystem)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// check, if we do already know this file system, and create it, if not
|
// check, if we do already know this file system, and create it, if not
|
||||||
FileSystem* fileSystem;
|
FileSystemInitializer* fileSystemInitializer;
|
||||||
{
|
{
|
||||||
FileSystemLocker _(fFileSystems);
|
FileSystemLocker _(fFileSystems);
|
||||||
fileSystem = fFileSystems->Get(name);
|
fileSystemInitializer = fFileSystems->Get(name);
|
||||||
if (fileSystem) {
|
if (fileSystemInitializer) {
|
||||||
fileSystem->AddReference();
|
fileSystemInitializer->AddReference();
|
||||||
} else {
|
} else {
|
||||||
status_t error;
|
fileSystemInitializer = new(nothrow) FileSystemInitializer(name,
|
||||||
fileSystem = new(nothrow) FileSystem(name, fPort, &error);
|
fPort);
|
||||||
if (!fileSystem)
|
if (!fileSystemInitializer)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
if (error == B_OK)
|
|
||||||
error = fFileSystems->Put(name, fileSystem);
|
status_t error = fFileSystems->Put(name, fileSystemInitializer);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
delete fileSystem;
|
delete fileSystemInitializer;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the file system
|
// prepare the file system
|
||||||
status_t error = fileSystem->Access();
|
status_t error = fileSystemInitializer->Access();
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
UnregisterFileSystem(fileSystem);
|
_UnregisterFileSystem(name);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
*_fileSystem = fileSystem;
|
*_fileSystem = fileSystemInitializer->GetFileSystem();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,22 +130,7 @@ UserlandFS::UnregisterFileSystem(FileSystem* fileSystem)
|
||||||
if (!fileSystem)
|
if (!fileSystem)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// find the FS and decrement its reference counter
|
return _UnregisterFileSystem(fileSystem->GetName());
|
||||||
bool deleteFS = false;
|
|
||||||
{
|
|
||||||
FileSystemLocker _(fFileSystems);
|
|
||||||
fileSystem = fFileSystems->Get(fileSystem->GetName());
|
|
||||||
if (!fileSystem)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
deleteFS = fileSystem->RemoveReference();
|
|
||||||
if (deleteFS)
|
|
||||||
fFileSystems->Remove(fileSystem->GetName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete the FS, if the last reference has been removed
|
|
||||||
if (deleteFS)
|
|
||||||
delete fileSystem;
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountFileSystems
|
// CountFileSystems
|
||||||
|
@ -205,3 +192,29 @@ UserlandFS::_Init()
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _UnregisterFileSystem
|
||||||
|
status_t
|
||||||
|
UserlandFS::_UnregisterFileSystem(const char* name)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// find the FS and decrement its reference counter
|
||||||
|
FileSystemInitializer* fileSystemInitializer = NULL;
|
||||||
|
bool deleteFS = false;
|
||||||
|
{
|
||||||
|
FileSystemLocker _(fFileSystems);
|
||||||
|
fileSystemInitializer = fFileSystems->Get(name);
|
||||||
|
if (!fileSystemInitializer)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
deleteFS = fileSystemInitializer->RemoveReference();
|
||||||
|
if (deleteFS)
|
||||||
|
fFileSystems->Remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the FS, if the last reference has been removed
|
||||||
|
if (deleteFS)
|
||||||
|
delete fileSystemInitializer;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ class RequestPort;
|
||||||
using UserlandFSUtil::RequestPort;
|
using UserlandFSUtil::RequestPort;
|
||||||
|
|
||||||
class FileSystem;
|
class FileSystem;
|
||||||
|
class FileSystemInitializer;
|
||||||
|
|
||||||
class UserlandFS {
|
class UserlandFS {
|
||||||
private:
|
private:
|
||||||
|
@ -35,14 +36,17 @@ public:
|
||||||
|
|
||||||
int32 CountFileSystems() const;
|
int32 CountFileSystems() const;
|
||||||
|
|
||||||
private:
|
|
||||||
status_t _Init();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class KernelDebug;
|
friend class KernelDebug;
|
||||||
typedef SynchronizedHashMap<String, FileSystem*> FileSystemMap;
|
typedef SynchronizedHashMap<String, FileSystemInitializer*>
|
||||||
|
FileSystemMap;
|
||||||
typedef AutoLocker<UserlandFS::FileSystemMap> FileSystemLocker;
|
typedef AutoLocker<UserlandFS::FileSystemMap> FileSystemLocker;
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _Init();
|
||||||
|
status_t _UnregisterFileSystem(const char* name);
|
||||||
|
|
||||||
|
private:
|
||||||
static UserlandFS* sUserlandFS;
|
static UserlandFS* sUserlandFS;
|
||||||
|
|
||||||
RequestPort* fPort;
|
RequestPort* fPort;
|
||||||
|
|
Loading…
Reference in New Issue