xref: /aosp_15_r20/external/ltp/testcases/kernel/device-drivers/tbio/tbio_user/tbio.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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