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->AcquireReference(); 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->ReleaseReference() == 1; 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