|
@@ -395,8 +395,10 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
|
|
|
* @is_root: If 1, ignore the caller's permissions
|
|
|
* @i_gh: An uninitialized holder for the new inode glock
|
|
|
*
|
|
|
- * There will always be a vnode (Linux VFS inode) for the d_gh inode unless
|
|
|
- * @is_root is true.
|
|
|
+ * This can be called via the VFS filldir function when NFS is doing
|
|
|
+ * a readdirplus and the inode which its intending to stat isn't
|
|
|
+ * already in cache. In this case we must not take the directory glock
|
|
|
+ * again, since the readdir call will have already taken that lock.
|
|
|
*
|
|
|
* Returns: errno
|
|
|
*/
|
|
@@ -409,8 +411,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
|
|
|
struct gfs2_holder d_gh;
|
|
|
struct gfs2_inum_host inum;
|
|
|
unsigned int type;
|
|
|
- int error = 0;
|
|
|
+ int error;
|
|
|
struct inode *inode = NULL;
|
|
|
+ int unlock = 0;
|
|
|
|
|
|
if (!name->len || name->len > GFS2_FNAMESIZE)
|
|
|
return ERR_PTR(-ENAMETOOLONG);
|
|
@@ -422,9 +425,12 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
|
|
|
return dir;
|
|
|
}
|
|
|
|
|
|
- error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
|
|
|
- if (error)
|
|
|
- return ERR_PTR(error);
|
|
|
+ if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) {
|
|
|
+ error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
|
|
|
+ if (error)
|
|
|
+ return ERR_PTR(error);
|
|
|
+ unlock = 1;
|
|
|
+ }
|
|
|
|
|
|
if (!is_root) {
|
|
|
error = permission(dir, MAY_EXEC, NULL);
|
|
@@ -439,10 +445,11 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
|
|
|
inode = gfs2_inode_lookup(sb, &inum, type);
|
|
|
|
|
|
out:
|
|
|
- gfs2_glock_dq_uninit(&d_gh);
|
|
|
+ if (unlock)
|
|
|
+ gfs2_glock_dq_uninit(&d_gh);
|
|
|
if (error == -ENOENT)
|
|
|
return NULL;
|
|
|
- return inode;
|
|
|
+ return inode ? inode : ERR_PTR(error);
|
|
|
}
|
|
|
|
|
|
static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino)
|