Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 300c7d75 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

[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: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent cb4c0313
Loading
Loading
Loading
Loading
+13 −6
Original line number Original line Diff line number Diff line
@@ -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,15 +847,18 @@ 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);
		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
	if (!error) {
		if (error)
			return error;
		unlock = 1;
	}

	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);
		gfs2_glock_dq_uninit(&i_gh);
	}


	return error;
	return error;
}
}