1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * This is the main of your user space test program,
20 * which will open the correct kernel bioule, find the
21 * file descriptor value and use that value to make
22 * ioctl calls to the system
23 *
24 * Use the ki_generic and other ki_testname functions
25 * to abstract the calls from the main
26 *
27 * FILE : user_tbio.c
28 * USAGE : kernel_space:./load_tbio.sh
29 * user_space :./test_bio
30 *
31 * DESCRIPTION : The bioule will test block i/o layer for kernel 2.5
32 * REQUIREMENTS:
33 * 1) glibc 2.1.91 or above.
34 *
35 * HISTORY :
36 * 11/19/2003 Kai Zhao (ltcd3@cn.ibm.com)
37 *
38 * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage)
39 *
40 */
41
42 #define _GNU_SOURCE
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <sys/stat.h>
46 #include <sys/ioctl.h>
47 #include <fcntl.h>
48 #include <errno.h>
49 #include <sys/types.h>
50 #include <linux/kernel.h>
51 #include <unistd.h>
52 #include <string.h>
53
54 #include "test.h"
55 #include "safe_macros.h"
56 #include "old_module.h"
57
58 #include "../tbio_kernel/tbio.h"
59
60 char *TCID = TBIO_DEVICE_NAME;
61
62 static const char module_name[] = "ltp_tbio.ko";
63 static int module_loaded;
64 static int tbio_fd = -1;
65
cleanup(void)66 void cleanup(void)
67 {
68
69 if (tbio_fd != -1) {
70 close(tbio_fd);
71 tbio_fd = -1;
72 }
73
74 if (module_loaded)
75 tst_module_unload(NULL, module_name);
76
77 if (unlink(DEVICE_NAME) && (errno != ENOENT))
78 tst_brkm(TBROK | TERRNO, NULL, "unlink failed");
79 }
80
81
setup(void)82 void setup(void)
83 {
84 dev_t devt;
85 struct stat st;
86 unsigned int i, valid_node_created;
87
88 tst_require_root();
89
90 if (tst_kvercmp(2, 6, 0) < 0) {
91 tst_brkm(TCONF, NULL,
92 "Test must be run with kernel 2.6 or newer");
93 }
94
95 tst_module_load(cleanup, module_name, NULL);
96 module_loaded = 1;
97
98 SAFE_FILE_SCANF(cleanup, "/sys/class/block/tbio/dev",
99 "%d:0", &TBIO_MAJOR);
100
101 devt = makedev(TBIO_MAJOR, 0);
102
103 /*
104 * Wait until udev creates the device node.
105 * If the node is not created or invalid, create it manually.
106 */
107 valid_node_created = 0;
108 for (i = 0; i < 50; i++) {
109 if (stat(DEVICE_NAME, &st)) {
110 if (errno != ENOENT)
111 tst_brkm(TBROK | TERRNO, cleanup,
112 "stat() failed");
113 } else {
114 if ((st.st_mode & S_IFBLK) && (st.st_rdev == devt)) {
115 valid_node_created = 1;
116 break;
117 }
118 }
119
120 usleep(100000);
121 }
122
123 if (!valid_node_created) {
124 tst_resm(TINFO,
125 "The device file was not created by udev, "
126 "proceeding with manual creation");
127
128 if (unlink(DEVICE_NAME) && (errno != ENOENT))
129 tst_brkm(TBROK | TERRNO, cleanup, "unlink() failed");
130 if (mknod(DEVICE_NAME, S_IFBLK | S_IRUSR | S_IWUSR |
131 S_IRGRP | S_IWGRP, devt))
132 tst_brkm(TBROK | TERRNO, cleanup, "mknod() failed");
133 }
134
135 tbio_fd = open(DEVICE_NAME, O_RDWR);
136 if (tbio_fd < 0) {
137 tst_brkm(TBROK | TERRNO, cleanup, "open of %s failed",
138 DEVICE_NAME);
139 }
140
141 tst_resm(TINFO, "Device opened successfully ");
142 }
143
144
tbio_to_dev(int fd,int flag)145 int tbio_to_dev(int fd, int flag)
146 {
147 int rc;
148 tbio_interface_t bif;
149
150 memset(&bif, 0, sizeof(tbio_interface_t));
151 rc = posix_memalign(&bif.data, 512, 1024);
152 if (rc) {
153 tst_resm(TINFO, "posix_memalign failed");
154 return -1;
155 }
156
157 strcpy(bif.data, "User space data");
158 bif.data_len = 1024;
159 bif.direction = TBIO_TO_DEV;
160 bif.cmd = SAFE_MALLOC(cleanup, 6);
161 if (bif.cmd == NULL) {
162 tst_resm(TINFO, "malloc cmd space failed");
163 free(bif.data);
164 return -1;
165 }
166 strcpy(bif.cmd, "WRITE");
167 bif.cmd_len = 6;
168
169 rc = ioctl(fd, flag, &bif);
170 if (rc) {
171 free(bif.data);
172 free(bif.cmd);
173 tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV");
174 return rc;
175 }
176
177 free(bif.data);
178 free(bif.cmd);
179
180 return 0;
181
182 }
183
tbio_from_dev(int fd,int flag)184 int tbio_from_dev(int fd, int flag)
185 {
186 int rc;
187 tbio_interface_t bif;
188
189 memset(&bif, 0, sizeof(tbio_interface_t));
190 rc = posix_memalign(&bif.data, 512, 1024);
191 if (rc) {
192 tst_resm(TINFO, "posix_memalign failed");
193 return -1;
194 }
195
196 memset(bif.data, 0, 1024);
197
198 bif.data_len = 1024;
199 bif.direction = TBIO_FROM_DEV;
200 bif.cmd = SAFE_MALLOC(cleanup, 5);
201 if (bif.cmd == NULL) {
202 tst_resm(TINFO, "malloc cmd space failed");
203 free(bif.data);
204 return -1;
205 }
206 strcpy(bif.cmd, "READ");
207 bif.cmd_len = 5;
208
209 rc = ioctl(fd, flag, &bif);
210 if (rc) {
211 free(bif.data);
212 free(bif.cmd);
213 tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV");
214 return rc;
215 }
216
217 if (strcmp(bif.data, "User space data")) {
218 tst_resm(TINFO, "TBIO_FROM_DEV failed");
219 free(bif.data);
220 free(bif.cmd);
221 return -1;
222 }
223
224 free(bif.data);
225 free(bif.cmd);
226
227 return 0;
228
229 }
230
tbio_split_to_dev(int fd,int flag)231 int tbio_split_to_dev(int fd, int flag)
232 {
233 int rc;
234 tbio_interface_t bif;
235
236 memset(&bif, 0, sizeof(tbio_interface_t));
237 rc = posix_memalign(&bif.data, 512, 2048);
238 if (rc) {
239 tst_resm(TINFO, "posix_memalign failed");
240 return -1;
241 }
242
243 strcpy(bif.data, "User space data");
244 bif.data_len = 2048;
245 bif.direction = TBIO_TO_DEV;
246 bif.cmd = SAFE_MALLOC(cleanup, 6);
247 if (bif.cmd == NULL) {
248 tst_resm(TINFO, "malloc cmd space failed");
249 free(bif.data);
250 return -1;
251 }
252 strcpy(bif.cmd, "WRITE");
253 bif.cmd_len = 6;
254
255 rc = ioctl(fd, flag, &bif);
256 if (rc) {
257 free(bif.data);
258 free(bif.cmd);
259 tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV");
260 return rc;
261 }
262
263 free(bif.data);
264 free(bif.cmd);
265
266 return 0;
267
268 }
269
ki_generic(int fd,int flag)270 int ki_generic(int fd, int flag)
271 {
272 tbio_interface_t bif;
273
274 int rc = ioctl(fd, flag, &bif);
275 if (rc)
276 tst_resm(TINFO | TERRNO, "ioctl error");
277
278 return rc;
279 }
280
281
main(void)282 int main(void)
283 {
284 setup();
285
286 if (ki_generic(tbio_fd, LTP_TBIO_ALLOC))
287 tst_resm(TFAIL, "failed on LTP_TBIO_ALLOC test");
288 else
289 tst_resm(TPASS, "success on LTP_TBIO_ALLOC test");
290
291 if (ki_generic(tbio_fd, LTP_TBIO_CLONE))
292 tst_resm(TFAIL, "failed on LTP_TBIO_CLONE test");
293 else
294 tst_resm(TPASS, "success on LTP_TBIO_CLONE test");
295
296 if (ki_generic(tbio_fd, LTP_TBIO_GET_NR_VECS))
297 tst_resm(TFAIL, "failed on LTP_TBIO_GET_NR_VECS test");
298 else
299 tst_resm(TPASS, "success on LTP_TBIO_GET_NR_VECS test");
300
301 if (ki_generic(tbio_fd, LTP_TBIO_ADD_PAGE))
302 tst_resm(TFAIL, "failed on LTP_TBIO_ADD_PAGE test");
303 else
304 tst_resm(TPASS, "success on LTP_TBIO_ADD_PAGE test");
305
306 if (tbio_split_to_dev(tbio_fd, LTP_TBIO_SPLIT))
307 tst_resm(TFAIL, "failed on LTP_TBIO_SPLIT:write to dev");
308 else
309 tst_resm(TPASS, "success on LTP_TBIO_SPLIT:write to dev");
310
311 if (tbio_to_dev(tbio_fd, LTP_TBIO_DO_IO))
312 tst_resm(TFAIL, "failed on LTP_TBIO_DO_IO:write to dev");
313 else
314 tst_resm(TPASS, "success on LTP_TBIO_DO_IO:write to dev");
315
316 if (tbio_from_dev(tbio_fd, LTP_TBIO_DO_IO))
317 tst_resm(TFAIL, "failed on LTP_TBIO_DO_IO:read from dev");
318 else
319 tst_resm(TPASS, "success on LTP_TBIO_DO_IO:read from dev");
320
321 if (ki_generic(tbio_fd, LTP_TBIO_PUT))
322 tst_resm(TFAIL, "failed on LTP_TBIO_PUT test");
323 else
324 tst_resm(TPASS, "success on LTP_TBIO_PUT test");
325
326 cleanup();
327
328 tst_exit();
329 }
330