xref: /haiku/headers/private/kernel/util/fs_trim_support.h (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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 <AutoDeleter.h>
10 #include <KernelExport.h>
11 #include <SupportDefs.h>
12 
13 #include <kernel.h>
14 #include <syscall_restart.h>
15 
16 
17 static inline status_t
18 get_trim_data_from_user(void* buffer, size_t size, MemoryDeleter& deleter,
19 	fs_trim_data*& _trimData)
20 {
21 	if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer)) {
22 		// Called from kernel
23 		_trimData = (fs_trim_data*)buffer;
24 		return B_OK;
25 	}
26 
27 	// Called from userland
28 	if (!IS_USER_ADDRESS(buffer))
29 		return B_BAD_ADDRESS;
30 
31 	uint32 count;
32 	if (user_memcpy(&count, buffer, sizeof(count)) != B_OK)
33 		return B_BAD_ADDRESS;
34 
35 	size_t bytes = (count - 1) * sizeof(uint64) * 2 + sizeof(fs_trim_data);
36 	if (bytes > size)
37 		return B_BAD_VALUE;
38 
39 	void* trimBuffer = malloc(bytes);
40 	if (trimBuffer == NULL)
41 		return B_NO_MEMORY;
42 
43 	if (user_memcpy(trimBuffer, buffer, bytes) != B_OK) {
44 		free(trimBuffer);
45 		return B_BAD_ADDRESS;
46 	}
47 
48 	// The passed in MemoryDeleter needs to take care of freeing the buffer
49 	// later, since we had to allocate it.
50 	deleter.SetTo(trimBuffer);
51 
52 	_trimData = (fs_trim_data*)trimBuffer;
53 	return B_OK;
54 }
55 
56 
57 static inline status_t
58 copy_trim_data_to_user(void* buffer, fs_trim_data* trimData)
59 {
60 	if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer))
61 		return B_OK;
62 
63 	if (!IS_USER_ADDRESS(buffer))
64 		return B_BAD_ADDRESS;
65 
66 	// Do not copy any ranges
67 	return user_memcpy(buffer, trimData, offsetof(fs_trim_data, ranges));
68 }
69 
70 
71 #endif	// _FS_TRIM_SUPPORT_H
72