Skip to content

Commit

Permalink
[patch 3/3] vfs: make d_path() consistent across mount operations
Browse files Browse the repository at this point in the history
The path that __d_path() computes can become slightly inconsistent when it
races with mount operations: it grabs the vfsmount_lock when traversing mount
points but immediately drops it again, only to re-grab it when it reaches the
next mount point.  The result is that the filename computed is not always
consisent, and the file may never have had that name. (This is unlikely, but
still possible.)

Fix this by grabbing the vfsmount_lock for the whole duration of
__d_path().

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Acked-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Andreas Gruenbacher authored and Al Viro committed Jun 23, 2008
1 parent f9f48ec commit be285c7
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,7 @@ char *__d_path(const struct path *path, struct path *root,
char * end = buffer+buflen;
char * retval;

spin_lock(&vfsmount_lock);
prepend(&end, &buflen, "\0", 1);
if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
(prepend(&end, &buflen, " (deleted)", 10) != 0))
Expand All @@ -1800,14 +1801,11 @@ char *__d_path(const struct path *path, struct path *root,
break;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
/* Global root? */
spin_lock(&vfsmount_lock);
if (vfsmnt->mnt_parent == vfsmnt) {
spin_unlock(&vfsmount_lock);
goto global_root;
}
dentry = vfsmnt->mnt_mountpoint;
vfsmnt = vfsmnt->mnt_parent;
spin_unlock(&vfsmount_lock);
continue;
}
parent = dentry->d_parent;
Expand All @@ -1820,6 +1818,8 @@ char *__d_path(const struct path *path, struct path *root,
dentry = parent;
}

out:
spin_unlock(&vfsmount_lock);
return retval;

global_root:
Expand All @@ -1829,9 +1829,11 @@ char *__d_path(const struct path *path, struct path *root,
goto Elong;
root->mnt = vfsmnt;
root->dentry = dentry;
return retval;
goto out;

Elong:
return ERR_PTR(-ENAMETOOLONG);
retval = ERR_PTR(-ENAMETOOLONG);
goto out;
}

/**
Expand Down

0 comments on commit be285c7

Please sign in to comment.