From 0750f5b62dd4d079fc4e8329f9a27ac669c2f85a Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 14 Aug 2024 18:35:37 -0400 Subject: [PATCH] ramfs: Properly acquire/release references to the vnode in VMCache. This is what AcquireStoreRef/ReleaseStoreRef are for. We don't use VMVnodeCache here because that is a non-"temporary" cache that writes its pages back to disk, while we need a store for the pages that won't discard unmodified ones when memory is low. Add a close() to the mmap_cut_tests, which triggers the case where this is important (a file is unlinked, mmap'ed, and then the lone FD referring to it is closed, triggering the file's deletion unless the mmap also acquired a reference to the vnode.) Fixes KDLs with Firefox test builds. (cherry picked from commit c0a12a6b7d697382511ff36e7815aad6a379b3a7) Change-Id: I589325966f7b8eb837750aea1f5adbdd94e06aeb Reviewed-on: https://review.haiku-os.org/c/haiku/+/8028 Reviewed-by: waddlesplash --- src/system/kernel/vm/VMAnonymousNoSwapCache.h | 2 +- src/tests/system/kernel/mmap_cut_tests.cpp | 3 +++ src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/add-ons/kernel/file_systems/ramfs/DataContainer.h | 2 +- src/add-ons/kernel/file_systems/ramfs/Jamfile | 1 + src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp | 2 +- 6 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/system/kernel/vm/VMAnonymousNoSwapCache.h b/src/system/kernel/vm/VMAnonymousNoSwapCache.h index 3754c04..ee92338 100644 --- a/src/system/kernel/vm/VMAnonymousNoSwapCache.h +++ b/src/system/kernel/vm/VMAnonymousNoSwapCache.h @@ -13,7 +13,7 @@ #include -class VMAnonymousNoSwapCache final : public VMCache { +class VMAnonymousNoSwapCache : public VMCache { public: virtual ~VMAnonymousNoSwapCache(); diff --git a/src/tests/system/kernel/mmap_cut_tests.cpp b/src/tests/system/kernel/mmap_cut_tests.cpp index 3f88103..cf58bff 100644 --- a/src/tests/system/kernel/mmap_cut_tests.cpp +++ b/src/tests/system/kernel/mmap_cut_tests.cpp @@ -94,6 +94,9 @@ uint8* ptr = (uint8*)mmap(NULL, B_PAGE_SIZE * 4, PROT_NONE, MAP_PRIVATE, fd, 0); + // we can close the FD as mmap acquires another reference to the vnode + close(fd); + // make the head accessible and also force the kernel to allocate the // page_protections array mprotect(ptr, B_PAGE_SIZE, PROT_READ | PROT_WRITE); diff --git a/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp b/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp index 054dece..54e9812 100644 --- a/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp @@ -8,9 +8,12 @@ #include #include #include +#include +#include #include #include +#include "VMAnonymousNoSwapCache.h" #include "AllocationInfo.h" #include "DebugSupport.h" @@ -42,6 +45,42 @@ static const off_t kMaximumSmallBufferSize = (B_PAGE_SIZE / 4); +// We don't use VMVnodeCache because it's for caching pages that exist on disk. +// All we need is an AnonymousCache that tracks when the vnode is referenced. +class VMForVnodeCache final : public VMAnonymousNoSwapCache { +public: + status_t Init() + { + fVnode = NULL; + return VMAnonymousNoSwapCache::Init(false, 0, 0, 0); + } + + status_t AcquireUnreferencedStoreRef() override + { + return B_NOT_SUPPORTED; + } + + void AcquireStoreRef() override + { + vfs_acquire_vnode(fVnode); + } + + void ReleaseStoreRef() override + { + vfs_put_vnode(fVnode); + } + +protected: + virtual void DeleteObject() + { + object_cache_delete(gVnodeCacheObjectCache, this); + } + +private: + friend class DataContainer; + struct vnode* fVnode; +}; + DataContainer::DataContainer(Volume *volume) : fVolume(volume), @@ -75,12 +114,13 @@ VMCache* -DataContainer::GetCache() +DataContainer::GetCache(struct vnode* vnode) { // TODO: Because we always get the cache for files on creation vs. on demand, // this means files (no matter how small) always use cache mode at present. if (!_IsCacheMode()) _SwitchToCacheMode(); + ((VMForVnodeCache*)fCache)->fVnode = vnode; return fCache; } @@ -249,11 +289,15 @@ status_t DataContainer::_SwitchToCacheMode() { - status_t error = VMCacheFactory::CreateAnonymousCache(fCache, false, 0, - 0, false, VM_PRIORITY_USER); + VMForVnodeCache* cache = new(gVnodeCacheObjectCache, 0) VMForVnodeCache; + if (cache == NULL) + return B_NO_MEMORY; + + status_t error = cache->Init(); if (error != B_OK) return error; + fCache = cache; fCache->temporary = 1; fCache->unmergeable = 1; fCache->virtual_end = fSize; diff --git a/src/add-ons/kernel/file_systems/ramfs/DataContainer.h b/src/add-ons/kernel/file_systems/ramfs/DataContainer.h index 0d30dc4..79909da 100644 --- a/src/add-ons/kernel/file_systems/ramfs/DataContainer.h +++ b/src/add-ons/kernel/file_systems/ramfs/DataContainer.h @@ -28,7 +28,7 @@ status_t Resize(off_t newSize); off_t GetSize() const { return fSize; } - VMCache* GetCache(); + VMCache* GetCache(struct vnode* vnode); virtual status_t ReadAt(off_t offset, void *buffer, size_t size, size_t *bytesRead); diff --git a/src/add-ons/kernel/file_systems/ramfs/Jamfile b/src/add-ons/kernel/file_systems/ramfs/Jamfile index bcbe864..44583a9 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Jamfile +++ b/src/add-ons/kernel/file_systems/ramfs/Jamfile @@ -1,8 +1,9 @@ SubDir HAIKU_TOP src add-ons kernel file_systems ramfs ; UsePrivateKernelHeaders ; UsePrivateHeaders file_systems storage ; UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel drivers disk virtual ram_disk ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src system kernel vm ] ; DEFINES += DEBUG_APP="\\\"ramfs\\\"" ; diff --git a/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp index 35a40f1..d56e322 100644 --- a/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp @@ -856,7 +856,7 @@ // set cache in vnode struct vnode* vnode; if (vfs_lookup_vnode(_volume->id, node->GetID(), &vnode) == B_OK) { - vfs_set_vnode_cache(vnode, file->GetCache()); + vfs_set_vnode_cache(vnode, file->GetCache(vnode)); } } } -- gitore 0.2.3