1
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <string.h>
6#include <ctype.h>
7#include <errno.h>
8#include <math.h>
9#include <time.h>
10#include <ftw.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <sys/ioctl.h>
15#include <linux/kd.h>
16#include <linux/errno.h>
17
18#include "Ltpfs.h"
19
20#define M_2PI (M_PI*2)
21#define MAXN 4096
22#define MAXFSIZE 1024 * 192
23#define FILE_CREATE_COUNT 256
24#define FAIL 0
25#define SUCCESS 1
26#define MAXNUM   5000
27#define BUFFSIZE 8192
28#define AVEFSIZE (MAXFSIZE/2)
29#define POOLDISKSPACE (AVEFSIZE*128)
30#define MAXERROR  1024
31#define FILES_ONLY 0x01
32#define ALL        0x00
33
34// Globals
35
36char wbuf[MAXFSIZE];
37int startc = 0;
38int showchar[] = { 124, 47, 45, 92, 124, 47, 45, 92 };
39
40int nullFileHandle;
41int openlog[2] = { 0, 0 };
42
43int cFileCount, dFileCount, errorCount;
44static int disk_space_pool = 0;
45char rootPath[BUFFSIZE];
46
47int LTP_fs_open_block_device(void);
48int do_fs_thump_tests(char *path);
49int do_create_file_test(char *path);
50int makedir(char *dir1);
51int changedir(char *dir);
52int do_random_access_test(int maxNum);
53int do_random_create_delete(int maxNum);
54int create_file(char *filename);
55int delete_file(char *filename);
56int gen_random_file_size(int min, int max);
57int open_read_close(char *fname);
58int create_or_delete(char *fname);
59int do_tree_cleanup(char *path, int flag);
60int cleanup_files(char *file, struct stat *statBuff, int flag);
61int cleanup_dirs(char *file, struct stat *statBuff, int flag);
62
63int ltp_block_dev_handle = 0;	/* handle to LTP Test block device */
64int ltp_fileHandle = 0;
65char *fileBuf;
66
67int main(int argc, char **argv)
68{
69
70	ltpdev_cmd_t cmd = { 0, 0 };
71	int rc, i, tmpHandle;
72	struct stat statBuf;
73
74	printf("[%s] - Running test program\n", argv[0]);
75
76	rc = LTP_fs_open_block_device();
77
78	if (!rc) {
79
80		ltp_block_dev_handle = open(LTP_FS_DEVICE_NAME, O_RDWR);
81
82		if (ltp_block_dev_handle < 0) {
83			printf
84			    ("ERROR: Open of device %s failed %d errno = %d\n",
85			     LTP_FS_DEVICE_NAME, ltp_block_dev_handle, errno);
86		} else {
87			rc = ioctl(ltp_block_dev_handle, LTPAIODEV_CMD, &cmd);
88
89			printf("return from AIO ioctl %d \n", rc);
90
91			rc = ioctl(ltp_block_dev_handle, LTPBIODEV_CMD, &cmd);
92
93			printf("return from BIO ioctl %d \n", rc);
94		}
95
96	} else {
97		printf("ERROR: Create/open block device failed\n");
98	}
99
100	ltp_fileHandle =
101	    open("/tmp/testfile", O_CREAT | O_RDWR | O_SYNC | FASYNC,
102		 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
103
104	if (ltp_fileHandle > 0) {
105
106		tmpHandle = open("/usr/include/ctype.h", O_RDONLY);
107
108		if (tmpHandle > 0) {
109
110			rc = fstat(tmpHandle, &statBuf);
111
112			if (!rc) {
113				fileBuf = malloc(statBuf.st_size);
114
115				if (fileBuf) {
116
117					read(tmpHandle, fileBuf,
118					     statBuf.st_size);
119					close(tmpHandle);
120					write(ltp_fileHandle, fileBuf,
121					      statBuf.st_size);
122
123					for (i = 0; i < 100; i++) {
124						read(ltp_fileHandle, fileBuf,
125						     statBuf.st_size * i);
126						write(ltp_fileHandle, fileBuf,
127						      statBuf.st_size * i);
128					}
129				}
130
131			}
132
133		} else {
134			printf("ERROR: Create/open file failed\n");
135		}
136	}
137
138	printf("*** Starting FileSystem thump tests....****\n");
139	printf("*** Please be patient, this may take a little while... ***\n");
140
141	for (i = 1; i < argc; i++) {
142		printf("Running test %d of %d on FileSystem %s \n", i, argc - 1,
143		       argv[i]);
144		if (strcmp(argv[i], "|") != 0) {
145			strcpy(rootPath, argv[i]);
146			rc = do_fs_thump_tests(argv[i]);
147			if (rc != 0 && rc != ENOSPC) {
148				printf
149				    ("ERROR: Failed on FileSystem %s with errno %d \n",
150				     argv[i], rc);
151			}
152		} else {
153			printf("Test Program complete..\n");
154			break;
155		}
156
157	}
158
159	printf("Test Program complete..\n");
160
161	return 0;
162}
163
164int do_fs_thump_tests(char *path)
165{
166	int rc = 0;
167
168	printf("Changing to directory %s \n", path);
169
170	changedir(path);
171
172	cFileCount = 0;
173	dFileCount = 0;
174
175	rc |= do_create_file_test(path);
176	rc |= do_random_access_test(MAXNUM);
177	rc |= do_tree_cleanup(path, FILES_ONLY);
178	rc |= do_random_create_delete(MAXNUM);
179	rc |= do_tree_cleanup(path, ALL);
180
181	return rc;
182
183}
184
185int do_tree_cleanup(char *path, int flag)
186{
187
188	if (flag == FILES_ONLY) {
189		printf("Cleaning up test files...\n");
190		ftw(path, (void *)cleanup_files, MAXNUM);
191	} else {
192		printf("Cleaning up everything in the test directory...\n");
193		ftw(path, (void *)cleanup_files, MAXNUM);
194		ftw(path, (void *)cleanup_dirs, MAXNUM);
195	}
196
197	return 0;
198}
199
200int cleanup_files(char *file, struct stat *statBuff, int flag)
201{
202	int rc = 0;
203
204	if (flag == FTW_F) {
205		if (unlink(file)) {
206			printf("ERROR:%d removing file %s\n", errno, file);
207		}
208	}
209
210	return rc;
211}
212
213int cleanup_dirs(char *file, struct stat *statBuff, int flag)
214{
215	int rc = 0;
216
217	//printf("%s:Cleaning up directory %s \n", __FUNCTION__, file);
218
219	if (strcmp(rootPath, file) == 0) {
220		return 0;
221	}
222
223	if (flag == FTW_F) {
224		if (unlink(file)) {
225			printf("ERROR:%d removing file %s\n", errno, file);
226		}
227	} else if (flag == FTW_D) {
228		changedir(file);
229		ftw(file, (void *)cleanup_dirs, MAXNUM);
230		rmdir(file);
231
232	} else {
233		printf("No idea what we found here\n");
234	}
235
236	return rc;
237}
238
239int do_create_file_test(char *path)
240{
241	int i = 0;
242	int j = 0;
243	int k = 0;
244	int l = 0;
245	int rc = 0;
246
247	char dir1[MAXN];
248	char dir2[MAXN];
249	char dir3[MAXN];
250	char filename[MAXN];
251
252	time_t t;
253
254	int maxfiles = 0xFFFFFF;
255
256	time(&t);
257
258	srandom((unsigned int)getpid() ^
259		(((unsigned int)t << 16) | (unsigned int)t >> 16));
260
261	printf("Creating files...\n");
262
263	for (i = 0; i < FILE_CREATE_COUNT; i++) {
264
265		sprintf(dir1, "%2.2x", i);
266
267		makedir(dir1);
268
269		changedir(dir1);
270
271		for (j = 0; j < FILE_CREATE_COUNT; j++) {
272
273			sprintf(dir2, "%2.2x", j);
274
275			makedir(dir2);
276
277			changedir(dir2);
278
279			for (k = 0; k < FILE_CREATE_COUNT; k++) {
280
281				sprintf(dir3, "%2.2x", k);
282				makedir(dir3);
283				changedir(dir3);
284
285				for (l = 0; l < FILE_CREATE_COUNT; l++) {
286					sprintf(filename, "%s%s%s%2.2x", dir1,
287						dir2, dir3, l);
288					rc = create_file(filename);
289					if (rc != 0 || maxfiles < dFileCount++) {
290						if (rc != ENOSPC) {
291							printf
292							    ("ERROR: failed error:%d creating all the test files ! \n",
293							     errno);
294							printf
295							    ("ERROR2: rc:%d -- dFileCount:%d \n",
296							     rc, dFileCount);
297						}
298						goto end;
299					}
300				}
301				changedir("../");
302			}
303			changedir("../");
304		}
305		changedir("../");
306	}
307end:
308	fprintf(stderr, "\nTotal create files: %d\n", cFileCount);
309	printf("Done\n");
310	return rc;
311}
312
313int makedir(char *dir1)
314{
315	if (mkdir(dir1, S_IRWXU) < 0) {
316		perror(dir1);
317		return (errno);
318	}
319	return 0;
320}
321
322int changedir(char *dir)
323{
324	if (chdir(dir) < 0) {
325		perror(dir);
326		return (errno);
327	}
328
329	return 0;
330}
331
332int create_file(char *filename)
333{
334	int fileHandle;
335	int randomsize;
336
337	if ((fileHandle = creat(filename, S_IRWXU)) < 0) {
338
339		fprintf(stderr, "\nERROR line %d: Total create files: %d\n",
340			__LINE__, cFileCount);
341		perror(filename);
342		return (errno);
343	}
344
345	if ((randomsize = gen_random_file_size(0, MAXFSIZE)) < 0) {
346		randomsize = MAXFSIZE;
347	}
348	if (write(fileHandle, wbuf, randomsize) < 0) {
349
350		fprintf(stderr, "\nERROR:%d line%d: Total create files: %d\n",
351			errno, __LINE__, cFileCount);
352		close(fileHandle);
353
354		perror(filename);
355		return (errno);
356	}
357
358	cFileCount++;
359	close(fileHandle);
360	return 0;
361}
362
363int delete_file(char *filename)
364{
365	struct stat buf;
366	int st;
367
368	st = stat(filename, &buf);
369
370	if (st < 0) {
371		errorCount++;
372		printf("ERROR line %d: Getting file stats %s \n", __LINE__,
373		       filename);
374		return (-1);
375	}
376
377	disk_space_pool += buf.st_size;
378
379	if (unlink(filename) < 0) {
380		errorCount++;
381		printf("ERROR line %d: Removing file %s \n", __LINE__,
382		       filename);
383		return (-1);
384	}
385
386	dFileCount++;
387	return 0;
388}
389
390int LTP_fs_open_block_device()
391{
392	dev_t devt;
393	struct stat statbuf;
394	int rc;
395
396	if (ltp_block_dev_handle == 0) {
397
398		/* check for the /dev/LTPFSTest subdir, and create if it does not exist.
399		 *
400		 * If devfs is running and mounted on /dev, these checks will all pass,
401		 * so a new node will not be created.
402		 */
403		devt = makedev(LTPMAJOR, 0);
404
405		rc = stat(LTP_FS_DEV_NODE_PATH, &statbuf);
406
407		if (rc) {
408			if (errno == ENOENT) {
409				/* dev node does not exist. */
410				rc = mkdir(LTP_FS_DEV_NODE_PATH,
411					   (S_IFDIR | S_IRWXU | S_IRGRP |
412					    S_IXGRP | S_IROTH | S_IXOTH));
413			} else {
414				printf
415				    ("ERROR: Problem with LTP FS dev directory.  Error code from stat() is %d\n\n",
416				     errno);
417			}
418
419		} else {
420			if (!(statbuf.st_mode & S_IFDIR)) {
421				rc = unlink(LTP_FS_DEV_NODE_PATH);
422				if (!rc) {
423					rc = mkdir(LTP_FS_DEV_NODE_PATH,
424						   (S_IFDIR | S_IRWXU | S_IRGRP
425						    | S_IXGRP | S_IROTH |
426						    S_IXOTH));
427				}
428			}
429		}
430
431		/*
432		 * Check for the /dev/ltp-fs/block_device node, and create if it does not
433		 * exist.
434		 */
435		rc = stat(LTP_FS_DEVICE_NAME, &statbuf);
436		if (rc) {
437			if (errno == ENOENT) {
438				/* dev node does not exist */
439				rc = mknod(LTP_FS_DEVICE_NAME,
440					   (S_IFBLK | S_IRUSR | S_IWUSR |
441					    S_IRGRP | S_IWGRP), devt);
442			} else {
443				printf
444				    ("ERROR:Problem with LTP FS block device node directory.  Error code form stat() is %d\n\n",
445				     errno);
446			}
447
448		} else {
449			/*
450			 * /dev/ltp-fs/block_device exists.  Check to make sure it is for a
451			 * block device and that it has the right major and minor.
452			 */
453			if ((!(statbuf.st_mode & S_IFBLK)) ||
454			    (statbuf.st_rdev != devt)) {
455
456				/* Recreate the dev node. */
457				rc = unlink(LTP_FS_DEVICE_NAME);
458				if (!rc) {
459					rc = mknod(LTP_FS_DEVICE_NAME,
460						   (S_IFBLK | S_IRUSR | S_IWUSR
461						    | S_IRGRP | S_IWGRP), devt);
462				}
463			}
464		}
465
466	}
467
468	return rc;
469}
470
471int gen_random_file_size(int min, int max)
472{
473	double u1, u2, z;
474	int i;
475	int ave;
476	int range;
477	int ZZ;
478	if (min >= max) {
479		return (-1);
480	}
481	range = max - min;
482	ave = range / 2;
483	for (i = 0; i < 10; i++) {
484		u1 = ((double)(random() % 1000000)) / 1000000;
485		u2 = ((double)(random() % 1000000)) / 1000000;
486		z = sqrt(-2.0 * log(u1)) * cos(M_2PI * u2);
487		ZZ = min + (ave + (z * (ave / 4)));
488		if (ZZ >= min && ZZ < max) {
489			return (ZZ);
490		}
491	}
492	return (-1);
493}
494
495int do_random_access_test(int maxNum)
496{
497	int r;
498	char fname[1024];
499	time_t t;
500	int i;
501
502	printf("Running random access test...\n");
503	changedir(rootPath);
504
505	if (maxNum < 1 || maxNum > MAXNUM) {
506		printf("out of size %d\n", maxNum);
507		return 1;
508	}
509
510	time(&t);
511	srandom((unsigned int)getpid() ^
512		(((unsigned int)t << 16) | (unsigned int)t >> 16));
513
514	if ((nullFileHandle = open("/dev/null", O_WRONLY)) < 0) {
515		perror("/dev/null");
516		return (errno);
517	}
518
519	/* 00/00/00/00 */
520	for (i = 0; i < maxNum; i++) {
521
522		r = random() % maxNum;
523
524		sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x",
525			((r >> 16) & 0xFF),
526			((r >> 8) & 0xFF),
527			((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF));
528
529		open_read_close(fname);
530	}
531	close(nullFileHandle);
532	printf("Success:\t%d\nFail:\t%d\n", openlog[SUCCESS], openlog[FAIL]);
533	return 0;
534}
535
536int open_read_close(char *fname)
537{
538	int fileHandle, fileHandle2;
539	char buffer[BUFFSIZE];
540	int c;
541
542	if ((fileHandle = open(fname, O_RDONLY | O_SYNC | O_ASYNC)) < 0) {
543		openlog[FAIL]++;
544		printf("ERROR:opening file %s failed %d \n", fname, errno);
545		return (errno);
546	}
547
548	if ((fileHandle2 = open(fname, O_RDONLY | O_SYNC | O_ASYNC)) < 0) {
549		openlog[FAIL]++;
550		printf("ERROR:2nd opening file %s failed %d \n", fname, errno);
551		return (errno);
552	}
553
554	openlog[SUCCESS]++;
555
556	while ((c = read(fileHandle, buffer, BUFFSIZE)) > 0) {
557		if (write(nullFileHandle, buffer, c) < 0) {
558			perror("/dev/null");
559			printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS],
560			       openlog[FAIL]);
561			close(fileHandle2);
562			close(fileHandle);
563			return (errno);
564		}
565		if ((c = read(fileHandle2, buffer, BUFFSIZE)) > 0) {
566			if (write(nullFileHandle, buffer, c) < 0) {
567				perror("/dev/null");
568				printf("Opened\t %d\nUnopend:\t%d\n",
569				       openlog[SUCCESS], openlog[FAIL]);
570				close(fileHandle2);
571				close(fileHandle);
572				return (errno);
573			}
574		}
575	}
576
577	if (c < 0) {
578		perror(fname);
579		printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS],
580		       openlog[FAIL]);
581		return (errno);
582	}
583
584	close(fileHandle2);
585	close(fileHandle);
586	return 0;
587}
588
589int create_or_delete(char *fname)
590{
591	int r, rc;
592
593	r = (random() & 1);
594
595	/* create */
596	if ((create_file(fname) == 0)) {
597		rc = delete_file(fname);
598	} else {
599		printf("Error: %d creating random file \n", errno);
600	}
601
602	if ((errorCount > dFileCount || errorCount > cFileCount)
603	    && (errorCount > MAXERROR)) {
604		fprintf(stderr, "Too many errors -- Aborting test\n");
605		fprintf(stderr, "Total create files: %d\n", cFileCount);
606		fprintf(stderr, "Total delete files: %d\n", dFileCount);
607		fprintf(stderr, "Total error       : %d\n", errorCount);
608		return (MAXERROR);
609	}
610
611	return 0;
612}
613
614int do_random_create_delete(int maxNum)
615{
616	int r, rc = 0;
617	char fname[1024];
618	time_t t;
619	int i;
620
621	printf("Running random create/delete test...\n");
622
623	if (maxNum < 1 || maxNum > MAXNUM) {
624		printf("MAX out of size %d\n", maxNum);
625		return (maxNum);
626	}
627
628	time(&t);
629	srandom((unsigned int)getpid() ^
630		(((unsigned int)t << 16) | (unsigned int)t >> 16));
631
632	/* 00/00/00/00 */
633	for (i = 0; i < maxNum && rc != MAXERROR; i++) {
634		r = random() % maxNum;
635		sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x",
636			((r >> 16) & 0xFF),
637			((r >> 8) & 0xFF),
638			((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF));
639
640		rc = create_or_delete(fname);
641	}
642
643	fprintf(stderr, "Total create files: %d\n", cFileCount);
644	fprintf(stderr, "Total delete files: %d\n", dFileCount);
645	fprintf(stderr, "Total error       : %d\n", errorCount);
646	return (rc);
647}
648