vserver 2.0 rc7
[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/config.h>
14 #include <linux/utsname.h>
15 #include <linux/sched.h>
16 #include <linux/vs_context.h>
17 #include <linux/vserver/namespace.h>
18 #include <linux/vserver/namespace_cmd.h>
19 #include <linux/dcache.h>
20 #include <linux/mount.h>
21 #include <linux/fs.h>
22
23 #include <asm/errno.h>
24 #include <asm/uaccess.h>
25
26
27 /* namespace functions */
28
29 #include <linux/namespace.h>
30
31 int vx_set_namespace(struct vx_info *vxi, struct namespace *ns, struct fs_struct *fs)
32 {
33         struct fs_struct *fs_copy;
34
35         if (vxi->vx_namespace)
36                 return -EPERM;
37         if (!ns || !fs)
38                 return -EINVAL;
39
40         fs_copy = copy_fs_struct(fs);
41         if (!fs_copy)
42                 return -ENOMEM;
43
44         get_namespace(ns);
45         vxi->vx_namespace = ns;
46         vxi->vx_fs = fs_copy;
47         return 0;
48 }
49
50 int vc_enter_namespace(uint32_t id, void *data)
51 {
52         struct vx_info *vxi;
53         struct fs_struct *old_fs, *fs;
54         struct namespace *old_ns;
55         int ret = 0;
56
57         if (!vx_check(0, VX_ADMIN))
58                 return -ENOSYS;
59
60         vxi = locate_vx_info(id);
61         if (!vxi)
62                 return -ESRCH;
63
64         ret = -EINVAL;
65         if (!vxi->vx_namespace)
66                 goto out_put;
67
68         ret = -ENOMEM;
69         fs = copy_fs_struct(vxi->vx_fs);
70         if (!fs)
71                 goto out_put;
72
73         ret = 0;
74         task_lock(current);
75         old_ns = current->namespace;
76         old_fs = current->fs;
77         get_namespace(vxi->vx_namespace);
78         current->namespace = vxi->vx_namespace;
79         current->fs = fs;
80         task_unlock(current);
81
82         put_namespace(old_ns);
83         put_fs_struct(old_fs);
84 out_put:
85         put_vx_info(vxi);
86         return ret;
87 }
88
89 int vc_cleanup_namespace(uint32_t id, void *data)
90 {
91         down_write(&current->namespace->sem);
92         spin_lock(&vfsmount_lock);
93         umount_unused(current->namespace->root, current->fs);
94         spin_unlock(&vfsmount_lock);
95         up_write(&current->namespace->sem);
96         return 0;
97 }
98
99 int vc_set_namespace(uint32_t id, void __user *data)
100 {
101         struct fs_struct *fs;
102         struct namespace *ns;
103         struct vx_info *vxi;
104         int ret;
105
106         if (vx_check(0, VX_ADMIN|VX_WATCH))
107                 return -ENOSYS;
108
109         task_lock(current);
110         vxi = get_vx_info(current->vx_info);
111         fs = current->fs;
112         atomic_inc(&fs->count);
113         ns = current->namespace;
114         get_namespace(current->namespace);
115         task_unlock(current);
116
117         ret = vx_set_namespace(vxi, ns, fs);
118
119         put_namespace(ns);
120         put_fs_struct(fs);
121         put_vx_info(vxi);
122         return ret;
123 }
124