fs: Use rename lock and RCU for multi-step operations
[pandora-kernel.git] / fs / nfs / namespace.c
index db6aa36..78c0ebb 100644 (file)
@@ -49,11 +49,17 @@ char *nfs_path(const char *base,
               const struct dentry *dentry,
               char *buffer, ssize_t buflen)
 {
-       char *end = buffer+buflen;
+       char *end;
        int namelen;
+       unsigned seq;
 
+rename_retry:
+       end = buffer+buflen;
        *--end = '\0';
        buflen--;
+
+       seq = read_seqbegin(&rename_lock);
+       rcu_read_lock();
        spin_lock(&dcache_lock);
        while (!IS_ROOT(dentry) && dentry != droot) {
                namelen = dentry->d_name.len;
@@ -66,6 +72,9 @@ char *nfs_path(const char *base,
                dentry = dentry->d_parent;
        }
        spin_unlock(&dcache_lock);
+       rcu_read_unlock();
+       if (read_seqretry(&rename_lock, seq))
+               goto rename_retry;
        if (*end != '/') {
                if (--buflen < 0)
                        goto Elong;
@@ -83,6 +92,9 @@ char *nfs_path(const char *base,
        return end;
 Elong_unlock:
        spin_unlock(&dcache_lock);
+       rcu_read_unlock();
+       if (read_seqretry(&rename_lock, seq))
+               goto rename_retry;
 Elong:
        return ERR_PTR(-ENAMETOOLONG);
 }