xref: /haiku/headers/private/kernel/util/fs_trim_support.h (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
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 
15 static inline status_t
16 get_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 
55 static inline status_t
56 copy_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