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 ([email protected])
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/sysmacros.h>
50 #include <sys/types.h>
51 #include <linux/kernel.h>
52 #include <unistd.h>
53 #include <string.h>
54
55 #include "test.h"
56 #include "safe_macros.h"
57 #include "old_module.h"
58
59 #include "../tbio_kernel/tbio.h"
60
61 char *TCID = TBIO_DEVICE_NAME;
62
63 static const char module_name[] = "ltp_tbio.ko";
64 static int module_loaded;
65 static int tbio_fd = -1;
66
cleanup(void)67 void cleanup(void)
68 {
69
70 if (tbio_fd != -1) {
71 close(tbio_fd);
72 tbio_fd = -1;
73 }
74
75 if (module_loaded)
76 tst_module_unload(NULL, module_name);
77
78 if (unlink(DEVICE_NAME) && (errno != ENOENT))
79 tst_brkm(TBROK | TERRNO, NULL, "unlink failed");
80 }
81
82
setup(void)83 void setup(void)
84 {
85 dev_t devt;
86 struct stat st;
87 unsigned int i, valid_node_created;
88
89 tst_require_root();
90
91 tst_module_load(cleanup, module_name, NULL);
92 module_loaded = 1;
93
94 SAFE_FILE_SCANF(cleanup, "/sys/class/block/tbio/dev",
95 "%d:0", &TBIO_MAJOR);
96
97 devt = makedev(TBIO_MAJOR, 0);
98
99 /*
100 * Wait until udev creates the device node.
101 * If the node is not created or invalid, create it manually.
102 */
103 valid_node_created = 0;
104 for (i = 0; i < 50; i++) {
105 if (stat(DEVICE_NAME, &st)) {
106 if (errno != ENOENT)
107 tst_brkm(TBROK | TERRNO, cleanup,
108 "stat() failed");
109 } else {
110 if ((st.st_mode & S_IFBLK) && (st.st_rdev == devt)) {
111 valid_node_created = 1;
112 break;
113 }
114 }
115
116 usleep(100000);
117 }
118
119 if (!valid_node_created) {
120 tst_resm(TINFO,
121 "The device file was not created by udev, "
122 "proceeding with manual creation");
123
124 if (unlink(DEVICE_NAME) && (errno != ENOENT))
125 tst_brkm(TBROK | TERRNO, cleanup, "unlink() failed");
126 if (mknod(DEVICE_NAME, S_IFBLK | S_IRUSR | S_IWUSR |
127 S_IRGRP | S_IWGRP, devt))
128 tst_brkm(TBROK | TERRNO, cleanup, "mknod() failed");
129 }
130
131 tbio_fd = SAFE_OPEN(cleanup, DEVICE_NAME, O_RDWR);
132
133 tst_resm(TINFO, "Device opened successfully ");
134 }
135
136
tbio_to_dev(int fd,int flag)137 int tbio_to_dev(int fd, int flag)
138 {
139 int rc;
140 tbio_interface_t bif;
141
142 memset(&bif, 0, sizeof(tbio_interface_t));
143 rc = posix_memalign(&bif.data, 512, 1024);
144 if (rc) {
145 tst_resm(TINFO, "posix_memalign failed");
146 return -1;
147 }
148
149 strcpy(bif.data, "User space data");
150 bif.data_len = 1024;
151 bif.direction = TBIO_TO_DEV;
152 bif.cmd = SAFE_MALLOC(cleanup, 6);
153 if (bif.cmd == NULL) {
154 tst_resm(TINFO, "malloc cmd space failed");
155 free(bif.data);
156 return -1;
157 }
158 strcpy(bif.cmd, "WRITE");
159 bif.cmd_len = 6;
160
161 rc = ioctl(fd, flag, &bif);
162 if (rc) {
163 free(bif.data);
164 free(bif.cmd);
165 tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV");
166 return rc;
167 }
168
169 free(bif.data);
170 free(bif.cmd);
171
172 return 0;
173
174 }
175
tbio_from_dev(int fd,int flag)176 int tbio_from_dev(int fd, int flag)
177 {
178 int rc;
179 tbio_interface_t bif;
180
181 memset(&bif, 0, sizeof(tbio_interface_t));
182 rc = posix_memalign(&bif.data, 512, 1024);
183 if (rc) {
184 tst_resm(TINFO, "posix_memalign failed");
185 return -1;
186 }
187
188 memset(bif.data, 0, 1024);
189
190 bif.data_len = 1024;
191 bif.direction = TBIO_FROM_DEV;
192 bif.cmd = SAFE_MALLOC(cleanup, 5);
193 if (bif.cmd == NULL) {
194 tst_resm(TINFO, "malloc cmd space failed");
195 free(bif.data);
196 return -1;
197 }
198 strcpy(bif.cmd, "READ");
199 bif.cmd_len = 5;
200
201 rc = ioctl(fd, flag, &bif);
202 if (rc) {
203 free(bif.data);
204 free(bif.cmd);
205 tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV");
206 return rc;
207 }
208
209 if (strcmp(bif.data, "User space data")) {
210 tst_resm(TINFO, "TBIO_FROM_DEV failed");
211 free(bif.data);
212 free(bif.cmd);
213 return -1;
214 }
215
216 free(bif.data);
217 free(bif.cmd);
218
219 return 0;
220
221 }
222
tbio_split_to_dev(int fd,int flag)223 int tbio_split_to_dev(int fd, int flag)
224 {
225 int rc;
226 tbio_interface_t bif;
227
228 memset(&bif, 0, sizeof(tbio_interface_t));
229 rc = posix_memalign(&bif.data, 512, 2048);
230 if (rc) {
231 tst_resm(TINFO, "posix_memalign failed");
232 return -1;
233 }
234
235 strcpy(bif.data, "User space data");
236 bif.data_len = 2048;
237 bif.direction = TBIO_TO_DEV;
238 bif.cmd = SAFE_MALLOC(cleanup, 6);
239 if (bif.cmd == NULL) {
240 tst_resm(TINFO, "malloc cmd space failed");
241 free(bif.data);
242 return -1;
243 }
244 strcpy(bif.cmd, "WRITE");
245 bif.cmd_len = 6;
246
247 rc = ioctl(fd, flag, &bif);
248 if (rc) {
249 free(bif.data);
250 free(bif.cmd);
251 tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV");
252 return rc;
253 }
254
255 free(bif.data);
256 free(bif.cmd);
257
258 return 0;
259
260 }
261
ki_generic(int fd,int flag)262 int ki_generic(int fd, int flag)
263 {
264 tbio_interface_t bif;
265
266 int rc = ioctl(fd, flag, &bif);
267 if (rc)
268 tst_resm(TINFO | TERRNO, "ioctl error");
269
270 return rc;
271 }
272
273
main(void)274 int main(void)
275 {
276 setup();
277
278 if (ki_generic(tbio_fd, LTP_TBIO_ALLOC))
279 tst_resm(TFAIL, "failed on LTP_TBIO_ALLOC test");
280 else
281 tst_resm(TPASS, "success on LTP_TBIO_ALLOC test");
282
283 if (ki_generic(tbio_fd, LTP_TBIO_CLONE))
284 tst_resm(TFAIL, "failed on LTP_TBIO_CLONE test");
285 else
286 tst_resm(TPASS, "success on LTP_TBIO_CLONE test");
287
288 if (ki_generic(tbio_fd, LTP_TBIO_GET_NR_VECS))
289 tst_resm(TFAIL, "failed on LTP_TBIO_GET_NR_VECS test");
290 else
291 tst_resm(TPASS, "success on LTP_TBIO_GET_NR_VECS test");
292
293 if (ki_generic(tbio_fd, LTP_TBIO_ADD_PAGE))
294 tst_resm(TFAIL, "failed on LTP_TBIO_ADD_PAGE test");
295 else
296 tst_resm(TPASS, "success on LTP_TBIO_ADD_PAGE test");
297
298 if (tbio_split_to_dev(tbio_fd, LTP_TBIO_SPLIT))
299 tst_resm(TFAIL, "failed on LTP_TBIO_SPLIT:write to dev");
300 else
301 tst_resm(TPASS, "success on LTP_TBIO_SPLIT:write to dev");
302
303 if (tbio_to_dev(tbio_fd, LTP_TBIO_DO_IO))
304 tst_resm(TFAIL, "failed on LTP_TBIO_DO_IO:write to dev");
305 else
306 tst_resm(TPASS, "success on LTP_TBIO_DO_IO:write to dev");
307
308 if (tbio_from_dev(tbio_fd, LTP_TBIO_DO_IO))
309 tst_resm(TFAIL, "failed on LTP_TBIO_DO_IO:read from dev");
310 else
311 tst_resm(TPASS, "success on LTP_TBIO_DO_IO:read from dev");
312
313 if (ki_generic(tbio_fd, LTP_TBIO_PUT))
314 tst_resm(TFAIL, "failed on LTP_TBIO_PUT test");
315 else
316 tst_resm(TPASS, "success on LTP_TBIO_PUT test");
317
318 cleanup();
319
320 tst_exit();
321 }
322