~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to modules/linux/shared/compat_kthread.h

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************
2
 
 * Copyright (C) 2008 VMware, Inc. All rights reserved.
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify it
5
 
 * under the terms of the GNU General Public License as published by the
6
 
 * Free Software Foundation version 2 and no later version.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but
9
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11
 
 * for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU General Public License along
14
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
15
 
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
16
 
 *
17
 
 *********************************************************/
18
 
 
19
 
#ifndef __COMPAT_KTHREAD_H__
20
 
#   define __COMPAT_KTHREAD_H__
21
 
 
22
 
/*
23
 
 * The kthread interface for managing kernel threads appeared in 2.6.4, but was
24
 
 * only exported for module use in 2.6.7.
25
 
 */
26
 
 
27
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 7)
28
 
# include <linux/kthread.h>
29
 
 
30
 
# define COMPAT_KTHREAD_DECLARE_STOP_INFO()
31
 
# define compat_kthread_stop(_tsk) kthread_stop(_tsk)
32
 
# define compat_kthread_should_stop() kthread_should_stop()
33
 
# define compat_kthread_run(_fn, _data, _namefmt, ...)                         \
34
 
   kthread_run(_fn, _data, _namefmt, ## __VA_ARGS__)
35
 
# define compat_kthread_create(_fn, _data, _namefmt, ...)                      \
36
 
   kthread_create(_fn, _data, _namefmt, ## __VA_ARGS__)
37
 
#else
38
 
 
39
 
/*
40
 
 * When the kthread interface isn't available, we do our best to emulate it,
41
 
 * with a few notable exceptions:
42
 
 *
43
 
 * 1: We use semaphores instead of mutexes for locking, because mutexes aren't
44
 
 *    available in kernels where kthread isn't available.
45
 
 * 2: The real kthread interface uses the kthreadd kernel_thread to broker the
46
 
 *    creation of new kernel threads. This makes sense because kthreadd is part
47
 
 *    of the kernel, but doesn't make sense at all in the context of an
48
 
 *    individual module. So in our emulation, thread creation occurs in the
49
 
 *    context of a kthread_create call.
50
 
 * 3: Because kthreadd is responsible for creating kernel threads in the real
51
 
 *    kthread interface, there's no need to explicitly reparent any of them. We
52
 
 *    aren't using kthreadd, so we call daemonize to reparent, which also sets
53
 
 *    the name of the new kernel thread. That's why we don't set the name as
54
 
 *    the real kthread interface does (within kthread_create). Furthermore, to
55
 
 *    get the name to daemonize, we're forced to pass it through the
56
 
 *    kthread_start_info struct.
57
 
 * 4: Since our interface isn't in the kernel proper, we can't make use of
58
 
 *    get_task_struct/put_task_struct so as to acquire references to kernel
59
 
 *    threads that we're managing. To prevent races, we use an extra completion
60
 
 *    when stopping kernel threads. See the comments in compat_kthread_stop for
61
 
 *    more details.
62
 
 *
63
 
 * Like the real kthread interface, ours must be globally available so that we
64
 
 * can emulate functions like kthread_should_stop without using different
65
 
 * signatures.
66
 
 */
67
 
 
68
 
# include "compat_completion.h"
69
 
# include "compat_kernel.h"
70
 
# include "compat_sched.h"
71
 
 
72
 
struct compat_kthread_start_info {
73
 
   int (*fn)(void *);
74
 
   void *data;
75
 
   compat_completion created;
76
 
   char comm[TASK_COMM_LEN];
77
 
};
78
 
 
79
 
struct compat_kthread_stop_info {
80
 
   struct semaphore lock;
81
 
   struct task_struct *task;
82
 
   compat_completion woken;
83
 
   compat_completion stopped;
84
 
   int ret;
85
 
};
86
 
 
87
 
extern struct compat_kthread_stop_info compat_kthread_stop_info;
88
 
 
89
 
# define COMPAT_KTHREAD_DECLARE_STOP_INFO()                                    \
90
 
   struct compat_kthread_stop_info compat_kthread_stop_info = {                \
91
 
      .lock = __SEMAPHORE_INITIALIZER(compat_kthread_stop_info.lock, 1),       \
92
 
      .task = NULL,                                                            \
93
 
   }
94
 
 
95
 
 
96
 
static inline int
97
 
compat_kthread_should_stop(void)
98
 
{
99
 
   return (compat_kthread_stop_info.task == current);
100
 
}
101
 
 
102
 
 
103
 
static inline int
104
 
compat_kthread_stop(struct task_struct *_task)
105
 
{
106
 
   int ret;
107
 
 
108
 
   down(&compat_kthread_stop_info.lock);
109
 
 
110
 
   /*
111
 
    * We use a write memory barrier to ensure that all CPUs see _task after
112
 
    * the completions have been initialized.
113
 
    *
114
 
    * There's a race between kernel threads managed by kthread and the upcoming
115
 
    * call to wake_up_process. If the kernel thread wakes up after we set task
116
 
    * but before the call to wake_up_process, the thread's call to
117
 
    * compat_kthread_should_stop will return true and the thread will exit. At
118
 
    * that point, the call to wake_up_process will be on a dead task_struct.
119
 
    *
120
 
    * XXX: The real kthread interface protects against this race by grabbing
121
 
    * and releasing a reference to _task. We don't have that luxury, because
122
 
    * there is a range of kernels where put_task_struct isn't exported to
123
 
    * modules. In fact, no other modules call get_task_struct or
124
 
    * put_task_struct, so to do so from this context may be unwise. Instead,
125
 
    * we'll use an extra completion to ensure that the kernel thread only exits
126
 
    * after wake_up_process has been called.
127
 
    */
128
 
   compat_init_completion(&compat_kthread_stop_info.woken);
129
 
   compat_init_completion(&compat_kthread_stop_info.stopped);
130
 
   smp_wmb();
131
 
 
132
 
   compat_kthread_stop_info.task = _task;
133
 
   wake_up_process(_task);
134
 
   compat_complete(&compat_kthread_stop_info.woken);
135
 
 
136
 
   compat_wait_for_completion(&compat_kthread_stop_info.stopped);
137
 
   compat_kthread_stop_info.task = NULL;
138
 
   ret = compat_kthread_stop_info.ret;
139
 
   up(&compat_kthread_stop_info.lock);
140
 
   return ret;
141
 
}
142
 
 
143
 
 
144
 
# define compat_kthread_run(_fn, _data, _namefmt, ...)                         \
145
 
({                                                                             \
146
 
   struct task_struct *tsk;                                                    \
147
 
   tsk = compat_kthread_create(_fn, _data, _namefmt, ## __VA_ARGS__);          \
148
 
   if (!IS_ERR(tsk)) {                                                         \
149
 
      wake_up_process(tsk);                                                    \
150
 
   }                                                                           \
151
 
   tsk;                                                                        \
152
 
})
153
 
 
154
 
 
155
 
static inline int
156
 
compat_kthread(void *_data)
157
 
{
158
 
   int ret = -EINTR;
159
 
   struct compat_kthread_start_info *info;
160
 
   int (*fn)(void *data);
161
 
   void *data;
162
 
 
163
 
   info = (struct compat_kthread_start_info *)_data;
164
 
   fn = info->fn;
165
 
   data = info->data;
166
 
 
167
 
   compat_daemonize(info->comm);
168
 
   __set_current_state(TASK_UNINTERRUPTIBLE);
169
 
   compat_complete(&info->created);
170
 
   schedule();
171
 
 
172
 
   if (!compat_kthread_should_stop()) {
173
 
      ret = fn(data);
174
 
   }
175
 
 
176
 
   if (compat_kthread_should_stop()) {
177
 
      compat_wait_for_completion(&compat_kthread_stop_info.woken);
178
 
      compat_kthread_stop_info.ret = ret;
179
 
      compat_complete_and_exit(&compat_kthread_stop_info.stopped, 0);
180
 
      BUG();
181
 
   }
182
 
   return 0;
183
 
}
184
 
 
185
 
 
186
 
static inline struct task_struct *
187
 
compat_kthread_create(int (*_fn)(void *data),
188
 
                      void *_data,
189
 
                      const char _namefmt[],
190
 
                      ...)
191
 
{
192
 
   pid_t pid;
193
 
   struct task_struct *task = NULL;
194
 
   struct compat_kthread_start_info info;
195
 
   va_list args;
196
 
 
197
 
   info.fn = _fn;
198
 
   info.data = _data;
199
 
   compat_init_completion(&info.created);
200
 
   va_start(args, _namefmt);
201
 
   vsnprintf(info.comm, sizeof info.comm, _namefmt, args);
202
 
   va_end(args);
203
 
   pid = kernel_thread(compat_kthread, &info, CLONE_KERNEL);
204
 
   if (pid >= 0) {
205
 
      compat_wait_for_completion(&info.created);
206
 
 
207
 
      /*
208
 
       * find_task_by_pid must be called with tasklist_lock held or under
209
 
       * rcu_read_lock. As the latter doesn't exist in old kernels, we use the
210
 
       * former for convenience.
211
 
       */
212
 
      read_lock(&tasklist_lock);
213
 
      task = find_task_by_pid(pid);
214
 
      read_unlock(&tasklist_lock);
215
 
 
216
 
      /* XXX: Do we need to get a reference on task? */
217
 
   }
218
 
   return task;
219
 
}
220
 
 
221
 
#endif
222
 
 
223
 
#endif /* __COMPAT_KTHREAD_H__ */