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 set_sys_tune("nr_hugepages", hugepages, 1);
93 hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
94
95 shm_size = hpage_size * hugepages / 2;
96 update_shm_size(&shm_size);
97
98 shmkey = getipckey();
99 shmkey2 = shmkey + 1;
100 shm_id_1 = shmget(shmkey, shm_size,
101 SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW);
102 if (shm_id_1 == -1)
103 tst_brk(TBROK | TERRNO, "shmget #setup");
104 }
105
cleanup(void)106 void cleanup(void)
107 {
108 rm_shm(shm_id_1);
109 restore_nr_hugepages();
110 }
111
112 static struct tst_test test = {
113 .needs_root = 1,
114 .options = options,
115 .setup = setup,
116 .cleanup = cleanup,
117 .test = test_hugeshmget,
118 .tcnt = ARRAY_SIZE(tcases),
119 };
120