diff options
-rw-r--r-- | fs/gfs2/inode.c | 23 | ||||
-rw-r--r-- | fs/gfs2/ops_inode.c | 2 |
2 files changed, 16 insertions, 9 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index f7c8d31ce41a..88fcfb4f5c4d 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -395,8 +395,10 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) | |||
395 | * @is_root: If 1, ignore the caller's permissions | 395 | * @is_root: If 1, ignore the caller's permissions |
396 | * @i_gh: An uninitialized holder for the new inode glock | 396 | * @i_gh: An uninitialized holder for the new inode glock |
397 | * | 397 | * |
398 | * There will always be a vnode (Linux VFS inode) for the d_gh inode unless | 398 | * This can be called via the VFS filldir function when NFS is doing |
399 | * @is_root is true. | 399 | * a readdirplus and the inode which its intending to stat isn't |
400 | * already in cache. In this case we must not take the directory glock | ||
401 | * again, since the readdir call will have already taken that lock. | ||
400 | * | 402 | * |
401 | * Returns: errno | 403 | * Returns: errno |
402 | */ | 404 | */ |
@@ -409,8 +411,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
409 | struct gfs2_holder d_gh; | 411 | struct gfs2_holder d_gh; |
410 | struct gfs2_inum_host inum; | 412 | struct gfs2_inum_host inum; |
411 | unsigned int type; | 413 | unsigned int type; |
412 | int error = 0; | 414 | int error; |
413 | struct inode *inode = NULL; | 415 | struct inode *inode = NULL; |
416 | int unlock = 0; | ||
414 | 417 | ||
415 | if (!name->len || name->len > GFS2_FNAMESIZE) | 418 | if (!name->len || name->len > GFS2_FNAMESIZE) |
416 | return ERR_PTR(-ENAMETOOLONG); | 419 | return ERR_PTR(-ENAMETOOLONG); |
@@ -422,9 +425,12 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
422 | return dir; | 425 | return dir; |
423 | } | 426 | } |
424 | 427 | ||
425 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); | 428 | if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) { |
426 | if (error) | 429 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); |
427 | return ERR_PTR(error); | 430 | if (error) |
431 | return ERR_PTR(error); | ||
432 | unlock = 1; | ||
433 | } | ||
428 | 434 | ||
429 | if (!is_root) { | 435 | if (!is_root) { |
430 | error = permission(dir, MAY_EXEC, NULL); | 436 | error = permission(dir, MAY_EXEC, NULL); |
@@ -439,10 +445,11 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
439 | inode = gfs2_inode_lookup(sb, &inum, type); | 445 | inode = gfs2_inode_lookup(sb, &inum, type); |
440 | 446 | ||
441 | out: | 447 | out: |
442 | gfs2_glock_dq_uninit(&d_gh); | 448 | if (unlock) |
449 | gfs2_glock_dq_uninit(&d_gh); | ||
443 | if (error == -ENOENT) | 450 | if (error == -ENOENT) |
444 | return NULL; | 451 | return NULL; |
445 | return inode; | 452 | return inode ? inode : ERR_PTR(error); |
446 | } | 453 | } |
447 | 454 | ||
448 | static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) | 455 | static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 747c7316f5cc..5591f8905cf7 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -1018,7 +1018,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | generic_fillattr(inode, stat); | 1020 | generic_fillattr(inode, stat); |
1021 | if (unlock); | 1021 | if (unlock) |
1022 | gfs2_glock_dq_uninit(&gh); | 1022 | gfs2_glock_dq_uninit(&gh); |
1023 | 1023 | ||
1024 | return 0; | 1024 | return 0; |