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