diff options
author | S. Wendy Cheng <wcheng@redhat.com> | 2007-01-18 16:07:03 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2007-02-05 13:36:31 -0500 |
commit | 87d21e07f3880b8d489f0b4a639deb1362101838 (patch) | |
tree | 20b41fc6dad45363b81a9e44daf5b278f532f183 /fs/gfs2/ops_inode.c | |
parent | 6c93fd1e578669364e026a0d44c669b871e2a8c4 (diff) |
[GFS2] Fix gfs2_rename deadlock
Second round of gfs2_rename lock re-ordering to allow Anaconda adding
root partition on top of gfs2. Previous to this patch the recursive
lock detector in glock.c can be triggered due to attempting to lock
the rgrp twice. This fixes it by checking to see whether the rgrp
is already locked.
This fixes Red Hat bugzilla #221237
Signed-off-by: S. Wendy Cheng <wcheng@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_inode.c')
-rw-r--r-- | fs/gfs2/ops_inode.c | 25 |
1 files changed, 3 insertions, 22 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 919e8947e710..b2a12f44f59d 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -553,7 +553,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
553 | int alloc_required; | 553 | int alloc_required; |
554 | unsigned int x; | 554 | unsigned int x; |
555 | int error; | 555 | int error; |
556 | struct gfs2_rgrpd *rgd; | ||
557 | 556 | ||
558 | if (ndentry->d_inode) { | 557 | if (ndentry->d_inode) { |
559 | nip = GFS2_I(ndentry->d_inode); | 558 | nip = GFS2_I(ndentry->d_inode); |
@@ -685,12 +684,12 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
685 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 684 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
686 | al->al_rgd->rd_ri.ri_length + | 685 | al->al_rgd->rd_ri.ri_length + |
687 | 4 * RES_DINODE + 4 * RES_LEAF + | 686 | 4 * RES_DINODE + 4 * RES_LEAF + |
688 | RES_STATFS + RES_QUOTA + 1, 0); | 687 | RES_STATFS + RES_QUOTA + 4, 0); |
689 | if (error) | 688 | if (error) |
690 | goto out_ipreserv; | 689 | goto out_ipreserv; |
691 | } else { | 690 | } else { |
692 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + | 691 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + |
693 | 5 * RES_LEAF + 1, 0); | 692 | 5 * RES_LEAF + 4, 0); |
694 | if (error) | 693 | if (error) |
695 | goto out_gunlock; | 694 | goto out_gunlock; |
696 | } | 695 | } |
@@ -704,25 +703,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
704 | error = gfs2_dir_del(ndip, &ndentry->d_name); | 703 | error = gfs2_dir_del(ndip, &ndentry->d_name); |
705 | if (error) | 704 | if (error) |
706 | goto out_end_trans; | 705 | goto out_end_trans; |
707 | error = gfs2_change_nlink_i(nip, -1); | 706 | error = gfs2_change_nlink(nip, -1); |
708 | if ((!error) && (nip->i_inode.i_nlink == 0)) { | ||
709 | error = -EIO; | ||
710 | rgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr); | ||
711 | if (rgd) { | ||
712 | struct gfs2_holder nlink_rg_gh; | ||
713 | if (rgd != nip->i_alloc.al_rgd) | ||
714 | error = gfs2_glock_nq_init( | ||
715 | rgd->rd_gl, LM_ST_EXCLUSIVE, | ||
716 | 0, &nlink_rg_gh); | ||
717 | else | ||
718 | error = 0; | ||
719 | if (!error) { | ||
720 | gfs2_unlink_di(&nip->i_inode); | ||
721 | if (rgd != nip->i_alloc.al_rgd) | ||
722 | gfs2_glock_dq_uninit(&nlink_rg_gh); | ||
723 | } | ||
724 | } | ||
725 | } | ||
726 | } | 707 | } |
727 | if (error) | 708 | if (error) |
728 | goto out_end_trans; | 709 | goto out_end_trans; |