Add TD_F_SYNCS thread flag
[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/sysmacros.h>
10 #include <sys/vfs.h>
11 #include <sys/mman.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 #include <sched.h>
16 #include <linux/unistd.h>
17 #include <linux/major.h>
18 #include <linux/fs.h>
19 #include <scsi/sg.h>
20
21 #ifdef ARCH_HAVE_CRC_CRYPTO
22 #include <sys/auxv.h>
23 #ifndef HWCAP_PMULL
24 #define HWCAP_PMULL             (1 << 4)
25 #endif /* HWCAP_PMULL */
26 #ifndef HWCAP_CRC32
27 #define HWCAP_CRC32             (1 << 7)
28 #endif /* HWCAP_CRC32 */
29 #endif /* ARCH_HAVE_CRC_CRYPTO */
30
31 #include "./os-linux-syscall.h"
32 #include "../file.h"
33
34 #ifndef __has_builtin         // Optional of course.
35   #define __has_builtin(x) 0  // Compatibility with non-clang compilers.
36 #endif
37
38 #define FIO_HAVE_CPU_AFFINITY
39 #define FIO_HAVE_DISK_UTIL
40 #define FIO_HAVE_SGIO
41 #define FIO_HAVE_IOPRIO
42 #define FIO_HAVE_IOPRIO_CLASS
43 #define FIO_HAVE_IOSCHED_SWITCH
44 #define FIO_HAVE_ODIRECT
45 #define FIO_HAVE_HUGETLB
46 #define FIO_HAVE_BLKTRACE
47 #define FIO_HAVE_CL_SIZE
48 #define FIO_HAVE_CGROUPS
49 #define FIO_HAVE_FS_STAT
50 #define FIO_HAVE_TRIM
51 #define FIO_HAVE_GETTID
52 #define FIO_USE_GENERIC_INIT_RANDOM_STATE
53 #define FIO_HAVE_PWRITEV2
54 #define FIO_HAVE_SHM_ATTACH_REMOVED
55
56 #ifdef MAP_HUGETLB
57 #define FIO_HAVE_MMAP_HUGE
58 #endif
59
60 #define OS_MAP_ANON             MAP_ANONYMOUS
61
62 #define FIO_EXT_ENG_DIR "/usr/local/lib/fio"
63
64 typedef cpu_set_t os_cpu_mask_t;
65
66 #ifdef CONFIG_3ARG_AFFINITY
67 #define fio_setaffinity(pid, cpumask)           \
68         sched_setaffinity((pid), sizeof(cpumask), &(cpumask))
69 #define fio_getaffinity(pid, ptr)       \
70         sched_getaffinity((pid), sizeof(cpu_set_t), (ptr))
71 #elif defined(CONFIG_2ARG_AFFINITY)
72 #define fio_setaffinity(pid, cpumask)   \
73         sched_setaffinity((pid), &(cpumask))
74 #define fio_getaffinity(pid, ptr)       \
75         sched_getaffinity((pid), (ptr))
76 #endif
77
78 #ifdef CONFIG_PTHREAD_GETAFFINITY
79 #define FIO_HAVE_GET_THREAD_AFFINITY
80 #define fio_get_thread_affinity(mask)   \
81         pthread_getaffinity_np(pthread_self(), sizeof(mask), &(mask))
82 #endif
83
84 #define fio_cpu_clear(mask, cpu)        (void) CPU_CLR((cpu), (mask))
85 #define fio_cpu_set(mask, cpu)          (void) CPU_SET((cpu), (mask))
86 #define fio_cpu_isset(mask, cpu)        (CPU_ISSET((cpu), (mask)) != 0)
87 #define fio_cpu_count(mask)             CPU_COUNT((mask))
88
89 static inline int fio_cpuset_init(os_cpu_mask_t *mask)
90 {
91         CPU_ZERO(mask);
92         return 0;
93 }
94
95 static inline int fio_cpuset_exit(os_cpu_mask_t *mask)
96 {
97         return 0;
98 }
99
100 #define FIO_MAX_CPUS                    CPU_SETSIZE
101
102 enum {
103         IOPRIO_CLASS_NONE,
104         IOPRIO_CLASS_RT,
105         IOPRIO_CLASS_BE,
106         IOPRIO_CLASS_IDLE,
107 };
108
109 enum {
110         IOPRIO_WHO_PROCESS = 1,
111         IOPRIO_WHO_PGRP,
112         IOPRIO_WHO_USER,
113 };
114
115 #define IOPRIO_BITS             16
116 #define IOPRIO_CLASS_SHIFT      13
117
118 #define IOPRIO_MIN_PRIO         0       /* highest priority */
119 #define IOPRIO_MAX_PRIO         7       /* lowest priority */
120
121 #define IOPRIO_MIN_PRIO_CLASS   0
122 #define IOPRIO_MAX_PRIO_CLASS   3
123
124 static inline int ioprio_value(int ioprio_class, int ioprio)
125 {
126         /*
127          * If no class is set, assume BE
128          */
129         if (!ioprio_class)
130                 ioprio_class = IOPRIO_CLASS_BE;
131
132         return (ioprio_class << IOPRIO_CLASS_SHIFT) | ioprio;
133 }
134
135 static inline bool ioprio_value_is_class_rt(unsigned int priority)
136 {
137         return (priority >> IOPRIO_CLASS_SHIFT) == IOPRIO_CLASS_RT;
138 }
139
140 static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio)
141 {
142         return syscall(__NR_ioprio_set, which, who,
143                        ioprio_value(ioprio_class, ioprio));
144 }
145
146 #ifndef CONFIG_HAVE_GETTID
147 static inline int gettid(void)
148 {
149         return syscall(__NR_gettid);
150 }
151 #endif
152
153 #define SPLICE_DEF_SIZE (64*1024)
154
155 #ifndef BLKGETSIZE64
156 #define BLKGETSIZE64    _IOR(0x12,114,size_t)
157 #endif
158
159 #ifndef BLKFLSBUF
160 #define BLKFLSBUF       _IO(0x12,97)
161 #endif
162
163 #ifndef BLKDISCARD
164 #define BLKDISCARD      _IO(0x12,119)
165 #endif
166
167 static inline int blockdev_invalidate_cache(struct fio_file *f)
168 {
169         return ioctl(f->fd, BLKFLSBUF);
170 }
171
172 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
173 {
174         if (!ioctl(f->fd, BLKGETSIZE64, bytes))
175                 return 0;
176
177         return errno;
178 }
179
180 static inline unsigned long long os_phys_mem(void)
181 {
182         long pagesize, pages;
183
184         pagesize = sysconf(_SC_PAGESIZE);
185         pages = sysconf(_SC_PHYS_PAGES);
186         if (pages == -1 || pagesize == -1)
187                 return 0;
188
189         return (unsigned long long) pages * (unsigned long long) pagesize;
190 }
191
192 #ifdef O_NOATIME
193 #define FIO_O_NOATIME   O_NOATIME
194 #else
195 #define FIO_O_NOATIME   0
196 #endif
197
198 #ifdef O_ATOMIC
199 #define OS_O_ATOMIC     O_ATOMIC
200 #else
201 #define OS_O_ATOMIC     040000000
202 #endif
203
204 #ifdef MADV_REMOVE
205 #define FIO_MADV_FREE   MADV_REMOVE
206 #endif
207
208 /* Check for GCC or Clang byte swap intrinsics */
209 #if (__has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) \
210      && __has_builtin(__builtin_bswap64)) || (__GNUC__ > 4 \
211      || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) /* fio_swapN */
212 #define fio_swap16(x)   __builtin_bswap16(x)
213 #define fio_swap32(x)   __builtin_bswap32(x)
214 #define fio_swap64(x)   __builtin_bswap64(x)
215 #else
216 #include <byteswap.h>
217 #define fio_swap16(x)   bswap_16(x)
218 #define fio_swap32(x)   bswap_32(x)
219 #define fio_swap64(x)   bswap_64(x)
220 #endif /* fio_swapN */
221
222 #define CACHE_LINE_FILE \
223         "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"
224
225 static inline int arch_cache_line_size(void)
226 {
227         char size[32];
228         int fd, ret;
229
230         fd = open(CACHE_LINE_FILE, O_RDONLY);
231         if (fd < 0)
232                 return -1;
233
234         ret = read(fd, size, sizeof(size));
235
236         close(fd);
237
238         if (ret <= 0)
239                 return -1;
240         else
241                 return atoi(size);
242 }
243
244 #ifdef __powerpc64__
245 #define FIO_HAVE_CPU_ONLINE_SYSCONF
246 static inline unsigned int cpus_online(void)
247 {
248         return sysconf(_SC_NPROCESSORS_CONF);
249 }
250 #endif
251
252 static inline unsigned long long get_fs_free_size(const char *path)
253 {
254         unsigned long long ret;
255         struct statfs s;
256
257         if (statfs(path, &s) < 0)
258                 return -1ULL;
259
260         ret = s.f_bsize;
261         ret *= (unsigned long long) s.f_bfree;
262         return ret;
263 }
264
265 static inline int os_trim(struct fio_file *f, unsigned long long start,
266                           unsigned long long len)
267 {
268         uint64_t range[2];
269
270         range[0] = start;
271         range[1] = len;
272
273         if (!ioctl(f->fd, BLKDISCARD, range))
274                 return 0;
275
276         return errno;
277 }
278
279 #ifdef CONFIG_SCHED_IDLE
280 static inline int fio_set_sched_idle(void)
281 {
282         struct sched_param p = { .sched_priority = 0, };
283         return sched_setscheduler(gettid(), SCHED_IDLE, &p);
284 }
285 #endif
286
287 #ifndef F_GET_RW_HINT
288 #ifndef F_LINUX_SPECIFIC_BASE
289 #define F_LINUX_SPECIFIC_BASE   1024
290 #endif
291 #define F_GET_RW_HINT           (F_LINUX_SPECIFIC_BASE + 11)
292 #define F_SET_RW_HINT           (F_LINUX_SPECIFIC_BASE + 12)
293 #define F_GET_FILE_RW_HINT      (F_LINUX_SPECIFIC_BASE + 13)
294 #define F_SET_FILE_RW_HINT      (F_LINUX_SPECIFIC_BASE + 14)
295 #endif
296
297 #ifndef RWH_WRITE_LIFE_NONE
298 #define RWH_WRITE_LIFE_NOT_SET  0
299 #define RWH_WRITE_LIFE_NONE     1
300 #define RWH_WRITE_LIFE_SHORT    2
301 #define RWH_WRITE_LIFE_MEDIUM   3
302 #define RWH_WRITE_LIFE_LONG     4
303 #define RWH_WRITE_LIFE_EXTREME  5
304 #endif
305
306 #define FIO_HAVE_WRITE_HINT
307
308 #ifndef RWF_HIPRI
309 #define RWF_HIPRI       0x00000001
310 #endif
311 #ifndef RWF_DSYNC
312 #define RWF_DSYNC       0x00000002
313 #endif
314 #ifndef RWF_SYNC
315 #define RWF_SYNC        0x00000004
316 #endif
317 #ifndef RWF_NOWAIT
318 #define RWF_NOWAIT      0x00000008
319 #endif
320
321 #ifndef RWF_UNCACHED
322 #define RWF_UNCACHED    0x00000040
323 #endif
324
325 #ifndef RWF_WRITE_LIFE_SHIFT
326 #define RWF_WRITE_LIFE_SHIFT            4
327 #define RWF_WRITE_LIFE_SHORT            (1 << RWF_WRITE_LIFE_SHIFT)
328 #define RWF_WRITE_LIFE_MEDIUM           (2 << RWF_WRITE_LIFE_SHIFT)
329 #define RWF_WRITE_LIFE_LONG             (3 << RWF_WRITE_LIFE_SHIFT)
330 #define RWF_WRITE_LIFE_EXTREME          (4 << RWF_WRITE_LIFE_SHIFT)
331 #endif
332
333 #ifndef CONFIG_PWRITEV2
334 #ifdef __NR_preadv2
335 static inline void make_pos_h_l(unsigned long *pos_h, unsigned long *pos_l,
336                                 off_t offset)
337 {
338 #if BITS_PER_LONG == 64
339         *pos_l = offset;
340         *pos_h = 0;
341 #else
342         *pos_l = offset & 0xffffffff;
343         *pos_h = ((uint64_t) offset) >> 32;
344 #endif
345 }
346 static inline ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt,
347                               off_t offset, unsigned int flags)
348 {
349         unsigned long pos_l, pos_h;
350
351         make_pos_h_l(&pos_h, &pos_l, offset);
352         return syscall(__NR_preadv2, fd, iov, iovcnt, pos_l, pos_h, flags);
353 }
354 static inline ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt,
355                                off_t offset, unsigned int flags)
356 {
357         unsigned long pos_l, pos_h;
358
359         make_pos_h_l(&pos_h, &pos_l, offset);
360         return syscall(__NR_pwritev2, fd, iov, iovcnt, pos_l, pos_h, flags);
361 }
362 #else
363 static inline ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt,
364                               off_t offset, unsigned int flags)
365 {
366         errno = ENOSYS;
367         return -1;
368 }
369 static inline ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt,
370                                off_t offset, unsigned int flags)
371 {
372         errno = ENOSYS;
373         return -1;
374 }
375 #endif /* __NR_preadv2 */
376 #endif /* CONFIG_PWRITEV2 */
377
378 static inline int shm_attach_to_open_removed(void)
379 {
380         return 1;
381 }
382
383 #ifdef CONFIG_LINUX_FALLOCATE
384 #define FIO_HAVE_NATIVE_FALLOCATE
385 static inline bool fio_fallocate(struct fio_file *f, uint64_t offset,
386                                  uint64_t len)
387 {
388         int ret;
389         ret = fallocate(f->fd, 0, offset, len);
390         if (ret == 0)
391                 return true;
392
393         /* Work around buggy old glibc versions... */
394         if (ret > 0)
395                 errno = ret;
396
397         return false;
398 }
399 #endif
400
401 #define FIO_HAVE_CPU_HAS
402 static inline bool os_cpu_has(cpu_features feature)
403 {
404         bool have_feature;
405         unsigned long fio_unused hwcap;
406
407         switch (feature) {
408 #ifdef ARCH_HAVE_CRC_CRYPTO
409         case CPU_ARM64_CRC32C:
410                 hwcap = getauxval(AT_HWCAP);
411                 have_feature = (hwcap & (HWCAP_PMULL | HWCAP_CRC32)) ==
412                                (HWCAP_PMULL | HWCAP_CRC32);
413                 break;
414 #endif
415         default:
416                 have_feature = false;
417         }
418
419         return have_feature;
420 }
421
422 #endif