84e58c5ae25ce82e73d1322f04883d2bb37986b1
[linux-2.6.git] / kernel / vserver / namespace.c
1 /*
2  *  linux/kernel/vserver/namespace.c
3  *
4  *  Virtual Server: Context Namespace Support
5  *
6  *  Copyright (C) 2003-2005  Herbert Pƶtzl
7  *
8  *  V0.01  broken out from context.c 0.07
9  *  V0.02  added task locking for namespace
10  *
11  */
12
13 #include <linux/utsname.h>
14 #include <linux/sched.h>
15 #include <linux/vs_context.h>
16 #include <linux/vserver/namespace.h>
17 #include <linux/vserver/namespace_cmd.h>
18 #include <linux/dcache.h>
19 #include <linux/mount.h>
20 #include <linux/fs.h>
21
22 #include <asm/errno.h>
23 #include <asm/uaccess.h>
24
25
26 /* namespace functions */
27
28 #include <linux/namespace.h>
29
30 int vx_set_namespace(struct vx_info *vxi, struct namespace *ns, struct fs_struct *fs)
31 {
32         struct fs_struct *fs_copy;
33
34         if (vxi->vx_namespace)
35                 return -EPERM;
36         if (!ns || !fs)
37                 return -EINVAL;
38
39         fs_copy = copy_fs_struct(fs);
40         if (!fs_copy)
41                 return -ENOMEM;
42
43         get_namespace(ns);
44         vxi->vx_namespace = ns;
45         vxi->vx_fs = fs_copy;
46         return 0;
47 }
48
49 int vc_enter_namespace(uint32_t id, void __user *data)
50 {
51         struct vx_info *vxi;
52         struct fs_struct *old_fs, *fs;
53         struct namespace *old_ns;
54         int ret = 0;
55
56         if (!vx_check(0, VX_ADMIN))
57                 return -ENOSYS;
58
59         vxi = lookup_vx_info(id);
60         if (!vxi)
61                 return -ESRCH;
62
63         ret = -EINVAL;
64         if (!vxi->vx_namespace)
65                 goto out_put;
66
67         ret = -ENOMEM;
68         fs = copy_fs_struct(vxi->vx_fs);
69         if (!fs)
70                 goto out_put;
71
72         ret = 0;
73         task_lock(current);
74         old_ns = current->namespace;
75         old_fs = current->fs;
76         get_namespace(vxi->vx_namespace);
77         current->namespace = vxi->vx_namespace;
78         current->fs = fs;
79         task_unlock(current);
80
81         put_namespace(old_ns);
82         put_fs_struct(old_fs);
83 out_put:
84         put_vx_info(vxi);
85         return ret;
86 }
87
88 int vc_cleanup_namespace(uint32_t id, void __user *data)
89 {
90         // down_write(&current->namespace->sem);
91         spin_lock(&vfsmount_lock);
92         umount_unused(current->namespace->root, current->fs);
93         spin_unlock(&vfsmount_lock);
94         // up_write(&current->namespace->sem);
95         return 0;
96 }
97
98 int vc_set_namespace(uint32_t id, void __user *data)
99 {
100         struct fs_struct *fs;
101         struct namespace *ns;
102         struct vx_info *vxi;
103         int ret;
104
105         vxi = lookup_vx_info(id);
106         if (!vxi)
107                 return -ESRCH;
108
109         task_lock(current);
110         fs = current->fs;
111         atomic_inc(&fs->count);
112         ns = current->namespace;
113         get_namespace(current->namespace);
114         task_unlock(current);
115
116         ret = vx_set_namespace(vxi, ns, fs);
117
118         put_namespace(ns);
119         put_fs_struct(fs);
120         put_vx_info(vxi);
121         return ret;
122 }
123