1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
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 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * hugetlb.c
23 *
24 * DESCRIPTION
25 * common routines for the hugepage tests.
26 *
27 * The library contains the following routines:
28 *
29 * getipckey()
30 * getuserid()
31 * rm_shm()
32 */
33
34 #define TST_NO_DEFAULT_MAIN
35 #include <sys/types.h>
36 #include <sys/ipc.h>
37 #include <sys/shm.h>
38 #include <sys/timeb.h>
39 #include <pwd.h>
40 #include "hugetlb.h"
41
42 static long orig_hugepages = -1;
43
save_nr_hugepages(void)44 long save_nr_hugepages(void)
45 {
46 check_hugepage();
47
48 orig_hugepages = get_sys_tune("nr_hugepages");
49
50 return orig_hugepages;
51 }
52
restore_nr_hugepages(void)53 void restore_nr_hugepages(void)
54 {
55 if (orig_hugepages != -1)
56 set_sys_tune("nr_hugepages", orig_hugepages, 0);
57 }
58
limit_hugepages(long * hpages)59 void limit_hugepages(long *hpages)
60 {
61 long mem_avail, max_hpages;
62
63 if (FILE_LINES_SCANF("/proc/meminfo",
64 "MemAvailable: %ld", &mem_avail)) {
65 /*
66 * Dropping caches and using "MemFree:" on kernel
67 * that doesn't have "MemAvailable:" in Meminfo
68 */
69 tst_res(TINFO, "MemAvailable: not found in /proc/meminfo");
70
71 SAFE_FILE_PRINTF("/proc/sys/vm/drop_caches", "3");
72 mem_avail = SAFE_READ_MEMINFO("MemFree:");
73 }
74
75 max_hpages = mem_avail / SAFE_READ_MEMINFO("Hugepagesize:");
76
77 if (*hpages > max_hpages) {
78 tst_res(TINFO, "Requested number of hugepages too large, "
79 "limiting to 80%% of the max hugepage count %ld",
80 max_hpages);
81 *hpages = max_hpages * 0.8;
82 }
83 }
84
85 /*
86 * getipckey() - generates and returns a message key used by the "get"
87 * calls to create an IPC resource.
88 */
getipckey(void)89 int getipckey(void)
90 {
91 const char a = 'a';
92 int ascii_a = (int)a;
93 char *curdir = NULL;
94 size_t size = 0;
95 key_t ipc_key;
96 struct timeb time_info;
97
98 curdir = getcwd(curdir, size);
99 if (curdir == NULL)
100 tst_brk(TBROK | TERRNO, "getcwd(curdir)");
101
102 /*
103 * Get a Sys V IPC key
104 *
105 * ftok() requires a character as a second argument. This is
106 * refered to as a "project identifier" in the man page. In
107 * order to maximize the chance of getting a unique key, the
108 * project identifier is a "random character" produced by
109 * generating a random number between 0 and 25 and then adding
110 * that to the ascii value of 'a'. The "seed" for the random
111 * number is the millisecond value that is set in the timeb
112 * structure after calling ftime().
113 */
114 ftime(&time_info);
115 srandom((unsigned int)time_info.millitm);
116
117 ipc_key = ftok(curdir, ascii_a + random() % 26);
118 if (ipc_key == -1)
119 tst_brk(TBROK | TERRNO, __func__);
120
121 return ipc_key;
122 }
123
124 /*
125 * getuserid() - return the integer value for the "user" id
126 */
getuserid(char * user)127 int getuserid(char *user)
128 {
129 struct passwd *ent;
130
131 ent = getpwnam(user);
132 if (ent == NULL)
133 tst_brk(TBROK | TERRNO, "getpwnam");
134
135 return ent->pw_uid;
136 }
137
138 /*
139 * rm_shm() - removes a shared memory segment.
140 */
rm_shm(int shm_id)141 void rm_shm(int shm_id)
142 {
143 if (shm_id == -1)
144 return;
145
146 /*
147 * check for # of attaches ?
148 */
149 if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
150 tst_res(TINFO, "WARNING: shared memory deletion failed.");
151 tst_res(TINFO, "This could lead to IPC resource problems.");
152 tst_res(TINFO, "id = %d", shm_id);
153 }
154 }
155