-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[NET]: Fix missed addition of fs/proc/proc_net.c
My bad. Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
David S. Miller
authored and
David S. Miller
committed
Oct 10, 2007
1 parent
678aa8e
commit 3c12afe
Showing
1 changed file
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
/* | ||
* linux/fs/proc/net.c | ||
* | ||
* Copyright (C) 2007 | ||
* | ||
* Author: Eric Biederman <ebiederm@xmission.com> | ||
* | ||
* proc net directory handling functions | ||
*/ | ||
|
||
#include <asm/uaccess.h> | ||
|
||
#include <linux/errno.h> | ||
#include <linux/time.h> | ||
#include <linux/proc_fs.h> | ||
#include <linux/stat.h> | ||
#include <linux/init.h> | ||
#include <linux/sched.h> | ||
#include <linux/module.h> | ||
#include <linux/bitops.h> | ||
#include <linux/smp_lock.h> | ||
#include <linux/mount.h> | ||
#include <linux/nsproxy.h> | ||
#include <net/net_namespace.h> | ||
|
||
#include "internal.h" | ||
|
||
|
||
struct proc_dir_entry *proc_net_create(struct net *net, | ||
const char *name, mode_t mode, get_info_t *get_info) | ||
{ | ||
return create_proc_info_entry(name,mode, net->proc_net, get_info); | ||
} | ||
|
||
struct proc_dir_entry *proc_net_fops_create(struct net *net, | ||
const char *name, mode_t mode, const struct file_operations *fops) | ||
{ | ||
struct proc_dir_entry *res; | ||
|
||
res = create_proc_entry(name, mode, net->proc_net); | ||
if (res) | ||
res->proc_fops = fops; | ||
return res; | ||
} | ||
|
||
void proc_net_remove(struct net *net, const char *name) | ||
{ | ||
remove_proc_entry(name, net->proc_net); | ||
} | ||
|
||
|
||
static struct proc_dir_entry *proc_net_shadow; | ||
|
||
static struct dentry *proc_net_shadow_dentry(struct dentry *parent, | ||
struct proc_dir_entry *de) | ||
{ | ||
struct dentry *shadow = NULL; | ||
struct inode *inode; | ||
if (!de) | ||
goto out; | ||
de_get(de); | ||
inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de); | ||
if (!inode) | ||
goto out_de_put; | ||
shadow = d_alloc_name(parent, de->name); | ||
if (!shadow) | ||
goto out_iput; | ||
shadow->d_op = parent->d_op; /* proc_dentry_operations */ | ||
d_instantiate(shadow, inode); | ||
out: | ||
return shadow; | ||
out_iput: | ||
iput(inode); | ||
out_de_put: | ||
de_put(de); | ||
goto out; | ||
} | ||
|
||
static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd) | ||
{ | ||
struct net *net = current->nsproxy->net_ns; | ||
struct dentry *shadow; | ||
shadow = proc_net_shadow_dentry(parent, net->proc_net); | ||
if (!shadow) | ||
return ERR_PTR(-ENOENT); | ||
|
||
dput(nd->dentry); | ||
/* My dentry count is 1 and that should be enough as the | ||
* shadow dentry is thrown away immediately. | ||
*/ | ||
nd->dentry = shadow; | ||
return NULL; | ||
} | ||
|
||
static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry, | ||
struct nameidata *nd) | ||
{ | ||
struct net *net = current->nsproxy->net_ns; | ||
struct dentry *shadow; | ||
|
||
shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net); | ||
if (!shadow) | ||
return ERR_PTR(-ENOENT); | ||
|
||
dput(nd->dentry); | ||
nd->dentry = shadow; | ||
|
||
return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd); | ||
} | ||
|
||
static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr) | ||
{ | ||
struct net *net = current->nsproxy->net_ns; | ||
struct dentry *shadow; | ||
int ret; | ||
|
||
shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net); | ||
if (!shadow) | ||
return -ENOENT; | ||
ret = shadow->d_inode->i_op->setattr(shadow, iattr); | ||
dput(shadow); | ||
return ret; | ||
} | ||
|
||
static const struct file_operations proc_net_dir_operations = { | ||
.read = generic_read_dir, | ||
}; | ||
|
||
static struct inode_operations proc_net_dir_inode_operations = { | ||
.follow_link = proc_net_follow_link, | ||
.lookup = proc_net_lookup, | ||
.setattr = proc_net_setattr, | ||
}; | ||
|
||
static int proc_net_ns_init(struct net *net) | ||
{ | ||
struct proc_dir_entry *root, *netd, *net_statd; | ||
int err; | ||
|
||
err = -ENOMEM; | ||
root = kzalloc(sizeof(*root), GFP_KERNEL); | ||
if (!root) | ||
goto out; | ||
|
||
err = -EEXIST; | ||
netd = proc_mkdir("net", root); | ||
if (!netd) | ||
goto free_root; | ||
|
||
err = -EEXIST; | ||
net_statd = proc_mkdir("stat", netd); | ||
if (!net_statd) | ||
goto free_net; | ||
|
||
root->data = net; | ||
netd->data = net; | ||
net_statd->data = net; | ||
|
||
net->proc_net_root = root; | ||
net->proc_net = netd; | ||
net->proc_net_stat = net_statd; | ||
err = 0; | ||
|
||
out: | ||
return err; | ||
free_net: | ||
remove_proc_entry("net", root); | ||
free_root: | ||
kfree(root); | ||
goto out; | ||
} | ||
|
||
static void proc_net_ns_exit(struct net *net) | ||
{ | ||
remove_proc_entry("stat", net->proc_net); | ||
remove_proc_entry("net", net->proc_net_root); | ||
kfree(net->proc_net_root); | ||
} | ||
|
||
struct pernet_operations proc_net_ns_ops = { | ||
.init = proc_net_ns_init, | ||
.exit = proc_net_ns_exit, | ||
}; | ||
|
||
int proc_net_init(void) | ||
{ | ||
proc_net_shadow = proc_mkdir("net", NULL); | ||
proc_net_shadow->proc_iops = &proc_net_dir_inode_operations; | ||
proc_net_shadow->proc_fops = &proc_net_dir_operations; | ||
|
||
return register_pernet_subsys(&proc_net_ns_ops); | ||
} |