Whamcloud - gitweb
LU-4476 kernel: support process namespace containers
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-curproc.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * libcfs/libcfs/winnt/winnt-curproc.c
37  *
38  * Impletion of winnt curproc routines.
39  */
40
41 #define DEBUG_SUBSYSTEM S_LNET
42
43 #include <libcfs/libcfs.h>
44
45 /*
46  * Implementation of cfs_curproc API (see portals/include/libcfs/curproc.h)
47  * for Linux kernel.
48  */
49
50 struct task_struct this_task =
51     { /* umask */ 0,/* blocked*/0, /* pid */ 0, /* pgrp */ 0,
52       /* uid,euid,suid,fsuid */  0, 0, 0, 0,
53       /* gid_t gid,egid,sgid,fsgid */ 0, 0, 0, 0,
54       /* ngroups*/ 1, /*cgroups*/ 0, /*groups*/ 0,
55       /* group_info */ NULL,
56       /* cap_effective, cap_inheritable, cap_permitted */  0, 0, 0,
57       /* comm */"sysetm\0",
58       /* journal_info */ NULL
59     };
60
61 struct user_namespace init_user_ns __read_mostly;
62 EXPORT_SYMBOL(init_user_ns);
63
64 uid_t  current_uid(void)
65 {
66     return this_task.uid;
67 }
68
69 gid_t  current_gid(void)
70 {
71     return this_task.gid;
72 }
73
74 uid_t  current_fsuid(void)
75 {
76     return this_task.fsuid;
77 }
78
79 gid_t current_fsgid(void)
80 {
81     return this_task.fsgid;
82 }
83
84 pid_t current_pid(void)
85 {
86     return current->pid;
87 }
88
89 mode_t current_umask(void)
90 {
91     return this_task.umask;
92 }
93
94 char  *current_comm(void)
95 {
96     return this_task.comm;
97 }
98
99 void cfs_cap_raise(cfs_cap_t cap)
100 {
101         this_task.cap_effective |= (1 << cap);
102 }
103
104 void cfs_cap_lower(cfs_cap_t cap)
105 {
106         this_task.cap_effective &= ~(1 << cap);
107 }
108
109 int cfs_cap_raised(cfs_cap_t cap)
110 {
111         return this_task.cap_effective & (1 << cap);
112 }
113
114 cfs_cap_t cfs_curproc_cap_pack(void) {
115         return this_task.cap_effective;
116 }
117
118 void cfs_curproc_cap_unpack(cfs_cap_t cap) {
119         this_task.cap_effective = cap;
120 }
121
122 int cfs_capable(cfs_cap_t cap)
123 {
124         return TRUE;
125 }
126
127 /*
128  * Implementation of linux task management routines
129  */
130
131
132 /* global of the task manager structure */
133
134 TASK_MAN cfs_win_task_manger;
135
136 /* global idr context */
137 struct idr_context * cfs_win_task_slot_idp = NULL;
138
139 /*
140  *  task slot routiens
141  */
142
143 PTASK_SLOT alloc_task_slot()
144 {
145         if (cfs_win_task_manger.slab)
146                 return kmem_cache_alloc(cfs_win_task_manger.slab, 0);
147         else
148                 return kmalloc(sizeof(TASK_SLOT), 0);
149 }
150
151 void
152 init_task_slot(PTASK_SLOT task)
153 {
154     memset(task, 0, sizeof(TASK_SLOT));
155     task->Magic = TASKSLT_MAGIC;
156     task->task  = this_task;
157     cfs_init_event(&task->Event, TRUE, FALSE);
158 }
159
160 void cleanup_task_slot(PTASK_SLOT task)
161 {
162         if (task->task.pid)
163                 cfs_idr_remove(cfs_win_task_slot_idp, task->task.pid);
164
165         if (cfs_win_task_manger.slab)
166                 kmem_cache_free(cfs_win_task_manger.slab, task);
167         else
168                 kfree(task);
169 }
170
171 /*
172  *  task manager related routines
173  */
174
175 VOID
176 task_manager_notify(
177     IN HANDLE   ProcessId,
178     IN HANDLE   ThreadId,
179     IN BOOLEAN  Create
180     )
181 {
182     PLIST_ENTRY ListEntry = NULL;
183     PTASK_SLOT  TaskSlot  = NULL;
184
185         spin_lock(&(cfs_win_task_manger.Lock));
186
187     ListEntry = cfs_win_task_manger.TaskList.Flink;
188     while (ListEntry != (&(cfs_win_task_manger.TaskList))) {
189
190         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
191
192         if (TaskSlot->Pid == ProcessId && TaskSlot->Tid == ThreadId) {
193
194             if (!Create) {
195                 /* remove the taskslot */
196                 RemoveEntryList(&(TaskSlot->Link));
197                 cfs_win_task_manger.NumOfTasks--;
198
199                 /* now free the task slot */
200                 cleanup_task_slot(TaskSlot);
201             }
202         }
203
204         ListEntry = ListEntry->Flink;
205     }
206
207         spin_unlock(&(cfs_win_task_manger.Lock));
208 }
209
210 int
211 init_task_manager()
212 {
213     NTSTATUS    status;
214
215     /* initialize the content and magic */
216     memset(&cfs_win_task_manger, 0, sizeof(TASK_MAN));
217     cfs_win_task_manger.Magic = TASKMAN_MAGIC;
218
219     /* initialize the spinlock protection */
220         spin_lock_init(&cfs_win_task_manger.Lock);
221
222         /* create slab memory cache */
223         cfs_win_task_manger.slab = kmem_cache_create("TSLT", sizeof(TASK_SLOT),
224                                                      0, 0, NULL);
225
226     /* intialize the list header */
227     InitializeListHead(&(cfs_win_task_manger.TaskList));
228
229     cfs_win_task_slot_idp = cfs_idr_init();
230     if (!cfs_win_task_slot_idp) {
231         return -ENOMEM;
232     }
233
234     /* set the thread creation/destruction notify routine */
235     status = PsSetCreateThreadNotifyRoutine(task_manager_notify);
236
237     if (!NT_SUCCESS(status)) {
238         cfs_enter_debugger();
239         /* remove idr context */
240         if (cfs_win_task_slot_idp) {
241             cfs_idr_exit(cfs_win_task_slot_idp);
242             cfs_win_task_slot_idp = NULL;
243         }
244         return cfs_error_code(status);
245     }
246
247     return 0;
248 }
249
250 void
251 cleanup_task_manager()
252 {
253     PLIST_ENTRY ListEntry = NULL;
254     PTASK_SLOT  TaskSlot  = NULL;
255
256     /* remove ThreadNotifyRoutine: task_manager_notify */
257     PsRemoveCreateThreadNotifyRoutine(task_manager_notify);
258
259     /* remove idr context */
260     if (cfs_win_task_slot_idp) {
261         cfs_idr_exit(cfs_win_task_slot_idp);
262         cfs_win_task_slot_idp = NULL;
263     }
264
265     /* cleanup all the taskslots attached to the list */
266         spin_lock(&(cfs_win_task_manger.Lock));
267
268     while (!IsListEmpty(&(cfs_win_task_manger.TaskList))) {
269
270         ListEntry = cfs_win_task_manger.TaskList.Flink;
271         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
272
273         RemoveEntryList(ListEntry);
274         cleanup_task_slot(TaskSlot);
275     }
276
277         spin_unlock(&cfs_win_task_manger.Lock);
278
279         /* destroy the taskslot cache slab */
280         kmem_cache_destroy(cfs_win_task_manger.slab);
281         memset(&cfs_win_task_manger, 0, sizeof(TASK_MAN));
282 }
283
284
285 /*
286  * schedule routines (task slot list)
287  */
288
289
290 struct task_struct *
291 current
292 {
293     HANDLE      Pid = PsGetCurrentProcessId();
294     HANDLE      Tid = PsGetCurrentThreadId();
295     PETHREAD    Tet = PsGetCurrentThread();
296
297     PLIST_ENTRY ListEntry = NULL;
298     PTASK_SLOT  TaskSlot  = NULL;
299
300         spin_lock(&(cfs_win_task_manger.Lock));
301
302     ListEntry = cfs_win_task_manger.TaskList.Flink;
303     while (ListEntry != (&(cfs_win_task_manger.TaskList))) {
304
305         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
306         if (TaskSlot->Pid == Pid && TaskSlot->Tid == Tid) {
307             if (TaskSlot->Tet != Tet) {
308
309                 //
310                 // The old thread was already exit. This must be a
311                 // new thread which get the same Tid to the previous.
312                 //
313
314                 TaskSlot->Tet = Tet;
315             }
316             break;
317
318         } else {
319
320             if (TaskSlot->Pid > Pid) {
321                 TaskSlot = NULL;
322                 break;
323             } else if (TaskSlot->Pid == Pid) {
324                 if (TaskSlot->Tid > Tid) {
325                     TaskSlot = NULL;
326                     break;
327                 }
328             }
329             TaskSlot =  NULL;
330         }
331
332         ListEntry = ListEntry->Flink;
333     }
334
335     if (!TaskSlot) {
336
337         /* allocate new task slot */
338         TaskSlot = alloc_task_slot();
339         if (!TaskSlot) {
340             cfs_enter_debugger();
341             goto errorout;
342         }
343
344         /* set task slot IDs */
345         init_task_slot(TaskSlot);
346         TaskSlot->Pid = Pid;
347         TaskSlot->Tid = Tid;
348         TaskSlot->Tet = Tet;
349         TaskSlot->task.pid = (pid_t)cfs_idr_get_new(cfs_win_task_slot_idp, Tet);
350
351         if (ListEntry == (&(cfs_win_task_manger.TaskList))) {
352             //
353             // Empty case or the biggest case, put it to the tail.
354             //
355             InsertTailList(&(cfs_win_task_manger.TaskList), &(TaskSlot->Link));
356         } else {
357             //
358             // Get a slot and smaller than it's tid, put it just before.
359             //
360             InsertHeadList(ListEntry->Blink, &(TaskSlot->Link));
361         }
362
363         cfs_win_task_manger.NumOfTasks++;
364     }
365
366     //
367     // To Check whether he task structures are arranged in the expected order ?
368     //
369
370     {
371         PTASK_SLOT  Prev = NULL, Curr = NULL;
372
373         ListEntry = cfs_win_task_manger.TaskList.Flink;
374
375         while (ListEntry != (&(cfs_win_task_manger.TaskList))) {
376
377             Curr = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
378             ListEntry = ListEntry->Flink;
379
380             if (Prev) {
381                 if (Prev->Pid > Curr->Pid) {
382                     cfs_enter_debugger();
383                 } else if (Prev->Pid == Curr->Pid) {
384                     if (Prev->Tid > Curr->Tid) {
385                         cfs_enter_debugger();
386                     }
387                 }
388             }
389
390             Prev = Curr;
391         }
392     }
393
394 errorout:
395
396         spin_unlock(&(cfs_win_task_manger.Lock));
397
398     if (!TaskSlot) {
399         cfs_enter_debugger();
400         return NULL;
401     }
402
403     return (&(TaskSlot->task));
404 }
405
406 /* deschedule for a bit... */
407 void
408 cfs_pause(cfs_duration_t ticks)
409 {
410     schedule_timeout_and_set_state(CFS_TASK_UNINTERRUPTIBLE, ticks);
411 }
412
413 void
414 schedule_timeout_and_set_state(long state, int64_t time)
415 {
416     struct task_struct * task = current;
417     PTASK_SLOT   slot = NULL;
418
419     if (!task) {
420         cfs_enter_debugger();
421         return;
422     }
423
424     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
425     cfs_assert(slot->Magic == TASKSLT_MAGIC);
426
427     if (time == MAX_SCHEDULE_TIMEOUT) {
428         time = 0;
429     }
430
431     cfs_wait_event_internal(&(slot->Event), time);
432 }
433
434 void
435 schedule()
436 {
437     schedule_timeout_and_set_state(CFS_TASK_UNINTERRUPTIBLE, 0);
438 }
439
440 int
441 wake_up_process(
442     struct task_struct * task
443     )
444 {
445     PTASK_SLOT   slot = NULL;
446
447     if (!task) {
448         cfs_enter_debugger();
449         return 0;
450     }
451
452     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
453     cfs_assert(slot->Magic == TASKSLT_MAGIC);
454
455     cfs_wake_event(&(slot->Event));
456
457     return TRUE;
458 }
459
460 void
461 sleep_on(wait_queue_head_t *waitq)
462 {
463         wait_queue_t link;
464
465         init_waitqueue_entry_current(&link);
466         add_wait_queue(waitq, &link);
467         waitq_wait(&link, TASK_INTERRUPTIBLE);
468         remove_wait_queue(waitq, &link);
469 }
470
471 EXPORT_SYMBOL(current_uid);
472 EXPORT_SYMBOL(current_pid);
473 EXPORT_SYMBOL(current_gid);
474 EXPORT_SYMBOL(current_fsuid);
475 EXPORT_SYMBOL(current_fsgid);
476 EXPORT_SYMBOL(current_umask);
477 EXPORT_SYMBOL(current_comm);
478 EXPORT_SYMBOL(cfs_cap_raise);
479 EXPORT_SYMBOL(cfs_cap_lower);
480 EXPORT_SYMBOL(cfs_cap_raised);
481 EXPORT_SYMBOL(cfs_curproc_cap_pack);
482 EXPORT_SYMBOL(cfs_curproc_cap_unpack);
483 EXPORT_SYMBOL(cfs_capable);