[NETNS]: Fix export symbols.
[powerpc.git] / fs / proc / proc_net.c
1 /*
2  *  linux/fs/proc/net.c
3  *
4  *  Copyright (C) 2007
5  *
6  *  Author: Eric Biederman <ebiederm@xmission.com>
7  *
8  *  proc net directory handling functions
9  */
10
11 #include <asm/uaccess.h>
12
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
26 #include "internal.h"
27
28
29 struct proc_dir_entry *proc_net_create(struct net *net,
30         const char *name, mode_t mode, get_info_t *get_info)
31 {
32         return create_proc_info_entry(name,mode, net->proc_net, get_info);
33 }
34 EXPORT_SYMBOL_GPL(proc_net_create);
35
36 struct proc_dir_entry *proc_net_fops_create(struct net *net,
37         const char *name, mode_t mode, const struct file_operations *fops)
38 {
39         struct proc_dir_entry *res;
40
41         res = create_proc_entry(name, mode, net->proc_net);
42         if (res)
43                 res->proc_fops = fops;
44         return res;
45 }
46 EXPORT_SYMBOL_GPL(proc_net_fops_create);
47
48 void proc_net_remove(struct net *net, const char *name)
49 {
50         remove_proc_entry(name, net->proc_net);
51 }
52 EXPORT_SYMBOL_GPL(proc_net_remove);
53
54 static struct proc_dir_entry *proc_net_shadow;
55
56 static struct dentry *proc_net_shadow_dentry(struct dentry *parent,
57                                                 struct proc_dir_entry *de)
58 {
59         struct dentry *shadow = NULL;
60         struct inode *inode;
61         if (!de)
62                 goto out;
63         de_get(de);
64         inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de);
65         if (!inode)
66                 goto out_de_put;
67         shadow = d_alloc_name(parent, de->name);
68         if (!shadow)
69                 goto out_iput;
70         shadow->d_op = parent->d_op; /* proc_dentry_operations */
71         d_instantiate(shadow, inode);
72 out:
73         return shadow;
74 out_iput:
75         iput(inode);
76 out_de_put:
77         de_put(de);
78         goto out;
79 }
80
81 static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd)
82 {
83         struct net *net = current->nsproxy->net_ns;
84         struct dentry *shadow;
85         shadow = proc_net_shadow_dentry(parent, net->proc_net);
86         if (!shadow)
87                 return ERR_PTR(-ENOENT);
88
89         dput(nd->dentry);
90         /* My dentry count is 1 and that should be enough as the
91          * shadow dentry is thrown away immediately.
92          */
93         nd->dentry = shadow;
94         return NULL;
95 }
96
97 static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
98                                       struct nameidata *nd)
99 {
100         struct net *net = current->nsproxy->net_ns;
101         struct dentry *shadow;
102
103         shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net);
104         if (!shadow)
105                 return ERR_PTR(-ENOENT);
106
107         dput(nd->dentry);
108         nd->dentry = shadow;
109
110         return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd);
111 }
112
113 static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
114 {
115         struct net *net = current->nsproxy->net_ns;
116         struct dentry *shadow;
117         int ret;
118
119         shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net);
120         if (!shadow)
121                 return -ENOENT;
122         ret = shadow->d_inode->i_op->setattr(shadow, iattr);
123         dput(shadow);
124         return ret;
125 }
126
127 static const struct file_operations proc_net_dir_operations = {
128         .read                   = generic_read_dir,
129 };
130
131 static struct inode_operations proc_net_dir_inode_operations = {
132         .follow_link    = proc_net_follow_link,
133         .lookup         = proc_net_lookup,
134         .setattr        = proc_net_setattr,
135 };
136
137 static int proc_net_ns_init(struct net *net)
138 {
139         struct proc_dir_entry *root, *netd, *net_statd;
140         int err;
141
142         err = -ENOMEM;
143         root = kzalloc(sizeof(*root), GFP_KERNEL);
144         if (!root)
145                 goto out;
146
147         err = -EEXIST;
148         netd = proc_mkdir("net", root);
149         if (!netd)
150                 goto free_root;
151
152         err = -EEXIST;
153         net_statd = proc_mkdir("stat", netd);
154         if (!net_statd)
155                 goto free_net;
156
157         root->data = net;
158         netd->data = net;
159         net_statd->data = net;
160
161         net->proc_net_root = root;
162         net->proc_net = netd;
163         net->proc_net_stat = net_statd;
164         err = 0;
165
166 out:
167         return err;
168 free_net:
169         remove_proc_entry("net", root);
170 free_root:
171         kfree(root);
172         goto out;
173 }
174
175 static void proc_net_ns_exit(struct net *net)
176 {
177         remove_proc_entry("stat", net->proc_net);
178         remove_proc_entry("net", net->proc_net_root);
179         kfree(net->proc_net_root);
180 }
181
182 struct pernet_operations proc_net_ns_ops = {
183         .init = proc_net_ns_init,
184         .exit = proc_net_ns_exit,
185 };
186
187 int proc_net_init(void)
188 {
189         proc_net_shadow = proc_mkdir("net", NULL);
190         proc_net_shadow->proc_iops = &proc_net_dir_inode_operations;
191         proc_net_shadow->proc_fops = &proc_net_dir_operations;
192
193         return register_pernet_subsys(&proc_net_ns_ops);
194 }