* [Cluster-devel] [GFS2 Patch] GFS2: stuck in inode wait, no glocks stuck [not found] <138792730.573041273614686623.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> @ 2010-05-11 21:58 ` Bob Peterson 2010-05-12 9:30 ` Steven Whitehouse 0 siblings, 1 reply; 2+ messages in thread From: Bob Peterson @ 2010-05-11 21:58 UTC (permalink / raw) To: cluster-devel.redhat.com Hi, This patch changes the lock ordering when gfs2 reclaims unlinked dinodes, thereby avoiding a livelock. Regards, Bob Peterson Red Hat GFS Signed-off-by: Bob Peterson <rpeterso@redhat.com> -- GFS2: stuck in inode wait, no glocks stuck This patch changes the lock ordering when gfs2 reclaims unlinked dinodes, thereby avoiding a livelock. rhbz#583737 diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 3739155..8bce73e 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -952,16 +952,14 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) * The inode, if one has been found, in inode. */ -static int try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, - u64 skip, struct inode **inode) +static u64 try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, + u64 skip) { u32 goal = 0, block; u64 no_addr; struct gfs2_sbd *sdp = rgd->rd_sbd; unsigned int n; - int error = 0; - *inode = NULL; for(;;) { if (goal >= rgd->rd_data) break; @@ -981,10 +979,7 @@ static int try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, if (no_addr == skip) continue; *last_unlinked = no_addr; - error = gfs2_unlinked_inode_lookup(rgd->rd_sbd->sd_vfs, - no_addr, inode); - if (*inode || error) - return error; + return no_addr; } rgd->rd_flags &= ~GFS2_RDF_CHECK; @@ -1069,11 +1064,12 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd) * Try to acquire rgrp in way which avoids contending with others. * * Returns: errno + * unlinked: the block address of an unlinked block to be reclaimed */ -static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) +static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked, + u64 *last_unlinked) { - struct inode *inode = NULL; struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_rgrpd *rgd, *begin = NULL; struct gfs2_alloc *al = ip->i_alloc; @@ -1082,6 +1078,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) int loops = 0; int error, rg_locked; + *unlinked = 0; rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); while (rgd) { @@ -1103,29 +1100,19 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) because that would require an iput which can only happen after the rgrp is unlocked. */ if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) - error = try_rgrp_unlink(rgd, last_unlinked, - ip->i_no_addr, &inode); + *unlinked = try_rgrp_unlink(rgd, last_unlinked, + ip->i_no_addr); if (!rg_locked) gfs2_glock_dq_uninit(&al->al_rgd_gh); - if (inode) { - if (error) { - if (inode->i_state & I_NEW) - iget_failed(inode); - else - iput(inode); - return ERR_PTR(error); - } - return inode; - } - if (error) - return ERR_PTR(error); + if (*unlinked) + return -EAGAIN; /* fall through */ case GLR_TRYFAILED: rgd = recent_rgrp_next(rgd); break; default: - return ERR_PTR(error); + return error; } } @@ -1148,22 +1135,12 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) if (try_rgrp_fit(rgd, al)) goto out; if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) - error = try_rgrp_unlink(rgd, last_unlinked, - ip->i_no_addr, &inode); + *unlinked = try_rgrp_unlink(rgd, last_unlinked, + ip->i_no_addr); if (!rg_locked) gfs2_glock_dq_uninit(&al->al_rgd_gh); - if (inode) { - if (error) { - if (inode->i_state & I_NEW) - iget_failed(inode); - else - iput(inode); - return ERR_PTR(error); - } - return inode; - } - if (error) - return ERR_PTR(error); + if (*unlinked) + return -EAGAIN; break; case GLR_TRYFAILED: @@ -1171,7 +1148,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) break; default: - return ERR_PTR(error); + return error; } rgd = gfs2_rgrpd_get_next(rgd); @@ -1180,7 +1157,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) if (rgd == begin) { if (++loops >= 3) - return ERR_PTR(-ENOSPC); + return -ENOSPC; if (!skipped) loops++; flags = 0; @@ -1200,7 +1177,7 @@ out: forward_rgrp_set(sdp, rgd); } - return NULL; + return 0; } /** @@ -1216,7 +1193,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) struct gfs2_alloc *al = ip->i_alloc; struct inode *inode; int error = 0; - u64 last_unlinked = NO_BLOCK; + u64 last_unlinked = NO_BLOCK, unlinked; if (gfs2_assert_warn(sdp, al->al_requested)) return -EINVAL; @@ -1232,14 +1209,19 @@ try_again: if (error) return error; - inode = get_local_rgrp(ip, &last_unlinked); - if (inode) { + error = get_local_rgrp(ip, &unlinked, &last_unlinked); + if (error) { if (ip != GFS2_I(sdp->sd_rindex)) gfs2_glock_dq_uninit(&al->al_ri_gh); - if (IS_ERR(inode)) - return PTR_ERR(inode); - iput(inode); + if (error != -EAGAIN) + return error; + error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb, + unlinked, &inode); + if (inode) + iput(inode); gfs2_log_flush(sdp, NULL); + if (error == GLR_TRYFAILED) + error = 0; goto try_again; } ^ permalink raw reply related [flat|nested] 2+ messages in thread
* [Cluster-devel] [GFS2 Patch] GFS2: stuck in inode wait, no glocks stuck 2010-05-11 21:58 ` [Cluster-devel] [GFS2 Patch] GFS2: stuck in inode wait, no glocks stuck Bob Peterson @ 2010-05-12 9:30 ` Steven Whitehouse 0 siblings, 0 replies; 2+ messages in thread From: Steven Whitehouse @ 2010-05-12 9:30 UTC (permalink / raw) To: cluster-devel.redhat.com Hi, Now in the -nmw git tree. Thanks, Steve. On Tue, 2010-05-11 at 17:58 -0400, Bob Peterson wrote: > Hi, > > This patch changes the lock ordering when gfs2 reclaims > unlinked dinodes, thereby avoiding a livelock. > > Regards, > > Bob Peterson > Red Hat GFS > > Signed-off-by: Bob Peterson <rpeterso@redhat.com> > -- > GFS2: stuck in inode wait, no glocks stuck > > This patch changes the lock ordering when gfs2 reclaims > unlinked dinodes, thereby avoiding a livelock. > > rhbz#583737 > > diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c > index 3739155..8bce73e 100644 > --- a/fs/gfs2/rgrp.c > +++ b/fs/gfs2/rgrp.c > @@ -952,16 +952,14 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) > * The inode, if one has been found, in inode. > */ > > -static int try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, > - u64 skip, struct inode **inode) > +static u64 try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, > + u64 skip) > { > u32 goal = 0, block; > u64 no_addr; > struct gfs2_sbd *sdp = rgd->rd_sbd; > unsigned int n; > - int error = 0; > > - *inode = NULL; > for(;;) { > if (goal >= rgd->rd_data) > break; > @@ -981,10 +979,7 @@ static int try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, > if (no_addr == skip) > continue; > *last_unlinked = no_addr; > - error = gfs2_unlinked_inode_lookup(rgd->rd_sbd->sd_vfs, > - no_addr, inode); > - if (*inode || error) > - return error; > + return no_addr; > } > > rgd->rd_flags &= ~GFS2_RDF_CHECK; > @@ -1069,11 +1064,12 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd) > * Try to acquire rgrp in way which avoids contending with others. > * > * Returns: errno > + * unlinked: the block address of an unlinked block to be reclaimed > */ > > -static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) > +static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked, > + u64 *last_unlinked) > { > - struct inode *inode = NULL; > struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); > struct gfs2_rgrpd *rgd, *begin = NULL; > struct gfs2_alloc *al = ip->i_alloc; > @@ -1082,6 +1078,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) > int loops = 0; > int error, rg_locked; > > + *unlinked = 0; > rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); > > while (rgd) { > @@ -1103,29 +1100,19 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) > because that would require an iput which can only > happen after the rgrp is unlocked. */ > if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) > - error = try_rgrp_unlink(rgd, last_unlinked, > - ip->i_no_addr, &inode); > + *unlinked = try_rgrp_unlink(rgd, last_unlinked, > + ip->i_no_addr); > if (!rg_locked) > gfs2_glock_dq_uninit(&al->al_rgd_gh); > - if (inode) { > - if (error) { > - if (inode->i_state & I_NEW) > - iget_failed(inode); > - else > - iput(inode); > - return ERR_PTR(error); > - } > - return inode; > - } > - if (error) > - return ERR_PTR(error); > + if (*unlinked) > + return -EAGAIN; > /* fall through */ > case GLR_TRYFAILED: > rgd = recent_rgrp_next(rgd); > break; > > default: > - return ERR_PTR(error); > + return error; > } > } > > @@ -1148,22 +1135,12 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) > if (try_rgrp_fit(rgd, al)) > goto out; > if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) > - error = try_rgrp_unlink(rgd, last_unlinked, > - ip->i_no_addr, &inode); > + *unlinked = try_rgrp_unlink(rgd, last_unlinked, > + ip->i_no_addr); > if (!rg_locked) > gfs2_glock_dq_uninit(&al->al_rgd_gh); > - if (inode) { > - if (error) { > - if (inode->i_state & I_NEW) > - iget_failed(inode); > - else > - iput(inode); > - return ERR_PTR(error); > - } > - return inode; > - } > - if (error) > - return ERR_PTR(error); > + if (*unlinked) > + return -EAGAIN; > break; > > case GLR_TRYFAILED: > @@ -1171,7 +1148,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) > break; > > default: > - return ERR_PTR(error); > + return error; > } > > rgd = gfs2_rgrpd_get_next(rgd); > @@ -1180,7 +1157,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) > > if (rgd == begin) { > if (++loops >= 3) > - return ERR_PTR(-ENOSPC); > + return -ENOSPC; > if (!skipped) > loops++; > flags = 0; > @@ -1200,7 +1177,7 @@ out: > forward_rgrp_set(sdp, rgd); > } > > - return NULL; > + return 0; > } > > /** > @@ -1216,7 +1193,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) > struct gfs2_alloc *al = ip->i_alloc; > struct inode *inode; > int error = 0; > - u64 last_unlinked = NO_BLOCK; > + u64 last_unlinked = NO_BLOCK, unlinked; > > if (gfs2_assert_warn(sdp, al->al_requested)) > return -EINVAL; > @@ -1232,14 +1209,19 @@ try_again: > if (error) > return error; > > - inode = get_local_rgrp(ip, &last_unlinked); > - if (inode) { > + error = get_local_rgrp(ip, &unlinked, &last_unlinked); > + if (error) { > if (ip != GFS2_I(sdp->sd_rindex)) > gfs2_glock_dq_uninit(&al->al_ri_gh); > - if (IS_ERR(inode)) > - return PTR_ERR(inode); > - iput(inode); > + if (error != -EAGAIN) > + return error; > + error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb, > + unlinked, &inode); > + if (inode) > + iput(inode); > gfs2_log_flush(sdp, NULL); > + if (error == GLR_TRYFAILED) > + error = 0; > goto try_again; > } > ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2010-05-12 9:30 UTC | newest] Thread overview: 2+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <138792730.573041273614686623.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> 2010-05-11 21:58 ` [Cluster-devel] [GFS2 Patch] GFS2: stuck in inode wait, no glocks stuck Bob Peterson 2010-05-12 9:30 ` Steven Whitehouse
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).