aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2016-01-07 16:08:20 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2016-01-09 03:07:52 -0500
commitbbddca8e8fac07ece3938e03526b5d00fa791a4c (patch)
tree5fbe9fe5251f1040bb001377260c56f7330e0459 /fs/namei.c
parentdb39c16724d019029d7533561754d92bef1b389a (diff)
nfsd: don't hold i_mutex over userspace upcalls
We need information about exports when crossing mountpoints during lookup or NFSv4 readdir. If we don't already have that information cached, we may have to ask (and wait for) rpc.mountd. In both cases we currently hold the i_mutex on the parent of the directory we're asking rpc.mountd about. We've seen situations where rpc.mountd performs some operation on that directory that tries to take the i_mutex again, resulting in deadlock. With some care, we may be able to avoid that in rpc.mountd. But it seems better just to avoid holding a mutex while waiting on userspace. It appears that lookup_one_len is pretty much the only operation that needs the i_mutex. So we could just drop the i_mutex elsewhere and do something like mutex_lock() lookup_one_len() mutex_unlock() In many cases though the lookup would have been cached and not required the i_mutex, so it's more efficient to create a lookup_one_len() variant that only takes the i_mutex when necessary. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 45c702edce3c..1067f7a0287a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2272,6 +2272,8 @@ EXPORT_SYMBOL(vfs_path_lookup);
2272 * 2272 *
2273 * Note that this routine is purely a helper for filesystem usage and should 2273 * Note that this routine is purely a helper for filesystem usage and should
2274 * not be called by generic code. 2274 * not be called by generic code.
2275 *
2276 * The caller must hold base->i_mutex.
2275 */ 2277 */
2276struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) 2278struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
2277{ 2279{
@@ -2315,6 +2317,75 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
2315} 2317}
2316EXPORT_SYMBOL(lookup_one_len); 2318EXPORT_SYMBOL(lookup_one_len);
2317 2319
2320/**
2321 * lookup_one_len_unlocked - filesystem helper to lookup single pathname component
2322 * @name: pathname component to lookup
2323 * @base: base directory to lookup from
2324 * @len: maximum length @len should be interpreted to
2325 *
2326 * Note that this routine is purely a helper for filesystem usage and should
2327 * not be called by generic code.
2328 *
2329 * Unlike lookup_one_len, it should be called without the parent
2330 * i_mutex held, and will take the i_mutex itself if necessary.
2331 */
2332struct dentry *lookup_one_len_unlocked(const char *name,
2333 struct dentry *base, int len)
2334{
2335 struct qstr this;
2336 unsigned int c;
2337 int err;
2338 struct dentry *ret;
2339
2340 this.name = name;
2341 this.len = len;
2342 this.hash = full_name_hash(name, len);
2343 if (!len)
2344 return ERR_PTR(-EACCES);
2345
2346 if (unlikely(name[0] == '.')) {
2347 if (len < 2 || (len == 2 && name[1] == '.'))
2348 return ERR_PTR(-EACCES);
2349 }
2350
2351 while (len--) {
2352 c = *(const unsigned char *)name++;
2353 if (c == '/' || c == '\0')
2354 return ERR_PTR(-EACCES);
2355 }
2356 /*
2357 * See if the low-level filesystem might want
2358 * to use its own hash..
2359 */
2360 if (base->d_flags & DCACHE_OP_HASH) {
2361 int err = base->d_op->d_hash(base, &this);
2362 if (err < 0)
2363 return ERR_PTR(err);
2364 }
2365
2366 err = inode_permission(base->d_inode, MAY_EXEC);
2367 if (err)
2368 return ERR_PTR(err);
2369
2370 /*
2371 * __d_lookup() is used to try to get a quick answer and avoid the
2372 * mutex. A false-negative does no harm.
2373 */
2374 ret = __d_lookup(base, &this);
2375 if (ret && unlikely(ret->d_flags & DCACHE_OP_REVALIDATE)) {
2376 dput(ret);
2377 ret = NULL;
2378 }
2379 if (ret)
2380 return ret;
2381
2382 mutex_lock(&base->d_inode->i_mutex);
2383 ret = __lookup_hash(&this, base, 0);
2384 mutex_unlock(&base->d_inode->i_mutex);
2385 return ret;
2386}
2387EXPORT_SYMBOL(lookup_one_len_unlocked);
2388
2318int user_path_at_empty(int dfd, const char __user *name, unsigned flags, 2389int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
2319 struct path *path, int *empty) 2390 struct path *path, int *empty)
2320{ 2391{