This commit was manufactured by cvs2svn to create branch 'vserver'.
[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-2004  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/vserver/namespace.h>
16 #include <linux/vinline.h>
17 #include <linux/namespace.h>
18 #include <linux/dcache.h>
19
20 #include <asm/errno.h>
21 #include <asm/uaccess.h>
22
23
24 /* virtual host info names */
25
26 static char * vx_vhi_name(struct vx_info *vxi, int id)
27 {
28         switch (id) {
29                 case VHIN_CONTEXT:
30                         return vxi->vx_name;
31                 case VHIN_SYSNAME:
32                         return vxi->cvirt.utsname.sysname;
33                 case VHIN_NODENAME:
34                         return vxi->cvirt.utsname.nodename;
35                 case VHIN_RELEASE:
36                         return vxi->cvirt.utsname.release;
37                 case VHIN_VERSION:
38                         return vxi->cvirt.utsname.version;
39                 case VHIN_MACHINE:
40                         return vxi->cvirt.utsname.machine;
41                 case VHIN_DOMAINNAME:
42                         return vxi->cvirt.utsname.domainname;
43                 default:
44                         return NULL;
45         }
46         return NULL;
47 }
48
49 int vc_set_vhi_name(uint32_t id, void __user *data)
50 {
51         struct vx_info *vxi;
52         struct vcmd_vx_vhi_name_v0 vc_data;
53         char *name;
54
55         if (!capable(CAP_SYS_ADMIN))
56                 return -EPERM;
57         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
58                 return -EFAULT;
59         
60         vxi = find_vx_info(id);
61         if (!vxi)
62                 return -ESRCH;
63         
64         name = vx_vhi_name(vxi, vc_data.field);
65         if (name)
66                 memcpy(name, vc_data.name, 65);
67         put_vx_info(vxi);
68         return (name ? 0 : -EFAULT);
69 }
70
71 int vc_get_vhi_name(uint32_t id, void __user *data)
72 {
73         struct vx_info *vxi;
74         struct vcmd_vx_vhi_name_v0 vc_data;
75         char *name;
76
77         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
78                 return -EFAULT;
79
80         vxi = find_vx_info(id);
81         if (!vxi)
82                 return -ESRCH;
83
84         name = vx_vhi_name(vxi, vc_data.field);
85         if (!name)
86                 goto out_put;
87                         
88         memcpy(vc_data.name, name, 65);
89         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
90                 return -EFAULT;
91 out_put:
92         put_vx_info(vxi);
93         return (name ? 0 : -EFAULT);
94 }
95
96 /* namespace functions */
97
98 #include <linux/namespace.h>
99
100 int vx_set_namespace(struct vx_info *vxi, struct namespace *ns, struct fs_struct *fs)
101 {
102         struct fs_struct *fs_copy;
103
104         if (vxi->vx_namespace)
105                 return -EPERM;
106         if (!ns || !fs)
107                 return -EINVAL;
108
109         fs_copy = copy_fs_struct(fs);
110         if (!fs_copy)
111                 return -ENOMEM;
112
113         get_namespace(ns);
114         vxi->vx_namespace = ns;
115         vxi->vx_fs = fs_copy;
116         return 0;
117 }
118
119 int vc_enter_namespace(uint32_t id, void *data)
120 {
121         struct vx_info *vxi;
122         struct fs_struct *old_fs, *fs;
123         struct namespace *old_ns;
124         int ret = 0;
125
126         if (!vx_check(0, VX_ADMIN))
127                 return -ENOSYS;
128
129         vxi = find_vx_info(id);
130         if (!vxi)
131                 return -ESRCH;
132
133         ret = -EINVAL;
134         if (!vxi->vx_namespace)
135                 goto out_put;
136
137         ret = -ENOMEM;
138         fs = copy_fs_struct(vxi->vx_fs);
139         if (!fs)
140                 goto out_put;
141
142         ret = 0;
143         task_lock(current);
144         old_ns = current->namespace;
145         old_fs = current->fs;
146         get_namespace(vxi->vx_namespace);
147         current->namespace = vxi->vx_namespace; 
148         current->fs = fs;
149         task_unlock(current);
150
151         put_namespace(old_ns);
152         put_fs_struct(old_fs);
153 out_put:
154         put_vx_info(vxi);
155         return ret;
156 }
157
158 int vc_cleanup_namespace(uint32_t id, void *data)
159 {
160         down_write(&current->namespace->sem);
161         // spin_lock(&dcache_lock);
162         spin_lock(&vfsmount_lock);
163         umount_unused(current->namespace->root, current->fs);
164         spin_unlock(&vfsmount_lock);
165         // spin_unlock(&dcache_lock);
166         up_write(&current->namespace->sem);
167         return 0;
168 }
169
170 int vc_set_namespace(uint32_t id, void __user *data)
171 {
172         struct fs_struct *fs;
173         struct namespace *ns;
174         struct vx_info *vxi;
175         int ret;
176
177         if (vx_check(0, VX_ADMIN|VX_WATCH))
178                 return -ENOSYS;
179
180         task_lock(current);
181         vxi = get_vx_info(current->vx_info);
182         fs = current->fs;
183         atomic_inc(&fs->count);
184         ns = current->namespace;
185         get_namespace(current->namespace);
186         task_unlock(current);
187
188         ret = vx_set_namespace(vxi, ns, fs);
189
190         put_namespace(ns);
191         put_fs_struct(fs);
192         put_vx_info(vxi);
193         return ret;
194 }
195