Skip to content

Commit

Permalink
[GFS2] Fix recursive locking attempt with NFS
Browse files Browse the repository at this point in the history
In certain cases, its possible for NFS to call the lookup code while
holding the glock (when doing a readdirplus operation) so we need to
check for that and not try and lock the glock twice. This also fixes a
typo in a previous NFS related GFS2 patch.

Signed-off-by: Steven Whitehouse <[email protected]>
  • Loading branch information
swhiteho committed Feb 5, 2007
1 parent b790c3b commit d7c103d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
23 changes: 15 additions & 8 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/ops_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
}

generic_fillattr(inode, stat);
if (unlock);
if (unlock)
gfs2_glock_dq_uninit(&gh);

return 0;
Expand Down

0 comments on commit d7c103d

Please sign in to comment.