1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/param.h>
28 #include <sys/sysmacros.h>
29 #include <sys/bitmap.h>
30 #include <sys/var.h>
31 #include <sys/thread.h>
32 #include <sys/proc.h>
33 #include <sys/brand.h>
34 #include <sys/zone.h>
35 #include <sys/lx_brand.h>
36 #include <sys/lx_pid.h>
37
38 #define LINUX_PROC_FACTOR 8 /* factor down the hash table by this */
39 static int hash_len = 4; /* desired average hash chain length */
40 static int hash_size; /* no of buckets in the hash table */
41
42 static struct lx_pid **stol_pid_hash;
43 static struct lx_pid **ltos_pid_hash;
44
45 #define LTOS_HASH(pid) ((pid) & (hash_size - 1))
46 #define STOL_HASH(pid, tid) (((pid) + (tid)) & (hash_size - 1))
47
48 static kmutex_t hash_lock;
49
50 static void
51 lx_pid_insert_hash(struct lx_pid *lpidp)
52 {
53 int shash = STOL_HASH(lpidp->s_pid, lpidp->s_tid);
54 int lhash = LTOS_HASH(lpidp->l_pid);
55
56 ASSERT(MUTEX_HELD(&hash_lock));
57
58 lpidp->stol_next = stol_pid_hash[shash];
59 stol_pid_hash[shash] = lpidp;
60
61 lpidp->ltos_next = ltos_pid_hash[lhash];
62 ltos_pid_hash[lhash] = lpidp;
63 }
64
65 static struct lx_pid *
66 lx_pid_remove_hash(pid_t pid, id_t tid)
67 {
68 struct lx_pid **hpp;
69 struct lx_pid *lpidp;
70
71 ASSERT(MUTEX_HELD(&hash_lock));
72
73 hpp = &stol_pid_hash[STOL_HASH(pid, tid)];
74 while (*hpp) {
75 if ((*hpp)->s_pid == pid && (*hpp)->s_tid == tid) {
76 lpidp = *hpp;
77 *hpp = (*hpp)->stol_next;
78 break;
79 }
80 hpp = &(*hpp)->stol_next;
81 }
82
83 /*
84 * when called during error recovery the pid may already
85 * be released
86 */
87 if (lpidp == NULL)
88 return (NULL);
89
90 hpp = <os_pid_hash[LTOS_HASH(lpidp->l_pid)];
91 while (*hpp) {
92 if (*hpp == lpidp) {
93 *hpp = lpidp->ltos_next;
94 break;
95 }
96 hpp = &(*hpp)->ltos_next;
97 }
98
99 return (lpidp);
100 }
101
102 /*
103 * given a solaris pid/tid pair, create a linux pid
104 */
105 int
106 lx_pid_assign(kthread_t *t)
107 {
108 proc_t *p = ttoproc(t);
109 pid_t s_pid = p->p_pid;
110 id_t s_tid = t->t_tid;
111 struct pid *pidp;
112 struct lx_pid *lpidp;
113 lx_lwp_data_t *lwpd = ttolxlwp(t);
114 pid_t newpid;
115
116 if (p->p_lwpcnt > 0) {
117 /*
118 * Allocate a pid for any thread other than the first
119 */
120 if ((newpid = pid_allocate(p, 0, 0)) < 0)
121 return (-1);
122
123 pidp = pid_find(newpid);
124 } else {
125 pidp = NULL;
126 newpid = s_pid;
127 }
128
129 lpidp = kmem_alloc(sizeof (struct lx_pid), KM_SLEEP);
130 lpidp->l_pid = newpid;
131 lpidp->s_pid = s_pid;
132 lpidp->s_tid = s_tid;
133 lpidp->l_pidp = pidp;
134 lpidp->l_start = t->t_start;
135
136 /*
137 * now put the pid into the linux-solaris and solaris-linux
138 * conversion hash tables
139 */
140 mutex_enter(&hash_lock);
141 lx_pid_insert_hash(lpidp);
142 mutex_exit(&hash_lock);
143
144 lwpd->br_pid = newpid;
145
146 return (0);
147 }
148
149 /*
150 * If we are exec()ing the process, this thread's tid is about to be reset
151 * to 1. Make sure the Linux PID bookkeeping reflects that change.
152 */
153 void
154 lx_pid_reassign(kthread_t *t)
155 {
156 proc_t *p = ttoproc(t);
157 struct pid *old_pidp;
158 struct lx_pid *lpidp;
159
160 ASSERT(p->p_lwpcnt == 1);
161
162 mutex_enter(&hash_lock);
163
164 /*
165 * Clean up all the traces of this thread's 'fake' Linux PID.
166 */
167 lpidp = lx_pid_remove_hash(p->p_pid, t->t_tid);
168 ASSERT(lpidp != NULL);
169 old_pidp = lpidp->l_pidp;
170 lpidp->l_pidp = NULL;
171
172 /*
173 * Now register this thread as (pid, 1).
174 */
175 lpidp->l_pid = p->p_pid;
176 lpidp->s_pid = p->p_pid;
177 lpidp->s_tid = 1;
178 lx_pid_insert_hash(lpidp);
179
180 mutex_exit(&hash_lock);
181
182 if (old_pidp)
183 (void) pid_rele(old_pidp);
184 }
185
186 /*
187 * release a solaris pid/tid pair
188 */
189 void
190 lx_pid_rele(pid_t pid, id_t tid)
191 {
192 struct lx_pid *lpidp;
193
194 mutex_enter(&hash_lock);
195 lpidp = lx_pid_remove_hash(pid, tid);
196 mutex_exit(&hash_lock);
197
198 if (lpidp) {
199 if (lpidp->l_pidp)
200 (void) pid_rele(lpidp->l_pidp);
201
202 kmem_free(lpidp, sizeof (*lpidp));
203 }
204 }
205
206 /*
207 * given a linux pid, return the solaris pid/tid pair
208 */
209 int
210 lx_lpid_to_spair(pid_t l_pid, pid_t *s_pid, id_t *s_tid)
211 {
212 struct lx_pid *hp;
213
214 mutex_enter(&hash_lock);
215 for (hp = ltos_pid_hash[LTOS_HASH(l_pid)]; hp; hp = hp->ltos_next) {
216 if (l_pid == hp->l_pid) {
217 if (s_pid)
218 *s_pid = hp->s_pid;
219 if (s_tid)
220 *s_tid = hp->s_tid;
221 break;
222 }
223 }
224 mutex_exit(&hash_lock);
225 if (hp != NULL)
226 return (0);
227
228 /*
229 * We didn't find this pid in our translation table.
230 * But this still could be the pid of a native process
231 * running in the current zone so check for that here.
232 *
233 * Note that prfind() only searches for processes in the current zone.
234 */
235 mutex_enter(&pidlock);
236 if (prfind(l_pid) != NULL) {
237 mutex_exit(&pidlock);
238 if (s_pid)
239 *s_pid = l_pid;
240 if (s_tid)
241 *s_tid = 0;
242 return (0);
243 }
244 mutex_exit(&pidlock);
245
246 return (-1);
247 }
248
249 /*
250 * Given an lwp, return the Linux pid of its parent. If the caller
251 * wants them, we return the Solaris (pid, tid) as well.
252 */
253 pid_t
254 lx_lwp_ppid(klwp_t *lwp, pid_t *ppidp, id_t *ptidp)
255 {
256 lx_lwp_data_t *lwpd = lwptolxlwp(lwp);
257 proc_t *p = lwptoproc(lwp);
258 struct lx_pid *hp;
259 pid_t zoneinit = curproc->p_zone->zone_proc_initpid;
260 pid_t lppid, ppid;
261
262 /*
263 * Be sure not to return a parent pid that should be invisible
264 * within this zone.
265 */
266 ppid = ((p->p_flag & SZONETOP)
267 ? curproc->p_zone->zone_zsched->p_pid : p->p_ppid);
268
269 /*
270 * If the parent process's pid is the zone's init process, force it
271 * to the Linux init pid value of 1.
272 */
273 if (ppid == zoneinit)
274 ppid = 1;
275
276 /*
277 * There are two cases in which the Linux definition of a 'parent'
278 * matches that of Solaris:
279 *
280 * - if our tgid is the same as our PID, then we are either the
281 * first thread in the process or a CLONE_THREAD thread.
282 *
283 * - if the brand lwp value for ppid is 0, then we are either the
284 * child of a differently-branded process or a CLONE_PARENT thread.
285 */
286 if (p->p_pid == lwpd->br_tgid || lwpd->br_ppid == 0) {
287 if (ppidp != NULL)
288 *ppidp = ppid;
289 if (ptidp != NULL)
290 *ptidp = -1;
291 return (ppid);
292 }
293
294 /*
295 * Set the default Linux parent pid to be the pid of the zone's init
296 * process; this will get converted back to the Linux default of 1
297 * later.
298 */
299 lppid = zoneinit;
300
301 /*
302 * If the process's parent isn't init, try and look up the Linux "pid"
303 * corresponding to the process's parent.
304 */
305 if (ppid != 1) {
306 /*
307 * In all other cases, we are looking for the parent of this
308 * specific thread, which in Linux refers to the thread that
309 * clone()d it. We stashed that thread's PID away when this
310 * thread was created.
311 */
312 mutex_enter(&hash_lock);
313 for (hp = ltos_pid_hash[LTOS_HASH(lwpd->br_ppid)]; hp;
314 hp = hp->ltos_next) {
315 if (lwpd->br_ppid == hp->l_pid) {
316 /*
317 * We found the PID we were looking for, but
318 * since we cached its value in this LWP's brand
319 * structure, it has exited and been reused by
320 * another process.
321 */
322 if (hp->l_start > lwptot(lwp)->t_start)
323 break;
324
325 lppid = lwpd->br_ppid;
326 if (ppidp != NULL)
327 *ppidp = hp->s_pid;
328 if (ptidp != NULL)
329 *ptidp = hp->s_tid;
330
331 break;
332 }
333 }
334 mutex_exit(&hash_lock);
335 }
336
337 if (lppid == zoneinit) {
338 lppid = 1;
339
340 if (ppidp != NULL)
341 *ppidp = lppid;
342 if (ptidp != NULL)
343 *ptidp = -1;
344 }
345
346 return (lppid);
347 }
348
349 void
350 lx_pid_init(void)
351 {
352 hash_size = 1 << highbit(v.v_proc / (hash_len * LINUX_PROC_FACTOR));
353
354 stol_pid_hash = kmem_zalloc(sizeof (struct lx_pid *) * hash_size,
355 KM_SLEEP);
356 ltos_pid_hash = kmem_zalloc(sizeof (struct lx_pid *) * hash_size,
357 KM_SLEEP);
358
359 mutex_init(&hash_lock, NULL, MUTEX_DEFAULT, NULL);
360 }
361
362 void
363 lx_pid_fini(void)
364 {
365 kmem_free(stol_pid_hash, sizeof (struct lx_pid *) * hash_size);
366 kmem_free(ltos_pid_hash, sizeof (struct lx_pid *) * hash_size);
367 }