#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)
 {
 {
        int rv;
 
-       spin_lock(&proc_subdir_lock);
+       read_lock(&proc_subdir_lock);
        rv = __xlate_proc_name(name, ret, residual);
-       spin_unlock(&proc_subdir_lock);
+       read_unlock(&proc_subdir_lock);
        return rv;
 }
 
 {
        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);
        if (de) {
                pde_get(de);
-               spin_unlock(&proc_subdir_lock);
+               read_unlock(&proc_subdir_lock);
                inode = proc_get_inode(dir->i_sb, de);
                if (!inode)
                        return ERR_PTR(-ENOMEM);
                d_add(dentry, inode);
                return NULL;
        }
-       spin_unlock(&proc_subdir_lock);
+       read_unlock(&proc_subdir_lock);
        return ERR_PTR(-ENOENT);
 }
 
        if (!dir_emit_dots(file, ctx))
                return 0;
 
-       spin_lock(&proc_subdir_lock);
+       read_lock(&proc_subdir_lock);
        de = pde_subdir_first(de);
        i = ctx->pos - 2;
        for (;;) {
                if (!de) {
-                       spin_unlock(&proc_subdir_lock);
+                       read_unlock(&proc_subdir_lock);
                        return 0;
                }
                if (!i)
        do {
                struct proc_dir_entry *next;
                pde_get(de);
-               spin_unlock(&proc_subdir_lock);
+               read_unlock(&proc_subdir_lock);
                if (!dir_emit(ctx, de->name, de->namelen,
                            de->low_ino, de->mode >> 12)) {
                        pde_put(de);
                        return 0;
                }
-               spin_lock(&proc_subdir_lock);
+               read_lock(&proc_subdir_lock);
                ctx->pos++;
                next = pde_subdir_next(de);
                pde_put(de);
                de = next;
        } while (de);
-       spin_unlock(&proc_subdir_lock);
+       read_unlock(&proc_subdir_lock);
        return 1;
 }
 
        if (ret)
                return ret;
 
-       spin_lock(&proc_subdir_lock);
+       write_lock(&proc_subdir_lock);
        dp->parent = dir;
        if (pde_subdir_insert(dir, dp) == false) {
                WARN(1, "proc_dir_entry '%s/%s' already registered\n",
                     dir->name, dp->name);
-               spin_unlock(&proc_subdir_lock);
+               write_unlock(&proc_subdir_lock);
                proc_free_inum(dp->low_ino);
                return -EEXIST;
        }
-       spin_unlock(&proc_subdir_lock);
+       write_unlock(&proc_subdir_lock);
 
        return 0;
 }
        const char *fn = name;
        unsigned int len;
 
-       spin_lock(&proc_subdir_lock);
+       write_lock(&proc_subdir_lock);
        if (__xlate_proc_name(name, &parent, &fn) != 0) {
-               spin_unlock(&proc_subdir_lock);
+               write_unlock(&proc_subdir_lock);
                return;
        }
        len = strlen(fn);
        de = pde_subdir_find(parent, fn, len);
        if (de)
                rb_erase(&de->subdir_node, &parent->subdir);
-       spin_unlock(&proc_subdir_lock);
+       write_unlock(&proc_subdir_lock);
        if (!de) {
                WARN(1, "name '%s'\n", name);
                return;
        const char *fn = name;
        unsigned int len;
 
-       spin_lock(&proc_subdir_lock);
+       write_lock(&proc_subdir_lock);
        if (__xlate_proc_name(name, &parent, &fn) != 0) {
-               spin_unlock(&proc_subdir_lock);
+               write_unlock(&proc_subdir_lock);
                return -ENOENT;
        }
        len = strlen(fn);
 
        root = pde_subdir_find(parent, fn, len);
        if (!root) {
-               spin_unlock(&proc_subdir_lock);
+               write_unlock(&proc_subdir_lock);
                return -ENOENT;
        }
        rb_erase(&root->subdir_node, &parent->subdir);
                        de = next;
                        continue;
                }
-               spin_unlock(&proc_subdir_lock);
+               write_unlock(&proc_subdir_lock);
 
                proc_entry_rundown(de);
                next = de->parent;
                        break;
                pde_put(de);
 
-               spin_lock(&proc_subdir_lock);
+               write_lock(&proc_subdir_lock);
                de = next;
        }
        pde_put(root);