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