Seperate disk util code out of fio.c
[fio.git] / os-linux.h
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 <unistd.h>
8 #include <fcntl.h>
9 #include <linux/unistd.h>
10 #include <linux/raw.h>
11 #include <linux/major.h>
12
13 #define FIO_HAVE_LIBAIO
14 #define FIO_HAVE_POSIXAIO
15 #define FIO_HAVE_FADVISE
16 #define FIO_HAVE_CPU_AFFINITY
17 #define FIO_HAVE_DISK_UTIL
18 #define FIO_HAVE_SGIO
19 #define FIO_HAVE_IOPRIO
20 #define FIO_HAVE_SPLICE
21 #define FIO_HAVE_IOSCHED_SWITCH
22 #define FIO_HAVE_ODIRECT
23 #define FIO_HAVE_HUGETLB
24 #define FIO_HAVE_RAWBIND
25
26 #define OS_MAP_ANON             (MAP_ANONYMOUS)
27
28 typedef cpu_set_t os_cpu_mask_t;
29 typedef struct drand48_data os_random_state_t;
30
31 /*
32  * we want fadvise64 really, but it's so tangled... later
33  */
34 #define fadvise(fd, off, len, advice)   \
35         posix_fadvise((fd), (off_t)(off), (len), (advice))
36
37 #define fio_setaffinity(td)             \
38         sched_setaffinity((td)->pid, sizeof((td)->o.cpumask), &(td)->o.cpumask)
39 #define fio_getaffinity(pid, ptr)       \
40         sched_getaffinity((pid), sizeof(cpu_set_t), (ptr))
41
42 static inline int ioprio_set(int which, int who, int ioprio)
43 {
44         return syscall(__NR_ioprio_set, which, who, ioprio);
45 }
46
47 /*
48  * Just check for SPLICE_F_MOVE, if that isn't there, assume the others
49  * aren't either.
50  */
51 #ifndef SPLICE_F_MOVE
52 #define SPLICE_F_MOVE   (0x01)  /* move pages instead of copying */
53 #define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
54                                  /* we may still block on the fd we splice */
55                                  /* from/to, of course */
56 #define SPLICE_F_MORE   (0x04)  /* expect more data */
57 #define SPLICE_F_GIFT   (0x08)  /* pages passed in are a gift */
58
59 static inline int splice(int fdin, loff_t *off_in, int fdout, loff_t *off_out,
60                          size_t len, unsigned long flags)
61 {
62         return syscall(__NR_sys_splice, fdin, off_in, fdout, off_out, len, flags);
63 }
64
65 static inline int tee(int fdin, int fdout, size_t len, unsigned int flags)
66 {
67         return syscall(__NR_sys_tee, fdin, fdout, len, flags);
68 }
69
70 static inline int vmsplice(int fd, const struct iovec *iov,
71                            unsigned long nr_segs, unsigned int flags)
72 {
73         return syscall(__NR_sys_vmsplice, fd, iov, nr_segs, flags);
74 }
75 #endif
76
77 #define SPLICE_DEF_SIZE (64*1024)
78
79 #ifdef FIO_HAVE_SYSLET
80
81 struct syslet_uatom;
82 struct async_head_user;
83
84 /*
85  * syslet stuff
86  */
87 static inline struct syslet_uatom *
88 async_exec(struct syslet_uatom *atom, struct async_head_user *ahu)
89 {
90         return (void *) syscall(__NR_async_exec, atom, ahu);
91 }
92
93 static inline long
94 async_wait(unsigned long min_wait_events, unsigned long user_ring_idx,
95            struct async_head_user *ahu)
96 {
97         return syscall(__NR_async_wait, min_wait_events,
98                         user_ring_idx, ahu);
99 }
100
101 static inline long async_thread(void *event, struct async_head_user *ahu)
102 {
103         return syscall(__NR_async_thread, event, ahu);
104 }
105
106 static inline long umem_add(unsigned long *uptr, unsigned long inc)
107 {
108         return syscall(__NR_umem_add, uptr, inc);
109 }
110 #endif /* FIO_HAVE_SYSLET */
111
112 enum {
113         IOPRIO_WHO_PROCESS = 1,
114         IOPRIO_WHO_PGRP,
115         IOPRIO_WHO_USER,
116 };
117
118 #define IOPRIO_CLASS_SHIFT      13
119
120 #ifndef BLKGETSIZE64
121 #define BLKGETSIZE64    _IOR(0x12,114,size_t)
122 #endif
123
124 #ifndef BLKFLSBUF
125 #define BLKFLSBUF       _IO(0x12,97)
126 #endif
127
128 static inline int blockdev_invalidate_cache(int fd)
129 {
130         return ioctl(fd, BLKFLSBUF);
131 }
132
133 static inline int blockdev_size(int fd, unsigned long long *bytes)
134 {
135         if (!ioctl(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 double os_random_double(os_random_state_t *rs)
167 {
168         double val;
169
170         drand48_r(rs, &val);
171         return val;
172 }
173
174 static inline void fio_lookup_raw(dev_t dev, int *majdev, int *mindev)
175 {
176         struct raw_config_request rq;
177         int fd;
178
179         if (major(dev) != RAW_MAJOR)
180                 return;
181
182         /*
183          * we should be able to find /dev/rawctl or /dev/raw/rawctl
184          */
185         fd = open("/dev/rawctl", O_RDONLY);
186         if (fd < 0) {
187                 fd = open("/dev/raw/rawctl", O_RDONLY);
188                 if (fd < 0)
189                         return;
190         }
191
192         rq.raw_minor = minor(dev);
193         if (ioctl(fd, RAW_GETBIND, &rq) < 0) {
194                 close(fd);
195                 return;
196         }
197
198         close(fd);
199         *majdev = rq.block_major;
200         *mindev = rq.block_minor;
201 }
202
203 #endif