os-linux.h revision a5f3027cb0495dfe217b2626d248fcc054e7e878
1#ifndef FIO_OS_LINUX_H 2#define FIO_OS_LINUX_H 3 4#include <sys/ioctl.h> 5#include <sys/uio.h> 6#include <sys/syscall.h> 7#include <sys/vfs.h> 8#include <unistd.h> 9#include <fcntl.h> 10#include <errno.h> 11#include <sched.h> 12#include <linux/unistd.h> 13#include <linux/raw.h> 14#include <linux/major.h> 15 16#include "indirect.h" 17 18#define FIO_HAVE_LIBAIO 19#define FIO_HAVE_POSIXAIO 20#define FIO_HAVE_FADVISE 21#define FIO_HAVE_CPU_AFFINITY 22#define FIO_HAVE_DISK_UTIL 23#define FIO_HAVE_SGIO 24#define FIO_HAVE_IOPRIO 25#define FIO_HAVE_SPLICE 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_STRSEP 32#define FIO_HAVE_FALLOCATE 33#define FIO_HAVE_POSIXAIO_FSYNC 34#define FIO_HAVE_PSHARED_MUTEX 35#define FIO_HAVE_CL_SIZE 36#define FIO_HAVE_CGROUPS 37#define FIO_HAVE_FDATASYNC 38#define FIO_HAVE_FS_STAT 39#define FIO_HAVE_TRIM 40 41#ifdef SYNC_FILE_RANGE_WAIT_BEFORE 42#define FIO_HAVE_SYNC_FILE_RANGE 43#endif 44 45#define OS_MAP_ANON MAP_ANONYMOUS 46 47#ifndef CLOCK_MONOTONIC 48#define CLOCK_MONOTONIC 1 49#endif 50 51typedef cpu_set_t os_cpu_mask_t; 52 53typedef struct drand48_data os_random_state_t; 54 55/* 56 * we want fadvise64 really, but it's so tangled... later 57 */ 58#ifdef FIO_HAVE_FADVISE 59#define fadvise(fd, off, len, advice) \ 60 posix_fadvise((fd), (off_t)(off), (len), (advice)) 61#endif 62 63/* 64 * If you are on an ancient glibc (2.3.2), then define GLIBC_2_3_2 if you want 65 * the affinity helpers to work. 66 */ 67#ifndef GLIBC_2_3_2 68#define fio_setaffinity(pid, cpumask) \ 69 sched_setaffinity((pid), sizeof(cpumask), &(cpumask)) 70#define fio_getaffinity(pid, ptr) \ 71 sched_getaffinity((pid), sizeof(cpu_set_t), (ptr)) 72#else 73#define fio_setaffinity(pid, cpumask) \ 74 sched_setaffinity((pid), &(cpumask)) 75#define fio_getaffinity(pid, ptr) \ 76 sched_getaffinity((pid), (ptr)) 77#endif 78 79#define fio_cpu_clear(mask, cpu) CPU_CLR((cpu), (mask)) 80#define fio_cpu_set(mask, cpu) CPU_SET((cpu), (mask)) 81 82static inline int fio_cpuset_init(os_cpu_mask_t *mask) 83{ 84 CPU_ZERO(mask); 85 return 0; 86} 87 88static inline int fio_cpuset_exit(os_cpu_mask_t *mask) 89{ 90 return 0; 91} 92 93#define FIO_MAX_CPUS CPU_SETSIZE 94 95static inline int ioprio_set(int which, int who, int ioprio) 96{ 97 return syscall(__NR_ioprio_set, which, who, ioprio); 98} 99 100/* 101 * Just check for SPLICE_F_MOVE, if that isn't there, assume the others 102 * aren't either. 103 */ 104#ifndef SPLICE_F_MOVE 105#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */ 106#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */ 107 /* we may still block on the fd we splice */ 108 /* from/to, of course */ 109#define SPLICE_F_MORE (0x04) /* expect more data */ 110#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */ 111 112static inline int splice(int fdin, loff_t *off_in, int fdout, loff_t *off_out, 113 size_t len, unsigned int flags) 114{ 115 return syscall(__NR_sys_splice, fdin, off_in, fdout, off_out, len, flags); 116} 117 118static inline int tee(int fdin, int fdout, size_t len, unsigned int flags) 119{ 120 return syscall(__NR_sys_tee, fdin, fdout, len, flags); 121} 122 123static inline int vmsplice(int fd, const struct iovec *iov, 124 unsigned long nr_segs, unsigned int flags) 125{ 126 return syscall(__NR_sys_vmsplice, fd, iov, nr_segs, flags); 127} 128#endif 129 130#define SPLICE_DEF_SIZE (64*1024) 131 132#ifdef FIO_HAVE_SYSLET 133 134struct syslet_uatom; 135struct async_head_user; 136 137/* 138 * syslet stuff 139 */ 140static inline struct syslet_uatom * 141async_exec(struct syslet_uatom *atom, struct async_head_user *ahu) 142{ 143 return (struct syslet_uatom *) syscall(__NR_async_exec, atom, ahu); 144} 145 146static inline long 147async_wait(unsigned long min_wait_events, unsigned long user_ring_idx, 148 struct async_head_user *ahu) 149{ 150 return syscall(__NR_async_wait, min_wait_events, 151 user_ring_idx, ahu); 152} 153 154static inline long async_thread(void *event, struct async_head_user *ahu) 155{ 156 return syscall(__NR_async_thread, event, ahu); 157} 158 159static inline long umem_add(unsigned long *uptr, unsigned long inc) 160{ 161 return syscall(__NR_umem_add, uptr, inc); 162} 163#endif /* FIO_HAVE_SYSLET */ 164 165enum { 166 IOPRIO_CLASS_NONE, 167 IOPRIO_CLASS_RT, 168 IOPRIO_CLASS_BE, 169 IOPRIO_CLASS_IDLE, 170}; 171 172enum { 173 IOPRIO_WHO_PROCESS = 1, 174 IOPRIO_WHO_PGRP, 175 IOPRIO_WHO_USER, 176}; 177 178#define IOPRIO_BITS 16 179#define IOPRIO_CLASS_SHIFT 13 180 181#ifndef BLKGETSIZE64 182#define BLKGETSIZE64 _IOR(0x12,114,size_t) 183#endif 184 185#ifndef BLKFLSBUF 186#define BLKFLSBUF _IO(0x12,97) 187#endif 188 189#ifndef BLKDISCARD 190#define BLKDISCARD _IO(0x12,119) 191#endif 192 193static inline int blockdev_invalidate_cache(int fd) 194{ 195 return ioctl(fd, BLKFLSBUF); 196} 197 198static inline int blockdev_size(int fd, unsigned long long *bytes) 199{ 200 if (!ioctl(fd, BLKGETSIZE64, bytes)) 201 return 0; 202 203 return errno; 204} 205 206static inline unsigned long long os_phys_mem(void) 207{ 208 long pagesize, pages; 209 210 pagesize = sysconf(_SC_PAGESIZE); 211 pages = sysconf(_SC_PHYS_PAGES); 212 if (pages == -1 || pagesize == -1) 213 return 0; 214 215 return (unsigned long long) pages * (unsigned long long) pagesize; 216} 217 218static inline void os_random_seed(unsigned long seed, os_random_state_t *rs) 219{ 220 srand48_r(seed, rs); 221} 222 223static inline long os_random_long(os_random_state_t *rs) 224{ 225 long val; 226 227 lrand48_r(rs, &val); 228 return val; 229} 230 231static inline int fio_lookup_raw(dev_t dev, int *majdev, int *mindev) 232{ 233 struct raw_config_request rq; 234 int fd; 235 236 if (major(dev) != RAW_MAJOR) 237 return 1; 238 239 /* 240 * we should be able to find /dev/rawctl or /dev/raw/rawctl 241 */ 242 fd = open("/dev/rawctl", O_RDONLY); 243 if (fd < 0) { 244 fd = open("/dev/raw/rawctl", O_RDONLY); 245 if (fd < 0) 246 return 1; 247 } 248 249 rq.raw_minor = minor(dev); 250 if (ioctl(fd, RAW_GETBIND, &rq) < 0) { 251 close(fd); 252 return 1; 253 } 254 255 close(fd); 256 *majdev = rq.block_major; 257 *mindev = rq.block_minor; 258 return 0; 259} 260 261#ifdef O_NOATIME 262#define FIO_O_NOATIME O_NOATIME 263#else 264#define FIO_O_NOATIME 0 265#endif 266 267#ifdef MADV_REMOVE 268#define FIO_MADV_FREE MADV_REMOVE 269#endif 270 271#define CACHE_LINE_FILE \ 272 "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size" 273 274static inline int arch_cache_line_size(void) 275{ 276 char size[32]; 277 int fd, ret; 278 279 fd = open(CACHE_LINE_FILE, O_RDONLY); 280 if (fd < 0) 281 return -1; 282 283 ret = read(fd, size, sizeof(size)); 284 285 close(fd); 286 287 if (ret <= 0) 288 return -1; 289 else 290 return atoi(size); 291} 292 293static inline unsigned long long get_fs_size(const char *path) 294{ 295 unsigned long long ret; 296 struct statfs s; 297 298 if (statfs(path, &s) < 0) 299 return -1ULL; 300 301 ret = s.f_bsize; 302 ret *= (unsigned long long) s.f_bfree; 303 return ret; 304} 305 306static inline int os_trim(int fd, unsigned long long start, 307 unsigned long long len) 308{ 309 uint64_t range[2]; 310 311 range[0] = start; 312 range[1] = len; 313 314 if (!ioctl(fd, BLKDISCARD, range)) 315 return 0; 316 317 return errno; 318} 319 320#endif 321