diff options
| -rw-r--r-- | fs/namei.c | 113 |
1 files changed, 46 insertions, 67 deletions
diff --git a/fs/namei.c b/fs/namei.c index 1d60fdf01b37..a919affd1531 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1108,6 +1108,51 @@ static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentr | |||
| 1108 | return dentry; | 1108 | return dentry; |
| 1109 | } | 1109 | } |
| 1110 | 1110 | ||
| 1111 | static struct dentry *__lookup_hash(struct qstr *name, | ||
| 1112 | struct dentry *base, struct nameidata *nd) | ||
| 1113 | { | ||
| 1114 | struct dentry *dentry; | ||
| 1115 | |||
| 1116 | /* | ||
| 1117 | * Don't bother with __d_lookup: callers are for creat as | ||
| 1118 | * well as unlink, so a lot of the time it would cost | ||
| 1119 | * a double lookup. | ||
| 1120 | */ | ||
| 1121 | dentry = d_lookup(base, name); | ||
| 1122 | |||
| 1123 | if (dentry && d_need_lookup(dentry)) { | ||
| 1124 | /* | ||
| 1125 | * __lookup_hash is called with the parent dir's i_mutex already | ||
| 1126 | * held, so we are good to go here. | ||
| 1127 | */ | ||
| 1128 | return d_inode_lookup(base, dentry, nd); | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) { | ||
| 1132 | int status = d_revalidate(dentry, nd); | ||
| 1133 | if (unlikely(status <= 0)) { | ||
| 1134 | /* | ||
| 1135 | * The dentry failed validation. | ||
| 1136 | * If d_revalidate returned 0 attempt to invalidate | ||
| 1137 | * the dentry otherwise d_revalidate is asking us | ||
| 1138 | * to return a fail status. | ||
| 1139 | */ | ||
| 1140 | if (status < 0) { | ||
| 1141 | dput(dentry); | ||
| 1142 | return ERR_PTR(status); | ||
| 1143 | } else if (!d_invalidate(dentry)) { | ||
| 1144 | dput(dentry); | ||
| 1145 | dentry = NULL; | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | if (!dentry) | ||
| 1151 | dentry = d_alloc_and_lookup(base, name, nd); | ||
| 1152 | |||
| 1153 | return dentry; | ||
| 1154 | } | ||
| 1155 | |||
| 1111 | /* | 1156 | /* |
| 1112 | * It's more convoluted than I'd like it to be, but... it's still fairly | 1157 | * It's more convoluted than I'd like it to be, but... it's still fairly |
| 1113 | * small and for now I'd prefer to have fast path as straight as possible. | 1158 | * small and for now I'd prefer to have fast path as straight as possible. |
| @@ -1173,28 +1218,7 @@ retry: | |||
| 1173 | BUG_ON(nd->inode != dir); | 1218 | BUG_ON(nd->inode != dir); |
| 1174 | 1219 | ||
| 1175 | mutex_lock(&dir->i_mutex); | 1220 | mutex_lock(&dir->i_mutex); |
| 1176 | dentry = d_lookup(parent, name); | 1221 | dentry = __lookup_hash(name, parent, nd); |
| 1177 | if (dentry && d_need_lookup(dentry)) { | ||
| 1178 | dentry = d_inode_lookup(parent, dentry, nd); | ||
| 1179 | goto l; | ||
| 1180 | } | ||
| 1181 | if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) { | ||
| 1182 | status = d_revalidate(dentry, nd); | ||
| 1183 | if (unlikely(status <= 0)) { | ||
| 1184 | if (status < 0) { | ||
| 1185 | dput(dentry); | ||
| 1186 | dentry = ERR_PTR(status); | ||
| 1187 | goto l; | ||
| 1188 | } | ||
| 1189 | if (!d_invalidate(dentry)) { | ||
| 1190 | dput(dentry); | ||
| 1191 | dentry = NULL; | ||
| 1192 | } | ||
| 1193 | } | ||
| 1194 | } | ||
| 1195 | if (!dentry) | ||
| 1196 | dentry = d_alloc_and_lookup(parent, name, nd); | ||
| 1197 | l: | ||
| 1198 | mutex_unlock(&dir->i_mutex); | 1222 | mutex_unlock(&dir->i_mutex); |
| 1199 | if (IS_ERR(dentry)) | 1223 | if (IS_ERR(dentry)) |
| 1200 | return PTR_ERR(dentry); | 1224 | return PTR_ERR(dentry); |
| @@ -1850,51 +1874,6 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
| 1850 | return err; | 1874 | return err; |
| 1851 | } | 1875 | } |
| 1852 | 1876 | ||
| 1853 | static struct dentry *__lookup_hash(struct qstr *name, | ||
| 1854 | struct dentry *base, struct nameidata *nd) | ||
| 1855 | { | ||
| 1856 | struct dentry *dentry; | ||
| 1857 | |||
| 1858 | /* | ||
| 1859 | * Don't bother with __d_lookup: callers are for creat as | ||
| 1860 | * well as unlink, so a lot of the time it would cost | ||
| 1861 | * a double lookup. | ||
| 1862 | */ | ||
| 1863 | dentry = d_lookup(base, name); | ||
| 1864 | |||
| 1865 | if (dentry && d_need_lookup(dentry)) { | ||
| 1866 | /* | ||
| 1867 | * __lookup_hash is called with the parent dir's i_mutex already | ||
| 1868 | * held, so we are good to go here. | ||
| 1869 | */ | ||
| 1870 | return d_inode_lookup(base, dentry, nd); | ||
| 1871 | } | ||
| 1872 | |||
| 1873 | if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) { | ||
| 1874 | int status = d_revalidate(dentry, nd); | ||
| 1875 | if (unlikely(status <= 0)) { | ||
| 1876 | /* | ||
| 1877 | * The dentry failed validation. | ||
| 1878 | * If d_revalidate returned 0 attempt to invalidate | ||
| 1879 | * the dentry otherwise d_revalidate is asking us | ||
| 1880 | * to return a fail status. | ||
| 1881 | */ | ||
| 1882 | if (status < 0) { | ||
| 1883 | dput(dentry); | ||
| 1884 | return ERR_PTR(status); | ||
| 1885 | } else if (!d_invalidate(dentry)) { | ||
| 1886 | dput(dentry); | ||
| 1887 | dentry = NULL; | ||
| 1888 | } | ||
| 1889 | } | ||
| 1890 | } | ||
| 1891 | |||
| 1892 | if (!dentry) | ||
| 1893 | dentry = d_alloc_and_lookup(base, name, nd); | ||
| 1894 | |||
| 1895 | return dentry; | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | /* | 1877 | /* |
| 1899 | * Restricted form of lookup. Doesn't follow links, single-component only, | 1878 | * Restricted form of lookup. Doesn't follow links, single-component only, |
| 1900 | * needs parent already locked. Doesn't follow mounts. | 1879 | * needs parent already locked. Doesn't follow mounts. |
