diff options
author | Abhijith Das <adas@redhat.com> | 2008-03-06 18:43:52 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2008-03-31 05:41:30 -0400 |
commit | 20b95bf2c4c5c28e093aa42699e67829b6cd7fd0 (patch) | |
tree | e611fb6ee336f37609a5881a0846ffdf80bf58dc /fs/gfs2/quota.c | |
parent | 182fe5abd8ebbb3a00c1be91f44e4783e139918c (diff) |
[GFS2] gfs2_adjust_quota has broken unstuffing code
This patch combines the 2 patches in bug 434736 to correct the lock
ordering in the unstuffing of the quota inode in gfs2_adjust_quota and
adjusting the number of revokes in gfs2_write_jdata_pagevec
Signed-off-by: Abhijith Das <adas@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/quota.c')
-rw-r--r-- | fs/gfs2/quota.c | 71 |
1 files changed, 30 insertions, 41 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 636bccfd2bcf..c71f781db5d7 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -616,17 +616,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
616 | s64 value; | 616 | s64 value; |
617 | int err = -EIO; | 617 | int err = -EIO; |
618 | 618 | ||
619 | if (gfs2_is_stuffed(ip)) { | 619 | if (gfs2_is_stuffed(ip)) |
620 | struct gfs2_alloc *al = gfs2_alloc_get(ip); | ||
621 | if (!al) | ||
622 | return -ENOMEM; | ||
623 | /* just request 1 blk */ | ||
624 | al->al_requested = 1; | ||
625 | gfs2_inplace_reserve(ip); | ||
626 | gfs2_unstuff_dinode(ip, NULL); | 620 | gfs2_unstuff_dinode(ip, NULL); |
627 | gfs2_inplace_release(ip); | 621 | |
628 | gfs2_alloc_put(ip); | ||
629 | } | ||
630 | page = grab_cache_page(mapping, index); | 622 | page = grab_cache_page(mapping, index); |
631 | if (!page) | 623 | if (!page) |
632 | return -ENOMEM; | 624 | return -ENOMEM; |
@@ -691,7 +683,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
691 | unsigned int qx, x; | 683 | unsigned int qx, x; |
692 | struct gfs2_quota_data *qd; | 684 | struct gfs2_quota_data *qd; |
693 | loff_t offset; | 685 | loff_t offset; |
694 | unsigned int nalloc = 0; | 686 | unsigned int nalloc = 0, blocks; |
695 | struct gfs2_alloc *al = NULL; | 687 | struct gfs2_alloc *al = NULL; |
696 | int error; | 688 | int error; |
697 | 689 | ||
@@ -728,34 +720,33 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
728 | nalloc++; | 720 | nalloc++; |
729 | } | 721 | } |
730 | 722 | ||
731 | if (nalloc) { | 723 | al = gfs2_alloc_get(ip); |
732 | al = gfs2_alloc_get(ip); | 724 | if (!al) { |
733 | if (!al) { | 725 | error = -ENOMEM; |
734 | error = -ENOMEM; | 726 | goto out_gunlock; |
735 | goto out_gunlock; | 727 | } |
736 | } | 728 | /* |
729 | * 1 blk for unstuffing inode if stuffed. We add this extra | ||
730 | * block to the reservation unconditionally. If the inode | ||
731 | * doesn't need unstuffing, the block will be released to the | ||
732 | * rgrp since it won't be allocated during the transaction | ||
733 | */ | ||
734 | al->al_requested = 1; | ||
735 | /* +1 in the end for block requested above for unstuffing */ | ||
736 | blocks = num_qd * data_blocks + RES_DINODE + num_qd + 1; | ||
737 | 737 | ||
738 | al->al_requested = nalloc * (data_blocks + ind_blocks); | 738 | if (nalloc) |
739 | al->al_requested += nalloc * (data_blocks + ind_blocks); | ||
740 | error = gfs2_inplace_reserve(ip); | ||
741 | if (error) | ||
742 | goto out_alloc; | ||
739 | 743 | ||
740 | error = gfs2_inplace_reserve(ip); | 744 | if (nalloc) |
741 | if (error) | 745 | blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS; |
742 | goto out_alloc; | 746 | |
743 | 747 | error = gfs2_trans_begin(sdp, blocks, 0); | |
744 | error = gfs2_trans_begin(sdp, | 748 | if (error) |
745 | al->al_rgd->rd_length + | 749 | goto out_ipres; |
746 | num_qd * data_blocks + | ||
747 | nalloc * ind_blocks + | ||
748 | RES_DINODE + num_qd + | ||
749 | RES_STATFS, 0); | ||
750 | if (error) | ||
751 | goto out_ipres; | ||
752 | } else { | ||
753 | error = gfs2_trans_begin(sdp, | ||
754 | num_qd * data_blocks + | ||
755 | RES_DINODE + num_qd, 0); | ||
756 | if (error) | ||
757 | goto out_gunlock; | ||
758 | } | ||
759 | 750 | ||
760 | for (x = 0; x < num_qd; x++) { | 751 | for (x = 0; x < num_qd; x++) { |
761 | qd = qda[x]; | 752 | qd = qda[x]; |
@@ -774,11 +765,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
774 | out_end_trans: | 765 | out_end_trans: |
775 | gfs2_trans_end(sdp); | 766 | gfs2_trans_end(sdp); |
776 | out_ipres: | 767 | out_ipres: |
777 | if (nalloc) | 768 | gfs2_inplace_release(ip); |
778 | gfs2_inplace_release(ip); | ||
779 | out_alloc: | 769 | out_alloc: |
780 | if (nalloc) | 770 | gfs2_alloc_put(ip); |
781 | gfs2_alloc_put(ip); | ||
782 | out_gunlock: | 771 | out_gunlock: |
783 | gfs2_glock_dq_uninit(&i_gh); | 772 | gfs2_glock_dq_uninit(&i_gh); |
784 | out: | 773 | out: |