[GFS2] Fix recursive locking in gfs2_permission
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>
This commit is contained in:
@@ -835,6 +835,10 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
|
|||||||
* @mask:
|
* @mask:
|
||||||
* @nd: passed from Linux VFS, ignored by us
|
* @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
|
* Returns: errno
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -843,16 +847,19 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
|
|||||||
struct gfs2_inode *ip = GFS2_I(inode);
|
struct gfs2_inode *ip = GFS2_I(inode);
|
||||||
struct gfs2_holder i_gh;
|
struct gfs2_holder i_gh;
|
||||||
int error;
|
int error;
|
||||||
|
int unlock = 0;
|
||||||
|
|
||||||
if (!test_bit(GIF_INVALID, &ip->i_flags))
|
if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
|
||||||
return generic_permission(inode, mask, gfs2_check_acl);
|
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
|
||||||
|
if (error)
|
||||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
|
return error;
|
||||||
if (!error) {
|
unlock = 1;
|
||||||
error = generic_permission(inode, mask, gfs2_check_acl_locked);
|
|
||||||
gfs2_glock_dq_uninit(&i_gh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = generic_permission(inode, mask, gfs2_check_acl_locked);
|
||||||
|
if (unlock)
|
||||||
|
gfs2_glock_dq_uninit(&i_gh);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user