1 #ifndef FIO_OS_LINUX_H 2 #define FIO_OS_LINUX_H 3 4 #define FIO_OS os_linux 5 6 #include <sys/ioctl.h> 7 #include <sys/uio.h> 8 #include <sys/syscall.h> 9 #include <sys/vfs.h> 10 #include <sys/mman.h> 11 #include <unistd.h> 12 #include <fcntl.h> 13 #include <errno.h> 14 #include <sched.h> 15 #include <linux/unistd.h> 16 #include <linux/raw.h> 17 #include <linux/major.h> 18 19 #include "binject.h" 20 #include "../file.h" 21 22 #define FIO_HAVE_CPU_AFFINITY 23 #define FIO_HAVE_DISK_UTIL 24 #define FIO_HAVE_SGIO 25 #define FIO_HAVE_IOPRIO 26 #define FIO_HAVE_IOSCHED_SWITCH 27 #define FIO_HAVE_ODIRECT 28 #define FIO_HAVE_HUGETLB 29 #define FIO_HAVE_RAWBIND 30 #define FIO_HAVE_BLKTRACE 31 #define FIO_HAVE_PSHARED_MUTEX 32 #define FIO_HAVE_CL_SIZE 33 #define FIO_HAVE_CGROUPS 34 #define FIO_HAVE_FS_STAT 35 #define FIO_HAVE_TRIM 36 #define FIO_HAVE_BINJECT 37 #define FIO_HAVE_GETTID 38 #define FIO_USE_GENERIC_INIT_RANDOM_STATE 39 40 #ifdef MAP_HUGETLB 41 #define FIO_HAVE_MMAP_HUGE 42 #endif 43 44 #define OS_MAP_ANON MAP_ANONYMOUS 45 46 typedef cpu_set_t os_cpu_mask_t; 47 48 typedef struct drand48_data os_random_state_t; 49 50 #ifdef CONFIG_3ARG_AFFINITY 51 #define fio_setaffinity(pid, cpumask) \ 52 sched_setaffinity((pid), sizeof(cpumask), &(cpumask)) 53 #define fio_getaffinity(pid, ptr) \ 54 sched_getaffinity((pid), sizeof(cpu_set_t), (ptr)) 55 #elif defined(CONFIG_2ARG_AFFINITY) 56 #define fio_setaffinity(pid, cpumask) \ 57 sched_setaffinity((pid), &(cpumask)) 58 #define fio_getaffinity(pid, ptr) \ 59 sched_getaffinity((pid), (ptr)) 60 #endif 61 62 #define fio_cpu_clear(mask, cpu) (void) CPU_CLR((cpu), (mask)) 63 #define fio_cpu_set(mask, cpu) (void) CPU_SET((cpu), (mask)) 64 #define fio_cpu_isset(mask, cpu) CPU_ISSET((cpu), (mask)) 65 #define fio_cpu_count(mask) CPU_COUNT((mask)) 66 67 static inline int fio_cpuset_init(os_cpu_mask_t *mask) 68 { 69 CPU_ZERO(mask); 70 return 0; 71 } 72 73 static inline int fio_cpuset_exit(os_cpu_mask_t *mask) 74 { 75 return 0; 76 } 77 78 #define FIO_MAX_CPUS CPU_SETSIZE 79 80 enum { 81 IOPRIO_CLASS_NONE, 82 IOPRIO_CLASS_RT, 83 IOPRIO_CLASS_BE, 84 IOPRIO_CLASS_IDLE, 85 }; 86 87 enum { 88 IOPRIO_WHO_PROCESS = 1, 89 IOPRIO_WHO_PGRP, 90 IOPRIO_WHO_USER, 91 }; 92 93 #define IOPRIO_BITS 16 94 #define IOPRIO_CLASS_SHIFT 13 95 96 static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio) 97 { 98 /* 99 * If no class is set, assume BE 100 */ 101 if (!ioprio_class) 102 ioprio_class = IOPRIO_CLASS_BE; 103 104 ioprio |= ioprio_class << IOPRIO_CLASS_SHIFT; 105 return syscall(__NR_ioprio_set, which, who, ioprio); 106 } 107 108 static inline int gettid(void) 109 { 110 return syscall(__NR_gettid); 111 } 112 113 #define SPLICE_DEF_SIZE (64*1024) 114 115 #ifndef BLKGETSIZE64 116 #define BLKGETSIZE64 _IOR(0x12,114,size_t) 117 #endif 118 119 #ifndef BLKFLSBUF 120 #define BLKFLSBUF _IO(0x12,97) 121 #endif 122 123 #ifndef BLKDISCARD 124 #define BLKDISCARD _IO(0x12,119) 125 #endif 126 127 static inline int blockdev_invalidate_cache(struct fio_file *f) 128 { 129 return ioctl(f->fd, BLKFLSBUF); 130 } 131 132 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes) 133 { 134 if (!ioctl(f->fd, BLKGETSIZE64, bytes)) 135 return 0; 136 137 return errno; 138 } 139 140 static inline unsigned long long os_phys_mem(void) 141 { 142 long pagesize, pages; 143 144 pagesize = sysconf(_SC_PAGESIZE); 145 pages = sysconf(_SC_PHYS_PAGES); 146 if (pages == -1 || pagesize == -1) 147 return 0; 148 149 return (unsigned long long) pages * (unsigned long long) pagesize; 150 } 151 152 static inline void os_random_seed(unsigned long seed, os_random_state_t *rs) 153 { 154 srand48_r(seed, rs); 155 } 156 157 static inline long os_random_long(os_random_state_t *rs) 158 { 159 long val; 160 161 lrand48_r(rs, &val); 162 return val; 163 } 164 165 static inline int fio_lookup_raw(dev_t dev, int *majdev, int *mindev) 166 { 167 struct raw_config_request rq; 168 int fd; 169 170 if (major(dev) != RAW_MAJOR) 171 return 1; 172 173 /* 174 * we should be able to find /dev/rawctl or /dev/raw/rawctl 175 */ 176 fd = open("/dev/rawctl", O_RDONLY); 177 if (fd < 0) { 178 fd = open("/dev/raw/rawctl", O_RDONLY); 179 if (fd < 0) 180 return 1; 181 } 182 183 rq.raw_minor = minor(dev); 184 if (ioctl(fd, RAW_GETBIND, &rq) < 0) { 185 close(fd); 186 return 1; 187 } 188 189 close(fd); 190 *majdev = rq.block_major; 191 *mindev = rq.block_minor; 192 return 0; 193 } 194 195 #ifdef O_NOATIME 196 #define FIO_O_NOATIME O_NOATIME 197 #else 198 #define FIO_O_NOATIME 0 199 #endif 200 201 #ifdef O_ATOMIC 202 #define OS_O_ATOMIC O_ATOMIC 203 #else 204 #define OS_O_ATOMIC 040000000 205 #endif 206 207 #ifdef MADV_REMOVE 208 #define FIO_MADV_FREE MADV_REMOVE 209 #endif 210 211 #define fio_swap16(x) __bswap_16(x) 212 #define fio_swap32(x) __bswap_32(x) 213 #define fio_swap64(x) __bswap_64(x) 214 215 #define CACHE_LINE_FILE \ 216 "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size" 217 218 static inline int arch_cache_line_size(void) 219 { 220 char size[32]; 221 int fd, ret; 222 223 fd = open(CACHE_LINE_FILE, O_RDONLY); 224 if (fd < 0) 225 return -1; 226 227 ret = read(fd, size, sizeof(size)); 228 229 close(fd); 230 231 if (ret <= 0) 232 return -1; 233 else 234 return atoi(size); 235 } 236 237 static inline unsigned long long get_fs_size(const char *path) 238 { 239 unsigned long long ret; 240 struct statfs s; 241 242 if (statfs(path, &s) < 0) 243 return -1ULL; 244 245 ret = s.f_bsize; 246 ret *= (unsigned long long) s.f_bfree; 247 return ret; 248 } 249 250 static inline int os_trim(int fd, unsigned long long start, 251 unsigned long long len) 252 { 253 uint64_t range[2]; 254 255 range[0] = start; 256 range[1] = len; 257 258 if (!ioctl(fd, BLKDISCARD, range)) 259 return 0; 260 261 return errno; 262 } 263 264 #ifdef CONFIG_SCHED_IDLE 265 static inline int fio_set_sched_idle(void) 266 { 267 struct sched_param p = { .sched_priority = 0, }; 268 return sched_setscheduler(gettid(), SCHED_IDLE, &p); 269 } 270 #endif 271 272 #endif 273