⛏️ index : haiku.git

author Augustin Cavalier <waddlesplash@gmail.com> 2024-08-14 18:35:37.0 -04:00:00
committer waddlesplash <waddlesplash@gmail.com> 2024-08-14 22:37:43.0 +00:00:00
commit
0750f5b62dd4d079fc4e8329f9a27ac669c2f85a [patch]
tree
ab680ae4bc4dafa65c810debcdcd279c7df1bfcb
parent
47e97829f6f17a4f938f53e3d01fbcbca2a1c8e3
download
0750f5b62dd4d079fc4e8329f9a27ac669c2f85a.tar.gz

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 <waddlesplash@gmail.com>

Diff

 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 <vm/VMCache.h>


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 <StackOrHeapArray.h>
#include <util/AutoLock.h>
#include <util/BitUtils.h>
#include <slab/Slab.h>

#include <vfs.h>
#include <vm/VMCache.h>
#include <vm/vm_page.h>
#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));
					}
				}
			}