aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_inode.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-11-27 09:55:28 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-11-30 10:36:53 -0500
commit300c7d75f3a5e8edd3e390ccd56b808f3fb14e33 (patch)
tree1cc627b0e6ef37c3e72691cc75c5be5db14cac72 /fs/gfs2/ops_inode.c
parentcb4c03131836a55bf95e1c165409244ac6b4f39f (diff)
[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>
Diffstat (limited to 'fs/gfs2/ops_inode.c')
-rw-r--r--fs/gfs2/ops_inode.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index b247f25effbf..fd9fee2ceeac 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -835,6 +835,10 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
835 * @mask: 835 * @mask:
836 * @nd: passed from Linux VFS, ignored by us 836 * @nd: passed from Linux VFS, ignored by us
837 * 837 *
838 * This may be called from the VFS directly, or from within GFS2 with the
839 * inode locked, so we look to see if the glock is already locked and only
840 * lock the glock if its not already been done.
841 *
838 * Returns: errno 842 * Returns: errno
839 */ 843 */
840 844
@@ -843,15 +847,18 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
843 struct gfs2_inode *ip = GFS2_I(inode); 847 struct gfs2_inode *ip = GFS2_I(inode);
844 struct gfs2_holder i_gh; 848 struct gfs2_holder i_gh;
845 int error; 849 int error;
850 int unlock = 0;
846 851
847 if (!test_bit(GIF_INVALID, &ip->i_flags)) 852 if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
848 return generic_permission(inode, mask, gfs2_check_acl); 853 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
854 if (error)
855 return error;
856 unlock = 1;
857 }
849 858
850 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); 859 error = generic_permission(inode, mask, gfs2_check_acl_locked);
851 if (!error) { 860 if (unlock)
852 error = generic_permission(inode, mask, gfs2_check_acl_locked);
853 gfs2_glock_dq_uninit(&i_gh); 861 gfs2_glock_dq_uninit(&i_gh);
854 }
855 862
856 return error; 863 return error;
857} 864}