mirror of https://gitee.com/openkylin/linux.git
proc: do translation + unlink atomically at remove_proc_entry()
remove_proc_entry() does lock lookup parent unlock lock unlink proc entry from lists unlock which can be made bit more correct by doing parent translation + unlink without dropping lock. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
5748150eab
commit
e17a5765f2
|
@ -291,19 +291,17 @@ static const struct inode_operations proc_file_inode_operations = {
|
|||
* returns the struct proc_dir_entry for "/proc/tty/driver", and
|
||||
* returns "serial" in residual.
|
||||
*/
|
||||
static int xlate_proc_name(const char *name,
|
||||
struct proc_dir_entry **ret, const char **residual)
|
||||
static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
|
||||
const char **residual)
|
||||
{
|
||||
const char *cp = name, *next;
|
||||
struct proc_dir_entry *de;
|
||||
int len;
|
||||
int rtn = 0;
|
||||
|
||||
de = *ret;
|
||||
if (!de)
|
||||
de = &proc_root;
|
||||
|
||||
spin_lock(&proc_subdir_lock);
|
||||
while (1) {
|
||||
next = strchr(cp, '/');
|
||||
if (!next)
|
||||
|
@ -314,17 +312,24 @@ static int xlate_proc_name(const char *name,
|
|||
if (proc_match(len, cp, de))
|
||||
break;
|
||||
}
|
||||
if (!de) {
|
||||
rtn = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
if (!de)
|
||||
return -ENOENT;
|
||||
cp += len + 1;
|
||||
}
|
||||
*residual = cp;
|
||||
*ret = de;
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
|
||||
const char **residual)
|
||||
{
|
||||
int rv;
|
||||
|
||||
spin_lock(&proc_subdir_lock);
|
||||
rv = __xlate_proc_name(name, ret, residual);
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
return rtn;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static DEFINE_IDA(proc_inum_ida);
|
||||
|
@ -797,11 +802,13 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
|||
const char *fn = name;
|
||||
int len;
|
||||
|
||||
if (xlate_proc_name(name, &parent, &fn) != 0)
|
||||
spin_lock(&proc_subdir_lock);
|
||||
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
return;
|
||||
}
|
||||
len = strlen(fn);
|
||||
|
||||
spin_lock(&proc_subdir_lock);
|
||||
for (p = &parent->subdir; *p; p=&(*p)->next ) {
|
||||
if (proc_match(len, fn, *p)) {
|
||||
de = *p;
|
||||
|
|
Loading…
Reference in New Issue