xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/UserlandFS.cpp (revision 4720c31bb08f5c6d1c8ddb616463c6fba9b350a1)
1 /*
2  * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "UserlandFS.h"
7 
8 #include <KernelExport.h>
9 
10 #include "Compatibility.h"
11 #include "Debug.h"
12 #include "FileSystem.h"
13 #include "FileSystemInitializer.h"
14 #include "KernelDebug.h"
15 #include "RequestPort.h"
16 #include "Requests.h"
17 #include "UserlandFSDefs.h"
18 
19 
20 UserlandFS* UserlandFS::sUserlandFS = NULL;
21 
22 // constructor
23 UserlandFS::UserlandFS()
24 	:
25 	fFileSystems(NULL),
26 	fDebuggerCommandsAdded(false)
27 {
28 }
29 
30 // destructor
31 UserlandFS::~UserlandFS()
32 {
33 PRINT(("UserlandFS::~UserlandFS()\n"))
34 	delete fFileSystems;
35 	if (fDebuggerCommandsAdded)
36 		KernelDebug::RemoveDebuggerCommands();
37 }
38 
39 // InitUserlandFS
40 status_t
41 UserlandFS::InitUserlandFS(UserlandFS** _userlandFS)
42 {
43 	// create the singleton instance
44 	sUserlandFS = new(nothrow) UserlandFS;
45 	if (!sUserlandFS)
46 		return B_NO_MEMORY;
47 
48 	// init the thing
49 	status_t error = sUserlandFS->_Init();
50 	if (error != B_OK) {
51 		delete sUserlandFS;
52 		sUserlandFS = NULL;
53 		return error;
54 	}
55 
56 	*_userlandFS = sUserlandFS;
57 
58 	return B_OK;
59 }
60 
61 // UninitUserlandFS
62 void
63 UserlandFS::UninitUserlandFS()
64 {
65 	delete sUserlandFS;
66 	sUserlandFS = NULL;
67 }
68 
69 // GetUserlandFS
70 UserlandFS*
71 UserlandFS::GetUserlandFS()
72 {
73 	return sUserlandFS;
74 }
75 
76 // RegisterFileSystem
77 status_t
78 UserlandFS::RegisterFileSystem(const char* name, FileSystem** _fileSystem)
79 {
80 	// check parameters
81 	if (!name || !_fileSystem)
82 		return B_BAD_VALUE;
83 
84 	// check, if we do already know this file system, and create it, if not
85 	FileSystemInitializer* fileSystemInitializer;
86 	{
87 		FileSystemLocker _(fFileSystems);
88 		fileSystemInitializer = fFileSystems->Get(name);
89 		if (fileSystemInitializer) {
90 			fileSystemInitializer->AddReference();
91 		} else {
92 			fileSystemInitializer = new(nothrow) FileSystemInitializer(name);
93 			if (!fileSystemInitializer)
94 				return B_NO_MEMORY;
95 
96 			status_t error = fFileSystems->Put(name, fileSystemInitializer);
97 			if (error != B_OK) {
98 				delete fileSystemInitializer;
99 				return error;
100 			}
101 		}
102 	}
103 
104 	// prepare the file system
105 	status_t error = fileSystemInitializer->Access();
106 	if (error != B_OK) {
107 		_UnregisterFileSystem(name);
108 		return error;
109 	}
110 
111 	*_fileSystem = fileSystemInitializer->GetFileSystem();
112 	return error;
113 }
114 
115 // UnregisterFileSystem
116 status_t
117 UserlandFS::UnregisterFileSystem(FileSystem* fileSystem)
118 {
119 	if (!fileSystem)
120 		return B_BAD_VALUE;
121 
122 	return _UnregisterFileSystem(fileSystem->GetName());
123 }
124 
125 // CountFileSystems
126 int32
127 UserlandFS::CountFileSystems() const
128 {
129 	return fFileSystems->Size();
130 }
131 
132 // _Init
133 status_t
134 UserlandFS::_Init()
135 {
136 	// add debugger commands
137 	KernelDebug::AddDebuggerCommands();
138 	fDebuggerCommandsAdded = true;
139 
140 	// create file system map
141 	fFileSystems = new(nothrow) FileSystemMap;
142 	if (!fFileSystems)
143 		RETURN_ERROR(B_NO_MEMORY);
144 	status_t error = fFileSystems->InitCheck();
145 	if (error != B_OK)
146 		RETURN_ERROR(error);
147 
148 	return B_OK;
149 }
150 
151 // _UnregisterFileSystem
152 status_t
153 UserlandFS::_UnregisterFileSystem(const char* name)
154 {
155 	if (!name)
156 		return B_BAD_VALUE;
157 
158 	// find the FS and decrement its reference counter
159 	FileSystemInitializer* fileSystemInitializer = NULL;
160 	bool deleteFS = false;
161 	{
162 		FileSystemLocker _(fFileSystems);
163 		fileSystemInitializer = fFileSystems->Get(name);
164 		if (!fileSystemInitializer)
165 			return B_BAD_VALUE;
166 
167 		deleteFS = fileSystemInitializer->RemoveReference();
168 		if (deleteFS)
169 			fFileSystems->Remove(name);
170 	}
171 
172 	// delete the FS, if the last reference has been removed
173 	if (deleteFS)
174 		delete fileSystemInitializer;
175 	return B_OK;
176 }
177