Blame src/vmount/ntapi_vms_cache.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
dd89bb
/*  Copyright (C) 2013,2014,2015  Z. Gilboa             */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <psxtypes/psxtypes.h>
dd89bb
#include <ntapi/nt_port.h>
dd89bb
#include <ntapi/nt_vmount.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
#include "ntapi_impl.h"
dd89bb
dd89bb
dd89bb
typedef struct nt_vms_cache_interface {
dd89bb
	nt_vms_system *		vms_sys;
dd89bb
	struct dalist_ex	cache;
dd89bb
	size_t			alloc_size;
dd89bb
	uintptr_t		buffer[1];
dd89bb
} nt_vms_cache_context;
dd89bb
dd89bb
dd89bb
typedef struct _nt_vms_cache_record {
dd89bb
	void *			hfile;
dd89bb
	uint32_t		dev_name_hash;
dd89bb
	nt_large_integer	index_number;
dd89bb
	intptr_t		client_key;
dd89bb
	intptr_t		server_key;
dd89bb
} nt_vms_cache_record;
dd89bb
dd89bb
dd89bb
int32_t __stdcall	__ntapi_vms_cache_free(
dd89bb
	__in	nt_vms_cache		vms_cache)
dd89bb
{
dd89bb
	int32_t		status;
dd89bb
	void *		region_addr;
dd89bb
	size_t		region_size;
dd89bb
dd89bb
	/* validation */
dd89bb
	if (!vms_cache)
dd89bb
		return NT_STATUS_INVALID_PARAMETER;
dd89bb
dd89bb
	/* free memory */
dd89bb
	region_addr = vms_cache;
dd89bb
	region_size = vms_cache->alloc_size;
dd89bb
dd89bb
	status = __ntapi->zw_free_virtual_memory(
dd89bb
		NT_CURRENT_PROCESS_HANDLE,
dd89bb
		&region_addr,
dd89bb
		&region_size,
dd89bb
		NT_MEM_RELEASE);
dd89bb
dd89bb
	return status;
dd89bb
}
dd89bb
dd89bb
/* vms optional cache functions */
dd89bb
nt_vms_cache __stdcall	__ntapi_vms_cache_alloc(
dd89bb
	__in	nt_vms_system *		vms_sys,
dd89bb
	__in	uint32_t		flags	__reserved,
dd89bb
	__in	void *			options	__reserved,
dd89bb
	__out	int32_t *		status	__optional)
