mfd: Fix cs5535 warning on x86-64
[firefly-linux-kernel-4.4.55.git] / fs / namei.c
index 0b14f6910fc68363cfd6da4799d9a0782b342be0..86643302079e33e010d29ae18d2fb392723c57bb 100644 (file)
@@ -479,6 +479,14 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry
        struct fs_struct *fs = current->fs;
        struct dentry *parent = nd->path.dentry;
 
+       /*
+        * It can be possible to revalidate the dentry that we started
+        * the path walk with. force_reval_path may also revalidate the
+        * dentry already committed to the nameidata.
+        */
+       if (unlikely(parent == dentry))
+               return nameidata_drop_rcu(nd);
+
        BUG_ON(!(nd->flags & LOOKUP_RCU));
        if (nd->root.mnt) {
                spin_lock(&fs->lock);
@@ -583,6 +591,13 @@ void release_open_intent(struct nameidata *nd)
                fput(nd->intent.open.file);
 }
 
+/*
+ * Call d_revalidate and handle filesystems that request rcu-walk
+ * to be dropped. This may be called and return in rcu-walk mode,
+ * regardless of success or error. If -ECHILD is returned, the caller
+ * must return -ECHILD back up the path walk stack so path walk may
+ * be restarted in ref-walk mode.
+ */
 static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
        int status;
@@ -673,6 +688,9 @@ force_reval_path(struct path *path, struct nameidata *nd)
                return 0;
 
        if (!status) {
+               /* Don't d_invalidate in rcu-walk mode */
+               if (nameidata_drop_rcu(nd))
+                       return -ECHILD;
                d_invalidate(dentry);
                status = -ESTALE;
        }
@@ -2105,11 +2123,13 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
                dir = nd->path.dentry;
        case LAST_DOT:
                if (need_reval_dot(dir)) {
-                       error = d_revalidate(nd->path.dentry, nd);
-                       if (!error)
-                               error = -ESTALE;
-                       if (error < 0)
+                       int status = d_revalidate(nd->path.dentry, nd);
+                       if (!status)
+                               status = -ESTALE;
+                       if (status < 0) {
+                               error = status;
                                goto exit;
+                       }
                }
                /* fallthrough */
        case LAST_ROOT: