xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/mkdir/mkdir09.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) International Business Machines Corp., 2001
4  * Copyright (c) Linux Test Project, 2022
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Create multiple processes which create subdirectories in the
11  * same directory multiple times within test time.
12  */
13 
14 #include <stdio.h>
15 #include <sys/param.h>
16 #include "tst_test.h"
17 #include "tst_safe_pthread.h"
18 
19 #define MNTPOINT	"mntpoint"
20 #define MODE_RWX	07770
21 #define DIR_NAME	MNTPOINT "/X.%d"
22 #define DIR_NAME_GROUP	MNTPOINT "/X.%d.%d"
23 #define NCHILD		3
24 
25 static int child_groups = 2;
26 static int test_time = 1;
27 static int nfiles = 10;
28 static volatile int done;
29 
30 /*
31  * Routine which attempts to create directories in the test
32  * directory that already exist.
33  */
test1(int child_num)34 static void test1(int child_num)
35 {
36 	int j;
37 	char tmpdir[MAXPATHLEN];
38 
39 	while (!done) {
40 		for (j = 0; j < nfiles; j += NCHILD) {
41 			sprintf(tmpdir, DIR_NAME, j);
42 			TST_EXP_FAIL_SILENT(mkdir(tmpdir, MODE_RWX), EEXIST);
43 			if (!TST_PASS)
44 				break;
45 		}
46 	}
47 	tst_res(TPASS, "[%d] create dirs that already exist", child_num);
48 }
49 
50 /*
51  * Child routine which attempts to remove directories from the
52  * test directory which do not exist.
53  */
test2(int child_num)54 static void test2(int child_num)
55 {
56 	int j;
57 	char tmpdir[MAXPATHLEN];
58 
59 	while (!done) {
60 		for (j = 1; j < nfiles; j += NCHILD) {
61 			sprintf(tmpdir, DIR_NAME, j);
62 			TST_EXP_FAIL_SILENT(rmdir(tmpdir), ENOENT);
63 			if (!TST_PASS)
64 				break;
65 		}
66 	}
67 	tst_res(TPASS, "[%d] remove dirs that do not exist", child_num);
68 }
69 
70 /*
71  * Child routine which creates and deletes directories in the
72  * test directory.
73  */
test3(int child_num)74 static void test3(int child_num)
75 {
76 	int j;
77 	char tmpdir[MAXPATHLEN];
78 
79 	while (!done) {
80 		for (j = 2; j < nfiles; j += NCHILD) {
81 			sprintf(tmpdir, DIR_NAME_GROUP, j, child_num / NCHILD);
82 			TST_EXP_PASS_SILENT(mkdir(tmpdir, MODE_RWX));
83 			if (!TST_PASS)
84 				break;
85 		}
86 		for (j = 2; j < nfiles; j += NCHILD) {
87 			sprintf(tmpdir, DIR_NAME_GROUP, j, child_num / NCHILD);
88 			TST_EXP_PASS_SILENT(rmdir(tmpdir));
89 			if (!TST_PASS)
90 				break;
91 		}
92 	}
93 	tst_res(TPASS, "[%d] create/remove dirs", child_num);
94 }
95 
child_thread_func(void * arg)96 static void *child_thread_func(void *arg)
97 {
98 	void (*tests[NCHILD])(int) = { test1, test2, test3 };
99 	int child_num = (long)arg;
100 
101 	tests[child_num % NCHILD](child_num);
102 
103 	/* if any thread failed, make other finish as well */
104 	done = 1;
105 
106 	return NULL;
107 }
108 
verify_mkdir(void)109 static void verify_mkdir(void)
110 {
111 	pthread_t child_thread[NCHILD * child_groups];
112 	long i;
113 
114 	done = 0;
115 	for (i = 0; i < child_groups * NCHILD; i++) {
116 		SAFE_PTHREAD_CREATE(&child_thread[i], NULL,
117 			child_thread_func, (void *)i);
118 	}
119 
120 	sleep(test_time);
121 	done = 1;
122 
123 	for (i = 0; i < child_groups * NCHILD; i++)
124 		SAFE_PTHREAD_JOIN(child_thread[i], NULL);
125 }
126 
setup(void)127 static void setup(void)
128 {
129 	int j;
130 	char tmpdir[MAXPATHLEN];
131 
132 	for (j = 0; j < nfiles; j += NCHILD) {
133 		sprintf(tmpdir, DIR_NAME, j);
134 		SAFE_MKDIR(tmpdir, MODE_RWX);
135 	}
136 }
137 
138 static struct tst_test test = {
139 	.test_all = verify_mkdir,
140 	.needs_root = 1,
141 	.setup = setup,
142 	.mount_device = 1,
143 	.mntpoint = MNTPOINT,
144 	.all_filesystems = 1,
145 };
146