delete_module03.c revision 5f30b5d78d6337a249724fb89888db68f23e711b
1/*
2 * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * You should have received a copy of the GNU General Public License along
13 * with this program; if not, write the Free Software Foundation, Inc., 59
14 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
15 *
16 */
17/**********************************************************
18 *
19 *    TEST IDENTIFIER   : delete_module03
20 *
21 *    EXECUTED BY       : root / superuser
22 *
23 *    TEST TITLE        : Checking error conditions for delete_module(2)
24 *
25 *    TEST CASE TOTAL   : 1
26 *
27 *    AUTHOR            : Madhu T L <madhu.tarikere@wipro.com>
28 *
29 *    SIGNALS
30 *      Uses SIGUSR1 to pause before test if option set.
31 *      (See the parse_opts(3) man page).
32 *
33 *    DESCRIPTION
34 *      Verify that, delete_module(2) returns -1 and sets errno to EBUSY, if
35 *	tried to remove a module in-use.
36 *
37 *      Setup:
38 *        Setup signal handling.
39 *        Test caller is super user
40 *        Set expected errnos for logging
41 *        Pause for SIGUSR1 if option specified.
42 *	  Insert loadable modules
43 *
44 *      Test:
45 *       Loop if the proper options are given.
46 *        Execute system call
47 *        Check return code and error number, if matching,
48 *                   Issue PASS message
49 *        Otherwise,
50 *                   Issue FAIL message
51 *
52 *      Cleanup:
53 *        Print errno log and/or timing stats if options given
54 *
55 * USAGE:  <for command-line>
56 *  delete_module03 [-c n] [-e] [-f] [-h] [-i n] [-I x] [-p] [-P x] [-t]
57 *		where,  -c n : Run n copies concurrently. (no effect)
58 *			-e   : Turn on errno logging.
59 *			-f   : Turn off functional testing
60 *			-h   : Show help screen
61 *			-i n : Execute test n times.
62 *			-I x : Execute test for x seconds.
63 *			-p   : Pause for SIGUSR1 before starting
64 *			-P x : Pause for x seconds between iterations.
65 *			-t   : Turn on syscall timing.
66 *
67 * RESTRICTIONS
68 *	-c option has no effect for this testcase, even if used allows only
69 *	one instance to run at a time.
70 *
71 * CHANGELOG
72 *
73 *  11/22/02 - Added "--force" to insmod options and redirected output to /dev/null.
74 *             This was done to allow kernel mismatches, b/c it doesn't matter in
75 *             this case.
76 *           Robbie Williamson <robbiew@us.ibm.com>
77 *
78 ****************************************************************/
79
80#include <errno.h>
81#include <pwd.h>
82#include <asm/atomic.h>
83#include <linux/module.h>
84#include "test.h"
85#include "usctest.h"
86
87extern int Tst_count;
88
89#define DUMMY_MOD	"dummy_del_mod"
90#define DUMMY_MOD_DEP	"dummy_del_mod_dep"
91#define EXP_RET_VAL	-1
92#define EXP_ERRNO	EBUSY
93
94char *TCID = "delete_module03";
95static int exp_enos[] = {EBUSY, 0};
96int TST_TOTAL = 1;
97
98static int setup(void);
99static void cleanup(void);
100
101int
102main(int argc, char **argv)
103{
104	int lc;				/* loop counter */
105	char *msg;			/* message returned from parse_opts */
106
107	/* parse standard options */
108	if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) !=
109	    (char *)NULL) {
110		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
111	}
112
113	if(STD_COPIES != 1) {
114		tst_resm(TINFO, "-c option has no effect for this testcase - "
115			"doesn't allow running more than one instance "
116			"at a time");
117		STD_COPIES = 1;
118	}
119	tst_tmpdir();
120	if(setup() != 0) {
121		return 1;
122	}
123
124	/* check looping state if -i option is given */
125	for (lc = 0; TEST_LOOPING(lc); lc++) {
126		/* reset Tst_count in case we are looping */
127		Tst_count = 0;
128
129		/* Test the system call */
130		TEST(delete_module(DUMMY_MOD));
131
132		TEST_ERROR_LOG(TEST_ERRNO);
133		if ( (TEST_RETURN == (int) EXP_RET_VAL ) &&
134				(TEST_ERRNO == EXP_ERRNO) ) {
135			tst_resm(TPASS, "Expected failure for module in-use, "
136				"errno: %d", TEST_ERRNO);
137		} else {
138			tst_resm(TFAIL, "Unexpected results for module in-use; "
139				"returned %d (expected %d), errno %d "
140				"(expected %d)", TEST_RETURN, EXP_RET_VAL,
141				TEST_ERRNO, EXP_ERRNO);
142		}
143	}
144	cleanup();
145
146	/*NOTREACHED*/
147	return 0;
148}
149
150/*
151 * setup()
152 *	performs all ONE TIME setup for this test
153 */
154int
155setup(void)
156{
157	char cmd[50];
158
159	/* capture signals */
160	tst_sig(FORK, DEF_HANDLER, cleanup);
161
162	/* Check whether it is root  */
163	if (geteuid() != 0) {
164		tst_resm(TBROK, "Must be root for this test!");
165		return 1;
166	}
167
168	if (tst_kvercmp(2,5,48) >= 0)
169		tst_brkm(TCONF, tst_exit, "This test will not work on "
170				"kernels after 2.5.48");
171
172	/* set the expected errnos... */
173	TEST_EXP_ENOS(exp_enos);
174
175	if( sprintf(cmd, "cp `which %s.o` ./", DUMMY_MOD) == -1) {
176                tst_resm(TBROK, "sprintf failed");
177                return 1;
178        }
179        if(system(cmd) != 0 ) {
180                tst_resm(TBROK, "Failed to copy %s module", DUMMY_MOD);
181                return 1;
182        }
183
184	/* Load first kernel module */
185	if( sprintf(cmd, "insmod --force %s.o >/dev/null 2>&1", DUMMY_MOD) <= 0) {
186		tst_resm(TBROK, "sprintf failed");
187		return 1;
188	}
189	if(system(cmd) != 0 ) {
190		tst_resm(TBROK, "Failed to load %s module", DUMMY_MOD);
191		return 1;
192	}
193
194	if( sprintf(cmd, "cp `which %s.o` ./", DUMMY_MOD_DEP) == -1) {
195                tst_resm(TBROK, "sprintf failed");
196                return 1;
197        }
198        if(system(cmd) != 0 ) {
199                tst_resm(TBROK, "Failed to copy %s module", DUMMY_MOD_DEP);
200                return 1;
201        }
202	/* Load dependent kernel module */
203	if( sprintf(cmd, "insmod --force %s.o >/dev/null 2>&1", DUMMY_MOD_DEP) <= 0) {
204		tst_resm(TBROK, "sprintf failed");
205		goto END;
206	}
207	if(system(cmd) != 0 ) {
208		tst_resm(TBROK, "Failed to load %s module", DUMMY_MOD_DEP);
209		goto END;
210	}
211
212	/* Pause if that option was specified
213	 * TEST_PAUSE contains the code to fork the test with the -c option.
214	 */
215	TEST_PAUSE;
216	return 0;
217
218END:
219
220	if(system("rmmod "DUMMY_MOD) != 0) {
221		tst_resm(TBROK, "Failed to unload %s module", DUMMY_MOD);
222	}
223	return 1;
224}
225
226/*
227 * cleanup()
228 *	performs all ONE TIME cleanup for this test at
229 *	completion or premature exit
230 */
231void
232cleanup(void)
233{
234	/* Unload dependent kernel module */
235	if(system("rmmod "DUMMY_MOD_DEP) != 0) {
236		tst_resm(TBROK, "Failed to unload %s module",
237			DUMMY_MOD_DEP);
238	}
239	/* Unload first kernel module */
240	if(system("rmmod "DUMMY_MOD) != 0) {
241		tst_resm(TBROK, "Failed to unload %s module",
242			DUMMY_MOD);
243	}
244	/*
245	 * print timing stats if that option was specified.
246	 * print errno log if that option was specified.
247	 */
248	TEST_CLEANUP;
249	tst_rmdir();
250	/* exit with return code appropriate for results */
251	tst_exit();
252	/*NOTREACHED*/
253}
254