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