dd89bb
{
dd89bb
	int32_t			_status;
dd89bb
	void *			buffer;
dd89bb
	size_t			buffer_size;
dd89bb
	nt_vms_cache_context *	vms_cache;
dd89bb
dd89bb
	/* status */
dd89bb
	if (!status) status = &_status;
dd89bb
dd89bb
	/* validation */
dd89bb
	if (!vms_sys) {
dd89bb
		*status = NT_STATUS_INVALID_PARAMETER;
dd89bb
		return (nt_vms_cache)0;
dd89bb
	}
dd89bb
dd89bb
	/* calculate size */
dd89bb
	buffer_size =  sizeof(nt_vms_cache_context);
dd89bb
	buffer_size += vms_sys->vms_points_cap * (sizeof(nt_vms_cache_record) - sizeof(uintptr_t));
dd89bb
dd89bb
	/* allocate buffer */
dd89bb
	*status = __ntapi->zw_allocate_virtual_memory(
dd89bb
		NT_CURRENT_PROCESS_HANDLE,
dd89bb
		&buffer,
dd89bb
		0,
dd89bb
		&buffer_size,
dd89bb
		NT_MEM_COMMIT,
dd89bb
		NT_PAGE_READWRITE);
dd89bb
dd89bb
	if (*status) return (nt_vms_cache)0;
dd89bb
dd89bb
	/* init vms cache */
dd89bb
	vms_cache = (nt_vms_cache_context *)buffer;
dd89bb
	vms_cache->vms_sys	= vms_sys;
dd89bb
	vms_cache->alloc_size	= buffer_size;
dd89bb
dd89bb
	/* init list */
dd89bb
	*status = dalist_init_ex(
dd89bb
		&vms_cache->cache,
dd89bb
		sizeof(nt_vms_cache_record),
dd89bb
		0x1000,
dd89bb
		__ntapi->zw_allocate_virtual_memory,
dd89bb
		DALIST_MEMFN_NT_ALLOCATE_VIRTUAL_MEMORY);
dd89bb
dd89bb
	if (*status != DALIST_OK) {
dd89bb
		*status = NT_STATUS_UNSUCCESSFUL;
dd89bb
		__ntapi_vms_cache_free(vms_cache);
dd89bb
		return (nt_vms_cache)0;
dd89bb
	}
dd89bb
dd89bb
	/* set list buffer */
dd89bb
	buffer_size -= (size_t)&(((nt_vms_cache_context *)0)->buffer);
dd89bb
dd89bb
	*status = dalist_deposit_memory_block(
dd89bb
		&vms_cache->cache,
dd89bb
		&vms_cache->buffer,
dd89bb
		buffer_size);
dd89bb
dd89bb
	return vms_cache;
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t __stdcall	__ntapi_vms_cache_record_append(
dd89bb
	__in	nt_vms_cache		cache,
dd89bb
	__in	void *			hfile,
dd89bb
	__in	uint32_t		dev_name_hash,
dd89bb
	__in	nt_large_integer	index_number,
dd89bb
	__in	intptr_t		client_key,
dd89bb
	__in	intptr_t		server_key)
dd89bb
{
dd89bb
	int32_t			status;
dd89bb
	struct dalist_node_ex *	node;
dd89bb
	nt_vms_cache_record *	cache_record;
dd89bb
dd89bb
	status = dalist_get_node_by_key(
dd89bb
			&cache->cache,
dd89bb
			&node,
dd89bb
			(uintptr_t)hfile,
dd89bb
			DALIST_NODE_TYPE_EXISTING,
dd89bb
			(uintptr_t *)0);
dd89bb
dd89bb
	if (status != DALIST_OK)
dd89bb
		status = NT_STATUS_INTERNAL_ERROR;
dd89bb
	else if (node)
dd89bb
		status = NT_STATUS_OBJECTID_EXISTS;
dd89bb
	else {
dd89bb
		status = dalist_get_free_node(&cache->cache,(void **)&node);
dd89bb
dd89bb
		if (status == DALIST_OK) {
dd89bb
			cache_record = (nt_vms_cache_record *)&node->dblock;
dd89bb
dd89bb
			__ntapi->tt_aligned_block_memset(
dd89bb
				node,
dd89bb
				0,
dd89bb
				(uintptr_t)&((struct dalist_node_ex *)0)->dblock + sizeof(*cache_record));
dd89bb
dd89bb
			node->key = (uintptr_t)hfile;
dd89bb
dd89bb
			cache_record->hfile		= hfile;
dd89bb
			cache_record->dev_name_hash	= dev_name_hash;
dd89bb
			cache_record->index_number.quad	= index_number.quad;
dd89bb
			cache_record->client_key	= client_key;
dd89bb
			cache_record->server_key	= server_key;
dd89bb
dd89bb
			status = dalist_insert_node_by_key(
dd89bb
				&cache->cache,
dd89bb
				node);
dd89bb
dd89bb
			if (status != DALIST_OK)
dd89bb
				dalist_deposit_free_node(
dd89bb
					&cache->cache,
dd89bb
					node);
dd89bb
		}
dd89bb
	}
dd89bb
dd89bb
	return status;
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t __stdcall	__ntapi_vms_cache_record_remove(
dd89bb
	__in	nt_vms_cache		cache,
dd89bb
	__in	void *			hfile,
dd89bb
	__in	uint32_t		dev_name_hash,
dd89bb
	__in	nt_large_integer	index_number)
dd89bb
{
dd89bb
	int32_t			status;
dd89bb
	struct dalist_node_ex *	node;
dd89bb
dd89bb
	status = dalist_get_node_by_key(
dd89bb
			&cache->cache,
dd89bb
			&node,
dd89bb
			(uintptr_t)hfile,
dd89bb
			DALIST_NODE_TYPE_EXISTING,
dd89bb
			(uintptr_t *)0);
dd89bb
dd89bb
	if (status != DALIST_OK)
dd89bb
		status = NT_STATUS_INTERNAL_ERROR;
dd89bb
	else if (node)
dd89bb
		status = NT_STATUS_INVALID_PARAMETER;
dd89bb
	else {
dd89bb
		status = dalist_discard_node(
dd89bb
			&cache->cache,
dd89bb
			node);
dd89bb
dd89bb
		if (status != DALIST_OK)
dd89bb
			status = NT_STATUS_INTERNAL_ERROR;
dd89bb
	}
dd89bb
dd89bb
	return status;
dd89bb
}