1/*
2 * Copyright 2013, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT license.
4 */
5#ifndef _FS_TRIM_SUPPORT_H
6#define _FS_TRIM_SUPPORT_H
7
8
9#include <KernelExport.h>
10
11#include <kernel.h>
12#include <syscall_restart.h>
13
14
15static inline status_t
16get_trim_data_from_user(void* buffer, size_t size, MemoryDeleter& deleter,
17	fs_trim_data*& _trimData)
18{
19	if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer)) {
20		// Called from kernel
21		_trimData = (fs_trim_data*)buffer;
22		return B_OK;
23	}
24
25	// Called from userland
26	if (!IS_USER_ADDRESS(buffer))
27		return B_BAD_ADDRESS;
28
29	uint32 count;
30	if (user_memcpy(&count, buffer, sizeof(count)) != B_OK)
31		return B_BAD_ADDRESS;
32
33	size_t bytes = (count - 1) * sizeof(uint64) * 2 + sizeof(fs_trim_data);
34	if (bytes > size)
35		return B_BAD_VALUE;
36
37	void* trimBuffer = malloc(bytes);
38	if (trimBuffer == NULL)
39		return B_NO_MEMORY;
40
41	if (user_memcpy(trimBuffer, buffer, bytes) != B_OK) {
42		free(trimBuffer);
43		return B_BAD_ADDRESS;
44	}
45
46	// The passed in MemoryDeleter needs to take care of freeing the buffer
47	// later, since we had to allocate it.
48	deleter.SetTo(trimBuffer);
49
50	_trimData = (fs_trim_data*)trimBuffer;
51	return B_OK;
52}
53
54
55static inline status_t
56copy_trim_data_to_user(void* buffer, fs_trim_data* trimData)
57{
58	if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer))
59		return B_OK;
60
61	if (!IS_USER_ADDRESS(buffer))
62		return B_BAD_ADDRESS;
63
64	// Do not copy any ranges
65	return user_memcpy(buffer, trimData, sizeof(uint64) * 2);
66}
67
68
69#endif	// _FS_TRIM_SUPPORT_H
70