1 /*
2  * Copyright (c) International Business Machines  Corp., 2004
3  * Copyright (c) Linux Test Project, 2004-2017
4  *
5  * This program is free software;  you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  * the GNU General Public License for more details.
14  */
15 
16 /*
17  * DESCRIPTION
18  *	hugeshmget02 - check for ENOENT, EEXIST and EINVAL errors
19  *
20  * HISTORY
21  *	03/2001 - Written by Wayne Boyer
22  *	04/2004 - Updated by Robbie Williamson
23  */
24 #include <limits.h>
25 #include "hugetlb.h"
26 
27 #include "hugetlb.h"
28 
29 static size_t shm_size;
30 static int shm_id_1 = -1;
31 static int shm_nonexistent_key = -1;
32 static key_t shmkey2;
33 
34 static long hugepages = 128;
35 static struct tst_option options[] = {
36 	{"s:", &nr_opt, "-s   num  Set the number of the been allocated hugepages"},
37 	{NULL, NULL, NULL}
38 };
39 
40 static struct tcase {
41 	int *skey;
42 	int size_coe;
43 	int flags;
44 	int error;
45 } tcases[] = {
46 	/* EINVAL - size is 0 */
47 	{&shmkey2, 0, SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW, EINVAL},
48 	/* EINVAL - size is larger than created segment */
49 	{&shmkey, 2, SHM_HUGETLB | SHM_RW, EINVAL},
50 	/* EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given */
51 	{&shmkey, 1, SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW, EEXIST},
52 	/* ENOENT - no segment exists for the key and IPC_CREAT is not given */
53 	/* use shm_nonexistend_key (-1) as the key */
54 	{&shm_nonexistent_key, 1, SHM_HUGETLB | SHM_RW, ENOENT}
55 };
56 
test_hugeshmget(unsigned int i)57 static void test_hugeshmget(unsigned int i)
58 {
59 	int shm_id_2 = -1;
60 
61 	if (*tcases[i].skey == -1) {
62 		shm_id_2 = shmget(*(tcases[i].skey), 0, 0);
63 		if (shm_id_2 != -1)
64 			shmctl(shm_id_2, IPC_RMID, NULL);
65 	}
66 
67 	TEST(shmget(*(tcases[i].skey), tcases[i].size_coe * shm_size,
68 					tcases[i].flags));
69 	if (TST_RET != -1) {
70 		tst_res(TFAIL, "shmget succeeded unexpectedly");
71 		return;
72 	}
73 
74 	if (TST_ERR != tcases[i].error) {
75 		tst_res(TFAIL | TTERRNO,
76 			"shmget failed unexpectedly, expected %s",
77 			tst_strerrno(tcases[i].error));
78 		return;
79 	}
80 
81 	tst_res(TPASS | TTERRNO, "shmget failed as expected");
82 }
83 
setup(void)84 void setup(void)
85 {
86 	long hpage_size;
87 
88 	save_nr_hugepages();
89 	if (nr_opt)
90 		hugepages = SAFE_STRTOL(nr_opt, 0, LONG_MAX);
91 
92 	limit_hugepages(&hugepages);
93 	set_sys_tune("nr_hugepages", hugepages, 1);
94 	hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
95 
96 	shm_size = hpage_size * hugepages / 2;
97 	update_shm_size(&shm_size);
98 
99 	shmkey = getipckey();
100 	shmkey2 = shmkey + 1;
101 	shm_id_1 = shmget(shmkey, shm_size,
102 			  SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW);
103 	if (shm_id_1 == -1)
104 		tst_brk(TBROK | TERRNO, "shmget #setup");
105 }
106 
cleanup(void)107 void cleanup(void)
108 {
109 	rm_shm(shm_id_1);
110 	restore_nr_hugepages();
111 }
112 
113 static struct tst_test test = {
114 	.needs_root = 1,
115 	.options = options,
116 	.setup = setup,
117 	.cleanup = cleanup,
118 	.test = test_hugeshmget,
119 	.tcnt = ARRAY_SIZE(tcases),
120 };
121