Skip to content

Commit

Permalink
[GFS2] Fix recursive locking in gfs2_permission
Browse files Browse the repository at this point in the history
Since gfs2_permission may be called either from the VFS (in which case
we need to obtain a shared glock) or from GFS2 (in which case we already
have a glock) we need to test to see whether or not a lock is required.
The original test was buggy due to a potential race. This one should
be safe.

This fixes Red Hat bugzilla #217129

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
  • Loading branch information
Steven Whitehouse committed Nov 30, 2006
1 parent cb4c031 commit 300c7d7
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions fs/gfs2/ops_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,10 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
* @mask:
* @nd: passed from Linux VFS, ignored by us
*
* This may be called from the VFS directly, or from within GFS2 with the
* inode locked, so we look to see if the glock is already locked and only
* lock the glock if its not already been done.
*
* Returns: errno
*/

Expand All @@ -843,15 +847,18 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder i_gh;
int error;
int unlock = 0;

if (!test_bit(GIF_INVALID, &ip->i_flags))
return generic_permission(inode, mask, gfs2_check_acl);
if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
if (error)
return error;
unlock = 1;
}

error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
if (!error) {
error = generic_permission(inode, mask, gfs2_check_acl_locked);
error = generic_permission(inode, mask, gfs2_check_acl_locked);
if (unlock)
gfs2_glock_dq_uninit(&i_gh);
}

return error;
}
Expand Down

0 comments on commit 300c7d7

Please sign in to comment.