diff options
Diffstat (limited to 'fs/gfs2/quota.c')
-rw-r--r-- | fs/gfs2/quota.c | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index c186857e48a8..6e546ee8f3d4 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -66,6 +66,18 @@ | |||
66 | #define QUOTA_USER 1 | 66 | #define QUOTA_USER 1 |
67 | #define QUOTA_GROUP 0 | 67 | #define QUOTA_GROUP 0 |
68 | 68 | ||
69 | struct gfs2_quota_host { | ||
70 | u64 qu_limit; | ||
71 | u64 qu_warn; | ||
72 | s64 qu_value; | ||
73 | }; | ||
74 | |||
75 | struct gfs2_quota_change_host { | ||
76 | u64 qc_change; | ||
77 | u32 qc_flags; /* GFS2_QCF_... */ | ||
78 | u32 qc_id; | ||
79 | }; | ||
80 | |||
69 | static u64 qd2offset(struct gfs2_quota_data *qd) | 81 | static u64 qd2offset(struct gfs2_quota_data *qd) |
70 | { | 82 | { |
71 | u64 offset; | 83 | u64 offset; |
@@ -561,6 +573,25 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) | |||
561 | mutex_unlock(&sdp->sd_quota_mutex); | 573 | mutex_unlock(&sdp->sd_quota_mutex); |
562 | } | 574 | } |
563 | 575 | ||
576 | static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) | ||
577 | { | ||
578 | const struct gfs2_quota *str = buf; | ||
579 | |||
580 | qu->qu_limit = be64_to_cpu(str->qu_limit); | ||
581 | qu->qu_warn = be64_to_cpu(str->qu_warn); | ||
582 | qu->qu_value = be64_to_cpu(str->qu_value); | ||
583 | } | ||
584 | |||
585 | static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) | ||
586 | { | ||
587 | struct gfs2_quota *str = buf; | ||
588 | |||
589 | str->qu_limit = cpu_to_be64(qu->qu_limit); | ||
590 | str->qu_warn = cpu_to_be64(qu->qu_warn); | ||
591 | str->qu_value = cpu_to_be64(qu->qu_value); | ||
592 | memset(&str->qu_reserved, 0, sizeof(str->qu_reserved)); | ||
593 | } | ||
594 | |||
564 | /** | 595 | /** |
565 | * gfs2_adjust_quota | 596 | * gfs2_adjust_quota |
566 | * | 597 | * |
@@ -573,12 +604,13 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
573 | struct inode *inode = &ip->i_inode; | 604 | struct inode *inode = &ip->i_inode; |
574 | struct address_space *mapping = inode->i_mapping; | 605 | struct address_space *mapping = inode->i_mapping; |
575 | unsigned long index = loc >> PAGE_CACHE_SHIFT; | 606 | unsigned long index = loc >> PAGE_CACHE_SHIFT; |
576 | unsigned offset = loc & (PAGE_CACHE_SHIFT - 1); | 607 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); |
577 | unsigned blocksize, iblock, pos; | 608 | unsigned blocksize, iblock, pos; |
578 | struct buffer_head *bh; | 609 | struct buffer_head *bh; |
579 | struct page *page; | 610 | struct page *page; |
580 | void *kaddr; | 611 | void *kaddr; |
581 | __be64 *ptr; | 612 | char *ptr; |
613 | struct gfs2_quota_host qp; | ||
582 | s64 value; | 614 | s64 value; |
583 | int err = -EIO; | 615 | int err = -EIO; |
584 | 616 | ||
@@ -620,13 +652,17 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
620 | 652 | ||
621 | kaddr = kmap_atomic(page, KM_USER0); | 653 | kaddr = kmap_atomic(page, KM_USER0); |
622 | ptr = kaddr + offset; | 654 | ptr = kaddr + offset; |
623 | value = (s64)be64_to_cpu(*ptr) + change; | 655 | gfs2_quota_in(&qp, ptr); |
624 | *ptr = cpu_to_be64(value); | 656 | qp.qu_value += change; |
657 | value = qp.qu_value; | ||
658 | gfs2_quota_out(&qp, ptr); | ||
625 | flush_dcache_page(page); | 659 | flush_dcache_page(page); |
626 | kunmap_atomic(kaddr, KM_USER0); | 660 | kunmap_atomic(kaddr, KM_USER0); |
627 | err = 0; | 661 | err = 0; |
628 | qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC); | 662 | qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC); |
629 | qd->qd_qb.qb_value = cpu_to_be64(value); | 663 | qd->qd_qb.qb_value = cpu_to_be64(value); |
664 | ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC); | ||
665 | ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value); | ||
630 | unlock: | 666 | unlock: |
631 | unlock_page(page); | 667 | unlock_page(page); |
632 | page_cache_release(page); | 668 | page_cache_release(page); |
@@ -689,7 +725,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
689 | goto out_alloc; | 725 | goto out_alloc; |
690 | 726 | ||
691 | error = gfs2_trans_begin(sdp, | 727 | error = gfs2_trans_begin(sdp, |
692 | al->al_rgd->rd_ri.ri_length + | 728 | al->al_rgd->rd_length + |
693 | num_qd * data_blocks + | 729 | num_qd * data_blocks + |
694 | nalloc * ind_blocks + | 730 | nalloc * ind_blocks + |
695 | RES_DINODE + num_qd + | 731 | RES_DINODE + num_qd + |
@@ -709,7 +745,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
709 | offset = qd2offset(qd); | 745 | offset = qd2offset(qd); |
710 | error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, | 746 | error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, |
711 | (struct gfs2_quota_data *) | 747 | (struct gfs2_quota_data *) |
712 | qd->qd_gl->gl_lvb); | 748 | qd); |
713 | if (error) | 749 | if (error) |
714 | goto out_end_trans; | 750 | goto out_end_trans; |
715 | 751 | ||
@@ -1050,6 +1086,15 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) | |||
1050 | return error; | 1086 | return error; |
1051 | } | 1087 | } |
1052 | 1088 | ||
1089 | static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf) | ||
1090 | { | ||
1091 | const struct gfs2_quota_change *str = buf; | ||
1092 | |||
1093 | qc->qc_change = be64_to_cpu(str->qc_change); | ||
1094 | qc->qc_flags = be32_to_cpu(str->qc_flags); | ||
1095 | qc->qc_id = be32_to_cpu(str->qc_id); | ||
1096 | } | ||
1097 | |||
1053 | int gfs2_quota_init(struct gfs2_sbd *sdp) | 1098 | int gfs2_quota_init(struct gfs2_sbd *sdp) |
1054 | { | 1099 | { |
1055 | struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); | 1100 | struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); |