Commit be285c712bbbe5db43e503782fbef2bfeaa345f9

Authored by Andreas Gruenbacher
Committed by Al Viro
1 parent f9f48ec72b

[patch 3/3] vfs: make d_path() consistent across mount operations

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>

Showing 1 changed file with 7 additions and 5 deletions Side-by-side Diff

... ... @@ -1782,6 +1782,7 @@
1782 1782 char * end = buffer+buflen;
1783 1783 char * retval;
1784 1784  
  1785 + spin_lock(&vfsmount_lock);
1785 1786 prepend(&end, &buflen, "\0", 1);
1786 1787 if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
1787 1788 (prepend(&end, &buflen, " (deleted)", 10) != 0))
1788 1789  
1789 1790  
... ... @@ -1800,14 +1801,11 @@
1800 1801 break;
1801 1802 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
1802 1803 /* Global root? */
1803   - spin_lock(&vfsmount_lock);
1804 1804 if (vfsmnt->mnt_parent == vfsmnt) {
1805   - spin_unlock(&vfsmount_lock);
1806 1805 goto global_root;
1807 1806 }
1808 1807 dentry = vfsmnt->mnt_mountpoint;
1809 1808 vfsmnt = vfsmnt->mnt_parent;
1810   - spin_unlock(&vfsmount_lock);
1811 1809 continue;
1812 1810 }
1813 1811 parent = dentry->d_parent;
... ... @@ -1820,6 +1818,8 @@
1820 1818 dentry = parent;
1821 1819 }
1822 1820  
  1821 +out:
  1822 + spin_unlock(&vfsmount_lock);
1823 1823 return retval;
1824 1824  
1825 1825 global_root:
1826 1826  
... ... @@ -1829,9 +1829,11 @@
1829 1829 goto Elong;
1830 1830 root->mnt = vfsmnt;
1831 1831 root->dentry = dentry;
1832   - return retval;
  1832 + goto out;
  1833 +
1833 1834 Elong:
1834   - return ERR_PTR(-ENAMETOOLONG);
  1835 + retval = ERR_PTR(-ENAMETOOLONG);
  1836 + goto out;
1835 1837 }
1836 1838  
1837 1839 /**