aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/glops.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-11-18 08:38:48 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2009-01-05 02:39:06 -0500
commit813e0c46c9e2a0c6f0b6e774faac82afd7a2e812 (patch)
treecb09aa118f9e053f02e17f7c5ff11139e8e22244 /fs/gfs2/glops.c
parent37b2c8377c98acb60cf4d0126e385ef2153bded9 (diff)
GFS2: Fix "truncate in progress" hang
Following on from the recent clean up of gfs2_quotad, this patch moves the processing of "truncate in progress" inodes from the glock workqueue into gfs2_quotad. This fixes a hang due to the "truncate in progress" processing requiring glocks in order to complete. It might seem odd to use gfs2_quotad for this particular item, but we have to use a pre-existing thread since creating a thread implies a GFP_KERNEL memory allocation which is not allowed from the glock workqueue context. Of the existing threads, gfs2_logd and gfs2_recoverd may deadlock if used for this operation. gfs2_scand and gfs2_glockd are both scheduled for removal at some (hopefully not too distant) future point. That leaves only gfs2_quotad whose workload is generally fairly light and is easily adapted for this extra task. Also, as a result of this change, it opens the way for a future patch to make the reading of the inode's information asynchronous with respect to the glock workqueue, which is another improvement that has been on the list for some time now. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/glops.c')
-rw-r--r--fs/gfs2/glops.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 68ee66552d19..8ebff8ebae20 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -227,6 +227,7 @@ static int inode_go_demote_ok(struct gfs2_glock *gl)
227static int inode_go_lock(struct gfs2_holder *gh) 227static int inode_go_lock(struct gfs2_holder *gh)
228{ 228{
229 struct gfs2_glock *gl = gh->gh_gl; 229 struct gfs2_glock *gl = gh->gh_gl;
230 struct gfs2_sbd *sdp = gl->gl_sbd;
230 struct gfs2_inode *ip = gl->gl_object; 231 struct gfs2_inode *ip = gl->gl_object;
231 int error = 0; 232 int error = 0;
232 233
@@ -241,8 +242,14 @@ static int inode_go_lock(struct gfs2_holder *gh)
241 242
242 if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) && 243 if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) &&
243 (gl->gl_state == LM_ST_EXCLUSIVE) && 244 (gl->gl_state == LM_ST_EXCLUSIVE) &&
244 (gh->gh_state == LM_ST_EXCLUSIVE)) 245 (gh->gh_state == LM_ST_EXCLUSIVE)) {
245 error = gfs2_truncatei_resume(ip); 246 spin_lock(&sdp->sd_trunc_lock);
247 if (list_empty(&ip->i_trunc_list))
248 list_add(&sdp->sd_trunc_list, &ip->i_trunc_list);
249 spin_unlock(&sdp->sd_trunc_lock);
250 wake_up(&sdp->sd_quota_wait);
251 return 1;
252 }
246 253
247 return error; 254 return error;
248} 255}