aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/generic.c40
-rw-r--r--fs/proc/proc_net.c7
-rw-r--r--fs/proc/root.c1
-rw-r--r--include/linux/proc_fs.h10
4 files changed, 47 insertions, 11 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index b9dd3628d43..68971e66cd4 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -562,7 +562,7 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
return 0;
}
-static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
+static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
const char *name,
mode_t mode,
nlink_t nlink)
@@ -605,7 +605,7 @@ struct proc_dir_entry *proc_symlink(const char *name,
{
struct proc_dir_entry *ent;
- ent = proc_create(&parent,name,
+ ent = __proc_create(&parent, name,
(S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
if (ent) {
@@ -630,7 +630,7 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
{
struct proc_dir_entry *ent;
- ent = proc_create(&parent, name, S_IFDIR | mode, 2);
+ ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
if (ent) {
if (proc_register(parent, ent) < 0) {
kfree(ent);
@@ -664,7 +664,7 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
nlink = 1;
}
- ent = proc_create(&parent,name,mode,nlink);
+ ent = __proc_create(&parent, name, mode, nlink);
if (ent) {
if (proc_register(parent, ent) < 0) {
kfree(ent);
@@ -674,6 +674,38 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
return ent;
}
+struct proc_dir_entry *proc_create(const char *name, mode_t mode,
+ struct proc_dir_entry *parent,
+ const struct file_operations *proc_fops)
+{
+ struct proc_dir_entry *pde;
+ nlink_t nlink;
+
+ if (S_ISDIR(mode)) {
+ if ((mode & S_IALLUGO) == 0)
+ mode |= S_IRUGO | S_IXUGO;
+ nlink = 2;
+ } else {
+ if ((mode & S_IFMT) == 0)
+ mode |= S_IFREG;
+ if ((mode & S_IALLUGO) == 0)
+ mode |= S_IRUGO;
+ nlink = 1;
+ }
+
+ pde = __proc_create(&parent, name, mode, nlink);
+ if (!pde)
+ goto out;
+ pde->proc_fops = proc_fops;
+ if (proc_register(parent, pde) < 0)
+ goto out_free;
+ return pde;
+out_free:
+ kfree(pde);
+out:
+ return NULL;
+}
+
void free_proc_entry(struct proc_dir_entry *de)
{
unsigned int ino = de->low_ino;
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 4823c9677fa..14e9b5aaf86 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -67,12 +67,7 @@ EXPORT_SYMBOL_GPL(seq_release_net);
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;
+ return proc_create(name, mode, net->proc_net, fops);
}
EXPORT_SYMBOL_GPL(proc_net_fops_create);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 81f99e691f9..ef0fb57fc9e 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -232,6 +232,7 @@ void pid_ns_release_proc(struct pid_namespace *ns)
EXPORT_SYMBOL(proc_symlink);
EXPORT_SYMBOL(proc_mkdir);
EXPORT_SYMBOL(create_proc_entry);
+EXPORT_SYMBOL(proc_create);
EXPORT_SYMBOL(remove_proc_entry);
EXPORT_SYMBOL(proc_root);
EXPORT_SYMBOL(proc_root_fs);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index e4a8f9aef18..d6a4f69bdc9 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -126,6 +126,9 @@ void de_put(struct proc_dir_entry *de);
extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent);
+struct proc_dir_entry *proc_create(const char *name, mode_t mode,
+ struct proc_dir_entry *parent,
+ const struct file_operations *proc_fops);
extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
extern struct vfsmount *proc_mnt;
@@ -220,7 +223,12 @@ static inline void proc_flush_task(struct task_struct *task)
static inline struct proc_dir_entry *create_proc_entry(const char *name,
mode_t mode, struct proc_dir_entry *parent) { return NULL; }
-
+static inline struct proc_dir_entry *proc_create(const char *name,
+ mode_t mode, struct proc_dir_entry *parent,
+ const struct file_operations *proc_fops)
+{
+ return NULL;
+}
#define remove_proc_entry(name, parent) do {} while (0)
static inline struct proc_dir_entry *proc_symlink(const char *name,