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