diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.cpp index 5d86e25f7a..d2602859fa 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.cpp @@ -2,13 +2,60 @@ #include "FileSystem.h" +#include "AutoLocker.h" +#include "Volume.h" + + +FileSystem* FileSystem::sInstance = NULL; + + // constructor FileSystem::FileSystem() { + sInstance = this; } + // destructor FileSystem::~FileSystem() { + sInstance = NULL; } + +/*static*/ FileSystem* +FileSystem::GetInstance() +{ + return sInstance; +} + + +void +FileSystem::RegisterVolume(Volume* volume) +{ + AutoLocker _(fLock); + fVolumes.Add(volume); +} + + +void +FileSystem::UnregisterVolume(Volume* volume) +{ + AutoLocker _(fLock); + fVolumes.Remove(volume); +} + + +Volume* +FileSystem::VolumeWithID(dev_t id) +{ + AutoLocker _(fLock); + + VolumeList::Iterator it = fVolumes.GetIterator(); + while (Volume* volume = it.Next()) { + if (volume->GetID() == id) + return volume; + } + + return NULL; +} diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h index 08c7173d0d..58ef70038f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h @@ -7,7 +7,11 @@ #include #include +#include + #include "FSCapabilities.h" +#include "Locker.h" + namespace UserlandFS { @@ -18,9 +22,15 @@ public: FileSystem(); virtual ~FileSystem(); + static FileSystem* GetInstance(); + virtual status_t CreateVolume(Volume** volume, dev_t id) = 0; virtual status_t DeleteVolume(Volume* volume) = 0; + void RegisterVolume(Volume* volume); + void UnregisterVolume(Volume* volume); + Volume* VolumeWithID(dev_t id); + void GetCapabilities( FSCapabilities& capabilities) const { capabilities = fCapabilities; } @@ -28,8 +38,15 @@ public: { return fClientFSType; } protected: + typedef DoublyLinkedList VolumeList; + +protected: + Locker fLock; + VolumeList fVolumes; FSCapabilities fCapabilities; client_fs_type fClientFSType; + + static FileSystem* sInstance; }; } // namespace UserlandFS diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp index 17c5d59c5a..9b351d11af 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp @@ -6,18 +6,22 @@ #include #include +#include "FileSystem.h" #include "kernel_emu.h" + // constructor Volume::Volume(FileSystem* fileSystem, dev_t id) : fFileSystem(fileSystem), fID(id) { + fFileSystem->RegisterVolume(this); } // destructor Volume::~Volume() { + fFileSystem->UnregisterVolume(this); } // GetFileSystem @@ -85,6 +89,15 @@ Volume::Lookup(void* dir, const char* entryName, ino_t* vnid) return B_BAD_VALUE; } + +// GetVNodeType +status_t +Volume::GetVNodeType(void* node, int* type) +{ + return B_NOT_SUPPORTED; +} + + // GetVNodeName status_t Volume::GetVNodeName(void* node, char* buffer, size_t bufferSize) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h index 66dbabbe0f..7c18a9227c 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h @@ -6,15 +6,18 @@ #include #include +#include + #include "FSCapabilities.h" + namespace UserlandFS { class FileSystem; using UserlandFSUtil::FSVolumeCapabilities; -class Volume { +class Volume : public DoublyLinkedListLinkImpl { public: Volume(FileSystem* fileSystem, dev_t id); virtual ~Volume(); @@ -38,6 +41,10 @@ public: // vnodes virtual status_t Lookup(void* dir, const char* entryName, ino_t* vnid); + virtual status_t GetVNodeType(void* node, int* type); + // Only needs to be implemented when + // the three parameters publish_vnode() is + // used. virtual status_t GetVNodeName(void* node, char* buffer, size_t bufferSize); virtual status_t ReadVNode(ino_t vnid, bool reenter, diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.cpp index 6b1d800ac1..cdbbdc4ac1 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.cpp @@ -43,9 +43,11 @@ public: // constructor BeOSKernelVolume::BeOSKernelVolume(FileSystem* fileSystem, dev_t id, beos_vnode_ops* fsOps) - : Volume(fileSystem, id), - fFSOps(fsOps), - fVolumeCookie(NULL) + : + Volume(fileSystem, id), + fFSOps(fsOps), + fVolumeCookie(NULL), + fMounted(false) { } @@ -66,8 +68,13 @@ BeOSKernelVolume::Mount(const char* device, uint32 flags, return B_BAD_VALUE; size_t len = (parameters ? strlen(parameters) : 0); - return fFSOps->mount(GetID(), device, flags, (void*)parameters, len, - &fVolumeCookie, rootID); + status_t error = fFSOps->mount(GetID(), device, flags, (void*)parameters, + len, &fVolumeCookie, rootID); + if (error != B_OK) + return error; + + fMounted = true; + return B_OK; } // Unmount @@ -123,6 +130,35 @@ BeOSKernelVolume::Lookup(void* dir, const char* entryName, ino_t* vnid) return fFSOps->walk(fVolumeCookie, dir, entryName, NULL, vnid); } + +// GetVNodeType +status_t +BeOSKernelVolume::GetVNodeType(void* node, int* type) +{ + if (fMounted) { + // The volume is mounted. We can stat() the node to get its type. + struct stat st; + status_t error = ReadStat(node, &st); + if (error != B_OK) + return error; + + *type = st.st_mode & S_IFMT; + } else { + // Not mounted yet. That particularly means we don't have a volume + // cookie yet and cannot use calls into the FS to get the node type. + // Just assume the node is a directory. That definitely is the case for + // the root node and shouldn't do harm for the index directory or + // indices, which could get published while mounting as well. + *type = S_IFDIR; + // TODO: Store the concerned nodes and check their type as soon as + // possible (at the end of Mount()). The incorrect ones could be + // corrected in the kernel: remove_vnode(), x*put_vnode() (catching + // the "remove_vnode()" callback), publish_vnode(), + // (x-1)*get_vnode(). + } +} + + // ReadVNode status_t BeOSKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type, diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.h b/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.h index 9adb6474d7..a874799efc 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/beos/BeOSKernelVolume.h @@ -27,6 +27,10 @@ public: // vnodes virtual status_t Lookup(void* dir, const char* entryName, ino_t* vnid); + virtual status_t GetVNodeType(void* node, int* type); + // Only needs to be implemented when + // the three parameters publish_vnode() is + // used. virtual status_t ReadVNode(ino_t vnid, bool reenter, void** node, int* type, uint32* flags); virtual status_t WriteVNode(void* node, bool reenter); @@ -153,6 +157,7 @@ private: private: beos_vnode_ops* fFSOps; void* fVolumeCookie; + bool fMounted; }; } // namespace UserlandFS diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/beos/beos_kernel_emu.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/beos/beos_kernel_emu.cpp index b1319006cd..f649cc6b59 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/beos/beos_kernel_emu.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/beos/beos_kernel_emu.cpp @@ -147,9 +147,7 @@ new_vnode(nspace_id nsid, ino_t vnid, void *data) { // The semantics of new_vnode() has changed. The new publish_vnode() // should work like the former new_vnode(). -// TODO: Implement correctly! Get the type! -// return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data); -return B_BAD_VALUE; + return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data); } // remove_vnode diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp index 042443663c..cf79dc1629 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp @@ -6,11 +6,13 @@ #include #include +#include "FileSystem.h" #include "RequestPort.h" #include "Requests.h" #include "RequestThread.h" #include "UserlandFSServer.h" #include "UserlandRequestHandler.h" +#include "Volume.h" // Taken from the Haiku Storage Kit (storage_support.cpp) @@ -407,6 +409,28 @@ UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data, return error; } + +// publish_vnode +status_t +UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data) +{ + // get the volume + Volume* volume = FileSystem::GetInstance()->VolumeWithID(nsid); + if (volume == NULL) + return B_BAD_VALUE; + + // stat() the node to get its type +// TODO: This must not be called while mounting! + int type; + status_t error = volume->GetVNodeType(data, &type); + if (error != B_OK) + return error; + + // publish the node + return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data, type, 0); +} + + // remove_vnode status_t UserlandFS::KernelEmu::remove_vnode(dev_t nsid, ino_t vnid) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h index 13cfdbc76c..5cd4069ab9 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h @@ -26,6 +26,7 @@ status_t acquire_vnode(dev_t nsid, ino_t vnodeID); status_t new_vnode(dev_t nsid, ino_t vnid, void* data); status_t publish_vnode(dev_t nsid, ino_t vnid, void* data, int type, uint32 flags); +status_t publish_vnode(dev_t nsid, ino_t vnid, void* data); status_t remove_vnode(dev_t nsid, ino_t vnid); status_t unremove_vnode(dev_t nsid, ino_t vnid); status_t get_vnode_removed(dev_t nsid, ino_t vnid, bool* removed);