Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[wrt350n-kernel.git] / fs / proc / proc_net.c
blobc19bbc7d3294b5deea0e60db70893449934963ac
1 /*
2 * linux/fs/proc/net.c
4 * Copyright (C) 2007
6 * Author: Eric Biederman <ebiederm@xmission.com>
8 * proc net directory handling functions
9 */
11 #include <asm/uaccess.h>
13 #include <linux/errno.h>
14 #include <linux/time.h>
15 #include <linux/proc_fs.h>
16 #include <linux/stat.h>
17 #include <linux/init.h>
18 #include <linux/sched.h>
19 #include <linux/module.h>
20 #include <linux/bitops.h>
21 #include <linux/smp_lock.h>
22 #include <linux/mount.h>
23 #include <linux/nsproxy.h>
24 #include <net/net_namespace.h>
25 #include <linux/seq_file.h>
27 #include "internal.h"
30 int seq_open_net(struct inode *ino, struct file *f,
31 const struct seq_operations *ops, int size)
33 struct net *net;
34 struct seq_net_private *p;
36 BUG_ON(size < sizeof(*p));
38 net = get_proc_net(ino);
39 if (net == NULL)
40 return -ENXIO;
42 p = __seq_open_private(f, ops, size);
43 if (p == NULL) {
44 put_net(net);
45 return -ENOMEM;
47 p->net = net;
48 return 0;
50 EXPORT_SYMBOL_GPL(seq_open_net);
52 int seq_release_net(struct inode *ino, struct file *f)
54 struct seq_file *seq;
55 struct seq_net_private *p;
57 seq = f->private_data;
58 p = seq->private;
60 put_net(p->net);
61 seq_release_private(ino, f);
62 return 0;
64 EXPORT_SYMBOL_GPL(seq_release_net);
66 <<<<<<< HEAD:fs/proc/proc_net.c
67 =======
68 static struct net *get_proc_task_net(struct inode *dir)
70 struct task_struct *task;
71 struct nsproxy *ns;
72 struct net *net = NULL;
74 rcu_read_lock();
75 task = pid_task(proc_pid(dir), PIDTYPE_PID);
76 if (task != NULL) {
77 ns = task_nsproxy(task);
78 if (ns != NULL)
79 net = get_net(ns->net_ns);
81 rcu_read_unlock();
83 return net;
86 static struct dentry *proc_tgid_net_lookup(struct inode *dir,
87 struct dentry *dentry, struct nameidata *nd)
89 struct dentry *de;
90 struct net *net;
92 de = ERR_PTR(-ENOENT);
93 net = get_proc_task_net(dir);
94 if (net != NULL) {
95 de = proc_lookup_de(net->proc_net, dir, dentry);
96 put_net(net);
98 return de;
101 static int proc_tgid_net_getattr(struct vfsmount *mnt, struct dentry *dentry,
102 struct kstat *stat)
104 struct inode *inode = dentry->d_inode;
105 struct net *net;
107 net = get_proc_task_net(inode);
109 generic_fillattr(inode, stat);
111 if (net != NULL) {
112 stat->nlink = net->proc_net->nlink;
113 put_net(net);
116 return 0;
119 const struct inode_operations proc_net_inode_operations = {
120 .lookup = proc_tgid_net_lookup,
121 .getattr = proc_tgid_net_getattr,
124 static int proc_tgid_net_readdir(struct file *filp, void *dirent,
125 filldir_t filldir)
127 int ret;
128 struct net *net;
130 ret = -EINVAL;
131 net = get_proc_task_net(filp->f_path.dentry->d_inode);
132 if (net != NULL) {
133 ret = proc_readdir_de(net->proc_net, filp, dirent, filldir);
134 put_net(net);
136 return ret;
139 const struct file_operations proc_net_operations = {
140 .read = generic_read_dir,
141 .readdir = proc_tgid_net_readdir,
144 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
146 struct proc_dir_entry *proc_net_fops_create(struct net *net,
147 const char *name, mode_t mode, const struct file_operations *fops)
149 return proc_create(name, mode, net->proc_net, fops);
151 EXPORT_SYMBOL_GPL(proc_net_fops_create);
153 void proc_net_remove(struct net *net, const char *name)
155 remove_proc_entry(name, net->proc_net);
157 EXPORT_SYMBOL_GPL(proc_net_remove);
159 struct net *get_proc_net(const struct inode *inode)
161 return maybe_get_net(PDE_NET(PDE(inode)));
163 EXPORT_SYMBOL_GPL(get_proc_net);
165 <<<<<<< HEAD:fs/proc/proc_net.c
166 static struct proc_dir_entry *shadow_pde;
168 static struct proc_dir_entry *proc_net_shadow(struct task_struct *task,
169 struct proc_dir_entry *de)
171 return task->nsproxy->net_ns->proc_net;
174 =======
175 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
176 struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
177 struct proc_dir_entry *parent)
179 struct proc_dir_entry *pde;
180 pde = proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
181 if (pde != NULL)
182 pde->data = net;
183 return pde;
185 EXPORT_SYMBOL_GPL(proc_net_mkdir);
187 static __net_init int proc_net_ns_init(struct net *net)
189 <<<<<<< HEAD:fs/proc/proc_net.c
190 struct proc_dir_entry *root, *netd, *net_statd;
191 =======
192 struct proc_dir_entry *netd, *net_statd;
193 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
194 int err;
196 err = -ENOMEM;
197 <<<<<<< HEAD:fs/proc/proc_net.c
198 root = kzalloc(sizeof(*root), GFP_KERNEL);
199 if (!root)
200 =======
201 netd = kzalloc(sizeof(*netd), GFP_KERNEL);
202 if (!netd)
203 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
204 goto out;
206 <<<<<<< HEAD:fs/proc/proc_net.c
207 err = -EEXIST;
208 netd = proc_net_mkdir(net, "net", root);
209 if (!netd)
210 goto free_root;
211 =======
212 netd->data = net;
213 netd->nlink = 2;
214 netd->name = "net";
215 netd->namelen = 3;
216 netd->parent = &proc_root;
217 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
219 err = -EEXIST;
220 net_statd = proc_net_mkdir(net, "stat", netd);
221 if (!net_statd)
222 goto free_net;
224 <<<<<<< HEAD:fs/proc/proc_net.c
225 root->data = net;
227 net->proc_net_root = root;
228 =======
229 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
230 net->proc_net = netd;
231 net->proc_net_stat = net_statd;
232 <<<<<<< HEAD:fs/proc/proc_net.c
233 err = 0;
234 =======
235 return 0;
236 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
238 <<<<<<< HEAD:fs/proc/proc_net.c
239 =======
240 free_net:
241 kfree(netd);
242 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
243 out:
244 return err;
245 <<<<<<< HEAD:fs/proc/proc_net.c
246 free_net:
247 remove_proc_entry("net", root);
248 free_root:
249 kfree(root);
250 goto out;
251 =======
252 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
255 static __net_exit void proc_net_ns_exit(struct net *net)
257 remove_proc_entry("stat", net->proc_net);
258 <<<<<<< HEAD:fs/proc/proc_net.c
259 remove_proc_entry("net", net->proc_net_root);
260 kfree(net->proc_net_root);
261 =======
262 kfree(net->proc_net);
263 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
266 static struct pernet_operations __net_initdata proc_net_ns_ops = {
267 .init = proc_net_ns_init,
268 .exit = proc_net_ns_exit,
271 int __init proc_net_init(void)
273 <<<<<<< HEAD:fs/proc/proc_net.c
274 shadow_pde = proc_mkdir("net", NULL);
275 shadow_pde->shadow_proc = proc_net_shadow;
276 =======
277 proc_symlink("net", NULL, "self/net");
278 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/proc/proc_net.c
280 return register_pernet_subsys(&proc_net_ns_ops);