|
@@ -26,7 +26,7 @@
|
|
|
|
|
|
#include "internal.h"
|
|
#include "internal.h"
|
|
|
|
|
|
-static DEFINE_SPINLOCK(proc_subdir_lock);
|
|
|
|
|
|
+static DEFINE_RWLOCK(proc_subdir_lock);
|
|
|
|
|
|
static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de)
|
|
static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de)
|
|
{
|
|
{
|
|
@@ -172,9 +172,9 @@ static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
|
|
{
|
|
{
|
|
int rv;
|
|
int rv;
|
|
|
|
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_lock(&proc_subdir_lock);
|
|
rv = __xlate_proc_name(name, ret, residual);
|
|
rv = __xlate_proc_name(name, ret, residual);
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_unlock(&proc_subdir_lock);
|
|
return rv;
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -231,11 +231,11 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
|
|
{
|
|
{
|
|
struct inode *inode;
|
|
struct inode *inode;
|
|
|
|
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_lock(&proc_subdir_lock);
|
|
de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len);
|
|
de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len);
|
|
if (de) {
|
|
if (de) {
|
|
pde_get(de);
|
|
pde_get(de);
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_unlock(&proc_subdir_lock);
|
|
inode = proc_get_inode(dir->i_sb, de);
|
|
inode = proc_get_inode(dir->i_sb, de);
|
|
if (!inode)
|
|
if (!inode)
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
@@ -243,7 +243,7 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
|
|
d_add(dentry, inode);
|
|
d_add(dentry, inode);
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_unlock(&proc_subdir_lock);
|
|
return ERR_PTR(-ENOENT);
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -270,12 +270,12 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
|
|
if (!dir_emit_dots(file, ctx))
|
|
if (!dir_emit_dots(file, ctx))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_lock(&proc_subdir_lock);
|
|
de = pde_subdir_first(de);
|
|
de = pde_subdir_first(de);
|
|
i = ctx->pos - 2;
|
|
i = ctx->pos - 2;
|
|
for (;;) {
|
|
for (;;) {
|
|
if (!de) {
|
|
if (!de) {
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_unlock(&proc_subdir_lock);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
if (!i)
|
|
if (!i)
|
|
@@ -287,19 +287,19 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
|
|
do {
|
|
do {
|
|
struct proc_dir_entry *next;
|
|
struct proc_dir_entry *next;
|
|
pde_get(de);
|
|
pde_get(de);
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_unlock(&proc_subdir_lock);
|
|
if (!dir_emit(ctx, de->name, de->namelen,
|
|
if (!dir_emit(ctx, de->name, de->namelen,
|
|
de->low_ino, de->mode >> 12)) {
|
|
de->low_ino, de->mode >> 12)) {
|
|
pde_put(de);
|
|
pde_put(de);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_lock(&proc_subdir_lock);
|
|
ctx->pos++;
|
|
ctx->pos++;
|
|
next = pde_subdir_next(de);
|
|
next = pde_subdir_next(de);
|
|
pde_put(de);
|
|
pde_put(de);
|
|
de = next;
|
|
de = next;
|
|
} while (de);
|
|
} while (de);
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ read_unlock(&proc_subdir_lock);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -338,16 +338,16 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_lock(&proc_subdir_lock);
|
|
dp->parent = dir;
|
|
dp->parent = dir;
|
|
if (pde_subdir_insert(dir, dp) == false) {
|
|
if (pde_subdir_insert(dir, dp) == false) {
|
|
WARN(1, "proc_dir_entry '%s/%s' already registered\n",
|
|
WARN(1, "proc_dir_entry '%s/%s' already registered\n",
|
|
dir->name, dp->name);
|
|
dir->name, dp->name);
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_unlock(&proc_subdir_lock);
|
|
proc_free_inum(dp->low_ino);
|
|
proc_free_inum(dp->low_ino);
|
|
return -EEXIST;
|
|
return -EEXIST;
|
|
}
|
|
}
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_unlock(&proc_subdir_lock);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -549,9 +549,9 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
|
const char *fn = name;
|
|
const char *fn = name;
|
|
unsigned int len;
|
|
unsigned int len;
|
|
|
|
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_lock(&proc_subdir_lock);
|
|
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
|
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_unlock(&proc_subdir_lock);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
len = strlen(fn);
|
|
len = strlen(fn);
|
|
@@ -559,7 +559,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
|
de = pde_subdir_find(parent, fn, len);
|
|
de = pde_subdir_find(parent, fn, len);
|
|
if (de)
|
|
if (de)
|
|
rb_erase(&de->subdir_node, &parent->subdir);
|
|
rb_erase(&de->subdir_node, &parent->subdir);
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_unlock(&proc_subdir_lock);
|
|
if (!de) {
|
|
if (!de) {
|
|
WARN(1, "name '%s'\n", name);
|
|
WARN(1, "name '%s'\n", name);
|
|
return;
|
|
return;
|
|
@@ -583,16 +583,16 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
|
|
const char *fn = name;
|
|
const char *fn = name;
|
|
unsigned int len;
|
|
unsigned int len;
|
|
|
|
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_lock(&proc_subdir_lock);
|
|
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
|
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_unlock(&proc_subdir_lock);
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
}
|
|
}
|
|
len = strlen(fn);
|
|
len = strlen(fn);
|
|
|
|
|
|
root = pde_subdir_find(parent, fn, len);
|
|
root = pde_subdir_find(parent, fn, len);
|
|
if (!root) {
|
|
if (!root) {
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_unlock(&proc_subdir_lock);
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
}
|
|
}
|
|
rb_erase(&root->subdir_node, &parent->subdir);
|
|
rb_erase(&root->subdir_node, &parent->subdir);
|
|
@@ -605,7 +605,7 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
|
|
de = next;
|
|
de = next;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- spin_unlock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_unlock(&proc_subdir_lock);
|
|
|
|
|
|
proc_entry_rundown(de);
|
|
proc_entry_rundown(de);
|
|
next = de->parent;
|
|
next = de->parent;
|
|
@@ -616,7 +616,7 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
|
|
break;
|
|
break;
|
|
pde_put(de);
|
|
pde_put(de);
|
|
|
|
|
|
- spin_lock(&proc_subdir_lock);
|
|
|
|
|
|
+ write_lock(&proc_subdir_lock);
|
|
de = next;
|
|
de = next;
|
|
}
|
|
}
|
|
pde_put(root);
|
|
pde_put(root);
|