2 * linux/kernel/vserver/space.c
4 * Virtual Server: Context Space Support
6 * Copyright (C) 2003-2007 Herbert Pƶtzl
8 * V0.01 broken out from context.c 0.07
9 * V0.02 added task locking for namespace
10 * V0.03 broken out vx_enter_namespace
11 * V0.04 added *space support and commands
15 #include <linux/utsname.h>
16 #include <linux/sched.h>
17 #include <linux/vs_context.h>
18 #include <linux/vserver/space.h>
19 #include <linux/vserver/space_cmd.h>
20 #include <linux/dcache.h>
21 #include <linux/mount.h>
22 #include <linux/nsproxy.h>
25 #include <asm/errno.h>
26 #include <asm/uaccess.h>
29 atomic_t vs_global_nsproxy = ATOMIC_INIT(0);
30 atomic_t vs_global_fs = ATOMIC_INIT(0);
31 atomic_t vs_global_mnt_ns = ATOMIC_INIT(0);
32 atomic_t vs_global_uts_ns = ATOMIC_INIT(0);
33 atomic_t vs_global_ipc_ns = ATOMIC_INIT(0);
36 /* namespace functions */
38 #include <linux/mnt_namespace.h>
40 const struct vcmd_space_mask space_mask = {
49 * build a new nsproxy mix
50 * assumes that both proxies are 'const'
51 * does not touch nsproxy refcounts
52 * will hold a reference on the result.
55 struct nsproxy *vs_mix_nsproxy(struct nsproxy *old_nsproxy,
56 struct nsproxy *new_nsproxy, unsigned long mask)
58 struct mnt_namespace *old_ns;
59 struct uts_namespace *old_uts;
60 struct ipc_namespace *old_ipc;
61 struct nsproxy *nsproxy;
63 nsproxy = dup_namespaces(old_nsproxy);
67 if (mask & CLONE_NEWNS) {
68 old_ns = nsproxy->mnt_ns;
69 nsproxy->mnt_ns = new_nsproxy->mnt_ns;
71 get_mnt_ns(nsproxy->mnt_ns);
75 if (mask & CLONE_NEWUTS) {
76 old_uts = nsproxy->uts_ns;
77 nsproxy->uts_ns = new_nsproxy->uts_ns;
79 get_uts_ns(nsproxy->uts_ns);
83 if (mask & CLONE_NEWIPC) {
84 old_ipc = nsproxy->ipc_ns;
85 nsproxy->ipc_ns = new_nsproxy->ipc_ns;
87 get_ipc_ns(nsproxy->ipc_ns);
103 * merge two nsproxy structs into a new one.
104 * will hold a reference on the result.
108 struct nsproxy * __vs_merge_nsproxy(struct nsproxy *old,
109 struct nsproxy *proxy, unsigned long mask)
111 struct nsproxy null_proxy = { .mnt_ns = NULL };
117 return vs_mix_nsproxy(old ? old : &null_proxy,
124 * merge two fs structs into a new one.
125 * will take a reference on the result.
129 struct fs_struct * __vs_merge_fs(struct fs_struct *old,
130 struct fs_struct *fs, unsigned long mask)
132 if (!(mask & CLONE_FS)) {
134 atomic_inc(&old->count);
141 return copy_fs_struct(fs);
145 int vx_enter_space(struct vx_info *vxi, unsigned long mask)
147 struct nsproxy *proxy, *proxy_cur, *proxy_new;
148 struct fs_struct *fs, *fs_cur, *fs_new;
151 if (vx_info_flags(vxi, VXF_INFO_PRIVATE, 0))
155 mask = vxi->vx_nsmask;
157 if ((mask & vxi->vx_nsmask) != mask)
160 proxy = vxi->vx_nsproxy;
164 fs_cur = current->fs;
165 atomic_inc(&fs_cur->count);
166 proxy_cur = current->nsproxy;
167 get_nsproxy(proxy_cur);
168 task_unlock(current);
170 fs_new = __vs_merge_fs(fs_cur, fs, mask);
171 if (IS_ERR(fs_new)) {
172 ret = PTR_ERR(fs_new);
176 proxy_new = __vs_merge_nsproxy(proxy_cur, proxy, mask);
177 if (IS_ERR(proxy_new)) {
178 ret = PTR_ERR(proxy_new);
182 fs_new = xchg(¤t->fs, fs_new);
183 proxy_new = xchg(¤t->nsproxy, proxy_new);
187 put_nsproxy(proxy_new);
190 put_fs_struct(fs_new);
193 put_nsproxy(proxy_cur);
195 put_fs_struct(fs_cur);
200 int vx_set_space(struct vx_info *vxi, unsigned long mask)
202 struct nsproxy *proxy_vxi, *proxy_cur, *proxy_new;
203 struct fs_struct *fs_vxi, *fs_cur, *fs_new;
207 mask = space_mask.mask;
209 if ((mask & space_mask.mask) != mask)
212 proxy_vxi = vxi->vx_nsproxy;
216 fs_cur = current->fs;
217 atomic_inc(&fs_cur->count);
218 proxy_cur = current->nsproxy;
219 get_nsproxy(proxy_cur);
220 task_unlock(current);
222 fs_new = __vs_merge_fs(fs_vxi, fs_cur, mask);
223 if (IS_ERR(fs_new)) {
224 ret = PTR_ERR(fs_new);
228 proxy_new = __vs_merge_nsproxy(proxy_vxi, proxy_cur, mask);
229 if (IS_ERR(proxy_new)) {
230 ret = PTR_ERR(proxy_new);
234 fs_new = xchg(&vxi->vx_fs, fs_new);
235 proxy_new = xchg(&vxi->vx_nsproxy, proxy_new);
236 vxi->vx_nsmask |= mask;
240 put_nsproxy(proxy_new);
243 put_fs_struct(fs_new);
246 put_nsproxy(proxy_cur);
248 put_fs_struct(fs_cur);
253 int vc_enter_space(struct vx_info *vxi, void __user *data)
255 struct vcmd_space_mask vc_data = { .mask = 0 };
257 if (data && copy_from_user (&vc_data, data, sizeof(vc_data)))
260 return vx_enter_space(vxi, vc_data.mask);
263 int vc_set_space(struct vx_info *vxi, void __user *data)
265 struct vcmd_space_mask vc_data = { .mask = 0 };
267 if (data && copy_from_user (&vc_data, data, sizeof(vc_data)))
270 return vx_set_space(vxi, vc_data.mask);
273 int vc_get_space_mask(struct vx_info *vxi, void __user *data)
275 if (copy_to_user(data, &space_mask, sizeof(space_mask)))