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 | |
| 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>
| -rw-r--r-- | fs/gfs2/ops_address.c | 3 | ||||
| -rw-r--r-- | fs/gfs2/quota.c | 71 |
2 files changed, 31 insertions, 43 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 2483d8741060..e72fd47d71eb 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/gfs2_ondisk.h> | 21 | #include <linux/gfs2_ondisk.h> |
| 22 | #include <linux/lm_interface.h> | 22 | #include <linux/lm_interface.h> |
| 23 | #include <linux/backing-dev.h> | 23 | #include <linux/backing-dev.h> |
| 24 | #include <linux/pagevec.h> | ||
| 25 | 24 | ||
| 26 | #include "gfs2.h" | 25 | #include "gfs2.h" |
| 27 | #include "incore.h" | 26 | #include "incore.h" |
| @@ -278,7 +277,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping, | |||
| 278 | int i; | 277 | int i; |
| 279 | int ret; | 278 | int ret; |
| 280 | 279 | ||
| 281 | ret = gfs2_trans_begin(sdp, nrblocks, 0); | 280 | ret = gfs2_trans_begin(sdp, nrblocks, nrblocks); |
| 282 | if (ret < 0) | 281 | if (ret < 0) |
| 283 | return ret; | 282 | return ret; |
| 284 | 283 | ||
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: |
