diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 93964979f5..63763c6f49 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -28,7 +28,6 @@ HAIKU_PACKAGE_FS_SOURCES = Query.cpp Package.cpp PackageDirectory.cpp - PackageDomain.cpp PackageFile.cpp PackageFSRoot.cpp PackageLeafNode.cpp diff --git a/src/add-ons/kernel/file_systems/packagefs/Package.cpp b/src/add-ons/kernel/file_systems/packagefs/Package.cpp index 28fc000b80..721d3219f6 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Package.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Package.cpp @@ -21,10 +21,10 @@ #include "DebugSupport.h" #include "PackageDirectory.h" -#include "PackageDomain.h" #include "PackageFile.h" #include "PackageSymlink.h" #include "Version.h" +#include "Volume.h" using namespace BPackageKit; @@ -300,9 +300,9 @@ private: // #pragma mark - Package -Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID) +Package::Package(::Volume* volume, dev_t deviceID, ino_t nodeID) : - fDomain(domain), + fVolume(volume), fFileName(NULL), fName(NULL), fInstallPath(NULL), @@ -461,7 +461,7 @@ Package::Open() } // open the file - fFD = openat(fDomain->DirectoryFD(), fFileName, O_RDONLY); + fFD = openat(fVolume->PackagesDirectoryFD(), fFileName, O_RDONLY); if (fFD < 0) { ERROR("Failed to open package file \"%s\"\n", fFileName); return errno; diff --git a/src/add-ons/kernel/file_systems/packagefs/Package.h b/src/add-ons/kernel/file_systems/packagefs/Package.h index d9b0b56a6a..b8495b5e5d 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Package.h +++ b/src/add-ons/kernel/file_systems/packagefs/Package.h @@ -24,22 +24,22 @@ using BPackageKit::BPackageArchitecture; -class PackageDomain; class PackageLinkDirectory; +class Volume; class Version; class Package : public BReferenceable, public DoublyLinkedListLinkImpl { public: - Package(PackageDomain* domain, dev_t deviceID, + Package(::Volume* volume, dev_t deviceID, ino_t nodeID); ~Package(); status_t Init(const char* fileName); status_t Load(); - PackageDomain* Domain() const { return fDomain; } + ::Volume* Volume() const { return fVolume; } const char* FileName() const { return fFileName; } status_t SetName(const char* name); @@ -93,7 +93,7 @@ private: private: mutex fLock; - PackageDomain* fDomain; + ::Volume* fVolume; char* fFileName; char* fName; char* fInstallPath; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageDomain.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageDomain.cpp deleted file mode 100644 index 69e5248eaf..0000000000 --- a/src/add-ons/kernel/file_systems/packagefs/PackageDomain.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Distributed under the terms of the MIT License. - */ - - -#include "PackageDomain.h" - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include "DebugSupport.h" -#include "Volume.h" - - -PackageDomain::PackageDomain(::Volume* volume) - : - fVolume(volume), - fPath(NULL), - fDirFD(-1) -{ -} - - -PackageDomain::~PackageDomain() -{ - PRINT("PackageDomain::~PackageDomain()\n"); - - Package* package = fPackages.Clear(true); - while (package != NULL) { - Package* next = package->FileNameHashTableNext(); - package->ReleaseReference(); - package = next; - } - - if (fDirFD >= 0) - close(fDirFD); - - free(fPath); -} - - -status_t -PackageDomain::Init(const char* path, struct stat* _st) -{ - // Open the directory. We want the path be interpreted depending on from - // where it came (kernel or userland), but we always want a FD in the kernel - // I/O context. There's no VFS service method to do that for us, so we need - // to do that ourselves. - bool calledFromKernel - = team_get_current_team_id() == team_get_kernel_team_id(); - // Not entirely correct, but good enough for now. The only alternative - // is to have that information passed in as well. - - struct vnode* vnode; - status_t error; - if (path != NULL) { - error = vfs_get_vnode_from_path(path, calledFromKernel, &vnode); - } else { - // No path given -- use the "packages" directory at our mount point. - error = vfs_entry_ref_to_vnode(fVolume->MountPointDeviceID(), - fVolume->MountPointNodeID(), "packages", &vnode); - } - if (error != B_OK) { - ERROR("Failed to open package domain \"%s\"\n", strerror(error)); - RETURN_ERROR(error); - } - - fDirFD = vfs_open_vnode(vnode, O_RDONLY, true); - - if (fDirFD < 0) { - ERROR("Failed to open package domain \"%s\"\n", strerror(fDirFD)); - vfs_put_vnode(vnode); - RETURN_ERROR(fDirFD); - } - // Our vnode reference has been transferred to the FD. - - // Is it a directory at all? - struct stat st; - if (fstat(fDirFD, &st) < 0) - RETURN_ERROR(errno); - - fDeviceID = st.st_dev; - fNodeID = st.st_ino; - - // get a normalized path - KPath normalizedPath; - if (normalizedPath.InitCheck() != B_OK) - RETURN_ERROR(normalizedPath.InitCheck()); - - char* normalizedPathBuffer = normalizedPath.LockBuffer(); - error = vfs_entry_ref_to_path(fDeviceID, fNodeID, NULL, - normalizedPathBuffer, normalizedPath.BufferSize()); - if (error != B_OK) - RETURN_ERROR(error); - - fPath = strdup(normalizedPathBuffer); - if (fPath == NULL) - RETURN_ERROR(B_NO_MEMORY); - - // init packages hash table - error = fPackages.Init(); - if (error != B_OK) - return error; - - if (_st != NULL) - *_st = st; - - return B_OK; -} - - -void -PackageDomain::AddPackage(Package* package) -{ - fPackages.Insert(package); - package->AcquireReference(); -} - - -void -PackageDomain::RemovePackage(Package* package) -{ - fPackages.Remove(package); - package->ReleaseReference(); -} - - -Package* -PackageDomain::FindPackage(const char* fileName) const -{ - return fPackages.Lookup(fileName); -} diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageDomain.h b/src/add-ons/kernel/file_systems/packagefs/PackageDomain.h deleted file mode 100644 index 2c8dd5629e..0000000000 --- a/src/add-ons/kernel/file_systems/packagefs/PackageDomain.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. - * Distributed under the terms of the MIT License. - */ -#ifndef PACKAGE_DOMAIN_H -#define PACKAGE_DOMAIN_H - - -#include - -#include - -#include "Package.h" - - -struct stat; - -class Volume; - - -class PackageDomain : public BReferenceable, - public DoublyLinkedListLinkImpl { -public: - PackageDomain(::Volume* volume); - ~PackageDomain(); - - ::Volume* Volume() const { return fVolume; } - const char* Path() const { return fPath; } - int DirectoryFD() { return fDirFD; } - dev_t DeviceID() { return fDeviceID; } - ino_t NodeID() { return fNodeID; } - - status_t Init(const char* path, struct stat* _st); - - void AddPackage(Package* package); - void RemovePackage(Package* package); - - Package* FindPackage(const char* fileName) const; - - const PackageFileNameHashTable& Packages() const - { return fPackages; } - -private: - ::Volume* fVolume; - char* fPath; - int fDirFD; - dev_t fDeviceID; - ino_t fNodeID; - PackageFileNameHashTable fPackages; -}; - - -#endif // PACKAGE_DOMAIN_H diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp index 48a11f54ac..b0dc5a45a6 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp @@ -99,11 +99,11 @@ PackageLinkDirectory::AddPackage(Package* package, // Find the insertion point in the list. We sort by mount type -- the more // specific the higher the priority. - MountType mountType = package->Domain()->Volume()->MountType(); + MountType mountType = package->Volume()->MountType(); Package* otherPackage = NULL; for (PackageList::Iterator it = fPackages.GetIterator(); (otherPackage = it.Next()) != NULL;) { - if (otherPackage->Domain()->Volume()->MountType() <= mountType) + if (otherPackage->Volume()->MountType() <= mountType) break; } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp index ed674e2785..4fbf81f7f2 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp @@ -94,7 +94,7 @@ PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener) fLinkPath = package->InstallPath(); if (fLinkPath == NULL) { fLinkPath = link_path_for_mount_type( - package->Domain()->Volume()->MountType()); + package->Volume()->MountType()); } } else fLinkPath = kUnknownLinkTarget; diff --git a/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp b/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp index f396eb6b03..9e61317986 100644 --- a/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp @@ -17,11 +17,11 @@ ResolvableFamily::AddResolvable(Resolvable* resolvable, // Find the insertion point in the list. We sort by mount type -- the more // specific the higher the priority. MountType mountType - = resolvable->Package()->Domain()->Volume()->MountType(); + = resolvable->Package()->Volume()->MountType(); Resolvable* otherResolvable = NULL; for (FamilyResolvableList::Iterator it = fResolvables.GetIterator(); (otherResolvable = it.Next()) != NULL;) { - if (otherResolvable->Package()->Domain()->Volume()->MountType() + if (otherResolvable->Package()->Volume()->MountType() <= mountType) { break; } diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 4c4f9c9433..523189d082 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -23,6 +23,8 @@ #include +#include +#include #include #include "AttributeIndex.h" @@ -63,51 +65,112 @@ const char* const* kHomeShineThroughDirectories const size_t kMaxActivationRequestSize = 10 * 1024 * 1024; -// #pragma mark - Job +// #pragma mark - ShineThroughDirectory -struct Volume::Job : DoublyLinkedListLinkImpl { - Job(Volume* volume) +struct Volume::PackagesDirectory { + PackagesDirectory() : - fVolume(volume) + fPath(NULL), + fDirFD(-1) { } - virtual ~Job() + + ~PackagesDirectory() { + if (fDirFD >= 0) + close(fDirFD); + + free(fPath); } - virtual void Do() = 0; - -protected: - Volume* fVolume; -}; - - -// #pragma mark - AddPackageDomainJob - - -struct Volume::AddPackageDomainJob : Job { - AddPackageDomainJob(Volume* volume, PackageDomain* domain) - : - Job(volume), - fDomain(domain) + const char* Path() const { - fDomain->AcquireReference(); + return fPath; } - virtual ~AddPackageDomainJob() + int DirectoryFD() const { - fDomain->ReleaseReference(); + return fDirFD; } - virtual void Do() + dev_t DeviceID() const { - fVolume->_AddPackageDomain(fDomain, true); + return fDeviceID; + } + + ino_t NodeID() const + { + return fNodeID; + } + + status_t Init(const char* path, dev_t mountPointDeviceID, + ino_t mountPointNodeID, struct stat& _st) + { + // Open the directory. We want the path be interpreted depending on from + // where it came (kernel or userland), but we always want a FD in the + // kernel I/O context. There's no VFS service method to do that for us, + // so we need to do that ourselves. + bool calledFromKernel + = team_get_current_team_id() == team_get_kernel_team_id(); + // Not entirely correct, but good enough for now. The only + // alternative is to have that information passed in as well. + + struct vnode* vnode; + status_t error; + if (path != NULL) { + error = vfs_get_vnode_from_path(path, calledFromKernel, &vnode); + } else { + // No path given -- use the "packages" directory at our mount point. + error = vfs_entry_ref_to_vnode(mountPointDeviceID, mountPointNodeID, + "packages", &vnode); + } + if (error != B_OK) { + ERROR("Failed to open package domain \"%s\"\n", strerror(error)); + RETURN_ERROR(error); + } + + fDirFD = vfs_open_vnode(vnode, O_RDONLY, true); + + if (fDirFD < 0) { + ERROR("Failed to open package domain \"%s\"\n", strerror(fDirFD)); + vfs_put_vnode(vnode); + RETURN_ERROR(fDirFD); + } + // Our vnode reference has been transferred to the FD. + + // Is it a directory at all? + struct stat& st = _st; + if (fstat(fDirFD, &st) < 0) + RETURN_ERROR(errno); + + fDeviceID = st.st_dev; + fNodeID = st.st_ino; + + // get a normalized path + KPath normalizedPath; + if (normalizedPath.InitCheck() != B_OK) + RETURN_ERROR(normalizedPath.InitCheck()); + + char* normalizedPathBuffer = normalizedPath.LockBuffer(); + error = vfs_entry_ref_to_path(fDeviceID, fNodeID, NULL, + normalizedPathBuffer, normalizedPath.BufferSize()); + if (error != B_OK) + RETURN_ERROR(error); + + fPath = strdup(normalizedPathBuffer); + if (fPath == NULL) + RETURN_ERROR(B_NO_MEMORY); + + return B_OK; } private: - PackageDomain* fDomain; + char* fPath; + int fDirFD; + dev_t fDeviceID; + ino_t fNodeID; }; @@ -264,22 +327,32 @@ Volume::Volume(fs_volume* fsVolume) fFSVolume(fsVolume), fRootDirectory(NULL), fPackageFSRoot(NULL), - fPackageLoader(-1), - fNextNodeID(kRootDirectoryID + 1), - fTerminating(false) + fPackagesDirectory(NULL), + fNextNodeID(kRootDirectoryID + 1) { rw_lock_init(&fLock, "packagefs volume"); - mutex_init(&fJobQueueLock, "packagefs volume job queue"); - fJobQueueCondition.Init(this, "packagefs volume job queue"); } Volume::~Volume() { - _TerminatePackageLoader(); + // remove the packages from the node tree + { + VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); + VolumeWriteLocker volumeLocker(this); + for (PackageFileNameHashTable::Iterator it = fPackages.GetIterator(); + Package* package = it.Next();) { + _RemovePackageContent(package, NULL, false); + } + } - while (PackageDomain* packageDomain = fPackageDomains.Head()) - _RemovePackageDomain(packageDomain); + // delete the packages + Package* package = fPackages.Clear(true); + while (package != NULL) { + Package* next = package->FileNameHashTableNext(); + package->ReleaseReference(); + package = next; + } // delete all indices Index* index = fIndices.Clear(true); @@ -307,11 +380,17 @@ Volume::~Volume() if (fRootDirectory != NULL) fRootDirectory->ReleaseReference(); - mutex_destroy(&fJobQueueLock); rw_lock_destroy(&fLock); } +int +Volume::PackagesDirectoryFD() const +{ + return fPackagesDirectory->DirectoryFD(); +} + + status_t Volume::Mount(const char* parameterString) { @@ -324,6 +403,10 @@ Volume::Mount(const char* parameterString) if (error != B_OK) RETURN_ERROR(error); + error = fPackages.Init(); + if (error != B_OK) + RETURN_ERROR(error); + error = fIndices.Init(); if (error != B_OK) RETURN_ERROR(error); @@ -425,14 +508,14 @@ Volume::Mount(const char* parameterString) if (error != B_OK) RETURN_ERROR(error); - // create initial package domain - PackageDomain* packageDomain = new(std::nothrow) PackageDomain(this); - if (packageDomain == NULL) + // create package domain + fPackagesDirectory = new(std::nothrow) PackagesDirectory; + if (fPackagesDirectory == NULL) RETURN_ERROR(B_NO_MEMORY); - BReference packageDomainReference(packageDomain, true); struct stat st; - error = packageDomain->Init(packages, &st); + error = fPackagesDirectory->Init(packages, fMountPoint.deviceID, + fMountPoint.nodeID, st); if (error != B_OK) RETURN_ERROR(error); @@ -481,17 +564,11 @@ Volume::Mount(const char* parameterString) if (error != B_OK) RETURN_ERROR(error); - // add initial package domain - error = _AddPackageDomain(packageDomain, false); + // add initial packages + error = _AddInitialPackages(); if (error != B_OK) RETURN_ERROR(error); - // spawn package loader thread - fPackageLoader = spawn_kernel_thread(&_PackageLoaderEntry, - "package loader", B_NORMAL_PRIORITY, this); - if (fPackageLoader < 0) - RETURN_ERROR(fPackageLoader); - // publish the root node fRootDirectory->AcquireReference(); error = PublishVNode(fRootDirectory); @@ -505,9 +582,6 @@ Volume::Mount(const char* parameterString) if (error != B_OK) RETURN_ERROR(error); - // run the package loader - resume_thread(fPackageLoader); - return B_OK; } @@ -515,7 +589,6 @@ Volume::Mount(const char* parameterString) void Volume::Unmount() { - _TerminatePackageLoader(); } @@ -534,10 +607,8 @@ Volume::IOCtl(Node* node, uint32 operation, void* buffer, size_t size) info.mountType = fMountType; info.rootDeviceID = fPackageFSRoot->DeviceID(); info.rootDirectoryID = fPackageFSRoot->NodeID(); - - PackageDomain* domain = fPackageDomains.Head(); - info.packagesDeviceID = domain != NULL ? domain->DeviceID() : -1; - info.packagesDirectoryID = domain != NULL ? domain->NodeID() : -1; + info.packagesDeviceID = fPackagesDirectory->DeviceID(); + info.packagesDirectoryID = fPackagesDirectory->NodeID(); RETURN_ERROR(user_memcpy(buffer, &info, sizeof(info))); } @@ -552,13 +623,9 @@ Volume::IOCtl(Node* node, uint32 operation, void* buffer, size_t size) VolumeReadLocker volumeReadLocker(this); - PackageDomain* domain = fPackageDomains.Head(); - if (domain == NULL) - RETURN_ERROR(B_BAD_VALUE); - uint32 packageIndex = 0; for (PackageFileNameHashTable::Iterator it - = domain->Packages().GetIterator(); it.HasNext(); + = fPackages.GetIterator(); it.HasNext(); packageIndex++) { Package* package = it.Next(); PackageFSPackageInfo info; @@ -572,7 +639,7 @@ Volume::IOCtl(Node* node, uint32 operation, void* buffer, size_t size) return B_BAD_ADDRESS; } - uint32 packageCount = domain->Packages().CountElements(); + uint32 packageCount = fPackages.CountElements(); RETURN_ERROR(user_memcpy(&request->packageCount, &packageCount, sizeof(packageCount))); } @@ -685,28 +752,6 @@ Volume::PublishVNode(Node* node) } -status_t -Volume::AddPackageDomain(const char* path) -{ - PackageDomain* packageDomain = new(std::nothrow) PackageDomain(this); - if (packageDomain == NULL) - RETURN_ERROR(B_NO_MEMORY); - BReference packageDomainReference(packageDomain, true); - - status_t error = packageDomain->Init(path, NULL); - if (error != B_OK) - RETURN_ERROR(error); - - Job* job = new(std::nothrow) AddPackageDomainJob(this, packageDomain); - if (job == NULL) - RETURN_ERROR(B_NO_MEMORY); - - _PushJob(job); - - return B_OK; -} - - void Volume::PackageLinkNodeAdded(Node* node) { @@ -736,84 +781,23 @@ Volume::PackageLinkNodeChanged(Node* node, uint32 statFields, } -/*static*/ status_t -Volume::_PackageLoaderEntry(void* data) -{ - return ((Volume*)data)->_PackageLoader(); -} - - status_t -Volume::_PackageLoader() +Volume::_AddInitialPackages() { - while (!fTerminating) { - MutexLocker jobQueueLocker(fJobQueueLock); - - Job* job = fJobQueue.RemoveHead(); - if (job == NULL) { - // no job yet -- wait for someone notifying us - ConditionVariableEntry waitEntry; - fJobQueueCondition.Add(&waitEntry); - jobQueueLocker.Unlock(); - waitEntry.Wait(); - continue; - } - - // do the job - jobQueueLocker.Unlock(); - job->Do(); - delete job; - } - - return B_OK; -} - - -void -Volume::_TerminatePackageLoader() -{ - fTerminating = true; - - if (fPackageLoader >= 0) { - MutexLocker jobQueueLocker(fJobQueueLock); - fJobQueueCondition.NotifyOne(); - jobQueueLocker.Unlock(); - - wait_for_thread(fPackageLoader, NULL); - fPackageLoader = -1; - } - - // empty the job queue - while (Job* job = fJobQueue.RemoveHead()) - delete job; -} - - -void -Volume::_PushJob(Job* job) -{ - MutexLocker jobQueueLocker(fJobQueueLock); - fJobQueue.Add(job); - fJobQueueCondition.NotifyOne(); -} - - -status_t -Volume::_AddPackageDomain(PackageDomain* domain, bool notify) -{ - dprintf("packagefs: Adding package domain \"%s\"\n", domain->Path()); + dprintf("packagefs: Adding packages from \"%s\"\n", + fPackagesDirectory->Path()); // iterate through the dir and create packages - int fd = dup(domain->DirectoryFD()); + int fd = dup(fPackagesDirectory->DirectoryFD()); if (fd < 0) { - ERROR("Failed to dup() package domain FD: %s\n", strerror(errno)); + ERROR("Failed to dup() packages directory FD: %s\n", strerror(errno)); RETURN_ERROR(errno); } DIR* dir = fdopendir(fd); if (dir == NULL) { - ERROR("Failed to open package domain directory \"%s\": %s\n", - domain->Path(), strerror(errno)); + ERROR("Failed to open packages directory \"%s\": %s\n", + fPackagesDirectory->Path(), strerror(errno)); RETURN_ERROR(errno); } CObjectDeleter dirCloser(dir, closedir); @@ -824,53 +808,56 @@ Volume::_AddPackageDomain(PackageDomain* domain, bool notify) continue; Package* package; - if (_LoadPackage(domain, entry->d_name, package) != B_OK) + if (_LoadPackage(entry->d_name, package) != B_OK) continue; BReference packageReference(package, true); VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); VolumeWriteLocker volumeLocker(this); - domain->AddPackage(package); + _AddPackage(package); } // add the packages to the node tree VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); VolumeWriteLocker volumeLocker(this); - for (PackageFileNameHashTable::Iterator it - = domain->Packages().GetIterator(); Package* package = it.Next();) { - status_t error = _AddPackageContent(package, notify); + for (PackageFileNameHashTable::Iterator it = fPackages.GetIterator(); + Package* package = it.Next();) { + status_t error = _AddPackageContent(package, false); if (error != B_OK) { for (it.Rewind(); Package* activePackage = it.Next();) { if (activePackage == package) break; - _RemovePackageContent(activePackage, NULL, notify); + _RemovePackageContent(activePackage, NULL, false); } RETURN_ERROR(error); } } - fPackageDomains.Add(domain); - domain->AcquireReference(); - return B_OK; } -void -Volume::_RemovePackageDomain(PackageDomain* domain) +inline void +Volume::_AddPackage(Package* package) { - // remove the domain's packages from the node tree - VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); - VolumeWriteLocker volumeLocker(this); - for (PackageFileNameHashTable::Iterator it - = domain->Packages().GetIterator(); Package* package = it.Next();) { - _RemovePackageContent(package, NULL, false); - } + fPackages.Insert(package); + package->AcquireReference(); +} - // remove the domain - fPackageDomains.Remove(domain); - domain->ReleaseReference(); + +inline void +Volume::_RemovePackage(Package* package) +{ + fPackages.Remove(package); + package->ReleaseReference(); +} + + +inline Package* +Volume::_FindPackage(const char* fileName) const +{ + return fPackages.Lookup(fileName); } @@ -1336,19 +1323,18 @@ Volume::_RemoveNodeAndVNode(Node* node) } -/*static*/ status_t -Volume::_LoadPackage(PackageDomain* domain, const char* name, - Package*& _package) +status_t +Volume::_LoadPackage(const char* name, Package*& _package) { // check whether the entry is a file struct stat st; - if (fstatat(domain->DirectoryFD(), name, &st, 0) < 0 + if (fstatat(fPackagesDirectory->DirectoryFD(), name, &st, 0) < 0 || !S_ISREG(st.st_mode)) { return B_BAD_VALUE; } // create a package - Package* package = new(std::nothrow) Package(domain, st.st_dev, st.st_ino); + Package* package = new(std::nothrow) Package(this, st.st_dev, st.st_ino); if (package == NULL) RETURN_ERROR(B_NO_MEMORY); BReference packageReference(package, true); @@ -1369,12 +1355,6 @@ Volume::_LoadPackage(PackageDomain* domain, const char* name, status_t Volume::_ChangeActivation(ActivationChangeRequest& request) { -// TODO: Would need locking, but will be irrelevant when removing the support -// for multiple package domains. - PackageDomain* domain = fPackageDomains.Head(); - if (domain == NULL) - RETURN_ERROR(B_BAD_VALUE); - // first check the request int32 newPackageCount = 0; int32 oldPackageCount = 0; @@ -1384,14 +1364,14 @@ Volume::_ChangeActivation(ActivationChangeRequest& request) for (ActivationChangeRequest::Iterator it = request.GetIterator(); it.HasNext();) { PackageFSActivationChangeItem* item = it.Next(); - if (item->parentDeviceID != domain->DeviceID() - || item->parentDirectoryID != domain->NodeID()) { + if (item->parentDeviceID != fPackagesDirectory->DeviceID() + || item->parentDirectoryID != fPackagesDirectory->NodeID()) { ERROR("Volume::_ChangeActivation(): mismatching packages " - "domain\n"); + "directory\n"); RETURN_ERROR(B_BAD_VALUE); } - Package* package = domain->FindPackage(item->name); + Package* package = _FindPackage(item->name); // TODO: We should better look up the package by node_ref! if (item->type == PACKAGE_FS_ACTIVATE_PACKAGE) { if (package != NULL) { @@ -1449,7 +1429,7 @@ INFORM("Volume::_ChangeActivation(): %" B_PRId32 " new packages, %" B_PRId32 " o } Package* package; - status_t error = _LoadPackage(domain, item->name, package); + status_t error = _LoadPackage(item->name, package); if (error != B_OK) { ERROR("Volume::_ChangeActivation(): failed to load package " "\"%s\"\n", item->name); @@ -1476,11 +1456,11 @@ INFORM("Volume::_ChangeActivation(): %" B_PRId32 " new packages, %" B_PRId32 " o continue; } - Package* package = domain->FindPackage(item->name); + Package* package = _FindPackage(item->name); // TODO: We should better look up the package by node_ref! oldPackageReferences[oldPackageIndex++].SetTo(package); _RemovePackageContent(package, NULL, true); - domain->RemovePackage(package); + _RemovePackage(package); INFORM("package \"%s\" deactivated\n", package->FileName()); } // TODO: Since package removal cannot fail, consider adding the new packages @@ -1492,12 +1472,12 @@ INFORM("package \"%s\" deactivated\n", package->FileName()); for (newPackageIndex = 0; newPackageIndex < newPackageCount; newPackageIndex++) { Package* package = newPackageReferences[newPackageIndex]; - domain->AddPackage(package); + _AddPackage(package); // add the package to the node tree error = _AddPackageContent(package, true); if (error != B_OK) { - domain->RemovePackage(package); + _RemovePackage(package); break; } INFORM("package \"%s\" activated\n", package->FileName()); @@ -1508,19 +1488,19 @@ INFORM("package \"%s\" activated\n", package->FileName()); for (int32 i = newPackageIndex - 1; i >= 0; i--) { Package* package = newPackageReferences[i]; _RemovePackageContent(package, NULL, true); - domain->RemovePackage(package); + _RemovePackage(package); } for (int32 i = oldPackageCount - 1; i >= 0; i--) { Package* package = oldPackageReferences[i]; - domain->AddPackage(package); + _AddPackage(package); if (_AddPackageContent(package, true) != B_OK) { // nothing we can do here ERROR("Volume::_ChangeActivation(): failed to roll back " "deactivation of package \"%s\" after error\n", package->FileName()); - domain->RemovePackage(package); + _RemovePackage(package); } } } diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h b/src/add-ons/kernel/file_systems/packagefs/Volume.h index 2064063236..23caf19fb8 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h @@ -1,5 +1,5 @@ /* - * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef VOLUME_H @@ -19,7 +19,7 @@ #include "Index.h" #include "Node.h" #include "NodeListener.h" -#include "PackageDomain.h" +#include "Package.h" #include "PackageLinksListener.h" #include "Query.h" @@ -51,6 +51,8 @@ public: ::MountType MountType() const { return fMountType; } + int PackagesDirectoryFD() const; + void SetPackageFSRoot(::PackageFSRoot* root) { fPackageFSRoot = root; } ::PackageFSRoot* PackageFSRoot() const @@ -94,8 +96,6 @@ public: status_t RemoveVNode(ino_t nodeID); status_t PublishVNode(Node* node); - status_t AddPackageDomain(const char* path); - private: // PackageLinksListener virtual void PackageLinkNodeAdded(Node* node); @@ -105,29 +105,16 @@ private: const OldNodeAttributes& oldAttributes); private: - struct Job; - struct AddPackageDomainJob; - struct DomainDirectoryEventJob; + struct PackagesDirectory; struct ShineThroughDirectory; struct ActivationChangeRequest; - friend struct AddPackageDomainJob; - - typedef DoublyLinkedList JobList; - typedef DoublyLinkedList PackageDomainList; - private: - static status_t _PackageLoaderEntry(void* data); - status_t _PackageLoader(); + status_t _AddInitialPackages(); - void _TerminatePackageLoader(); - - void _PushJob(Job* job); - - status_t _AddInitialPackageDomain(const char* path); - status_t _AddPackageDomain(PackageDomain* domain, - bool notify); - void _RemovePackageDomain(PackageDomain* domain); + inline void _AddPackage(Package* package); + inline void _RemovePackage(Package* package); + inline Package* _FindPackage(const char* fileName) const; status_t _AddPackageContent(Package* package, bool notify); @@ -155,8 +142,8 @@ private: void _RemoveNodeAndVNode(Node* node); // caller must hold a reference - static status_t _LoadPackage(PackageDomain* domain, - const char* name, Package*& _package); + status_t _LoadPackage(const char* name, + Package*& _package); status_t _ChangeActivation( ActivationChangeRequest& request); @@ -187,8 +174,7 @@ private: Directory* fRootDirectory; ::PackageFSRoot* fPackageFSRoot; ::MountType fMountType; - thread_id fPackageLoader; - PackageDomainList fPackageDomains; + PackagesDirectory* fPackagesDirectory; struct { dev_t deviceID; @@ -197,16 +183,11 @@ private: NodeIDHashTable fNodes; NodeListenerHashTable fNodeListeners; + PackageFileNameHashTable fPackages; QueryList fQueries; IndexHashTable fIndices; - JobList fJobQueue; - mutex fJobQueueLock; - ConditionVariable fJobQueueCondition; - ino_t fNextNodeID; - - volatile bool fTerminating; };