diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-27 12:47:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-27 12:47:46 -0400 |
commit | 546fac60739ef8d7cbf8ce0b8251a519f68b2804 (patch) | |
tree | 8ddfc9346814d3c9ae2e94365e9fd28fa7b1e02b /fs/gfs2/quota.c | |
parent | ebeaa8ddb3663b5c6cfc205605c35116381550c5 (diff) | |
parent | 39b0f1e9290880a6c905f639e7db6b646e302a4f (diff) |
Merge tag 'gfs2-merge-window' of git://git.kernel.org:/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull GFS2 updates from Bob Peterson:
"Here are the patches we've accumulated for GFS2 for the current
upstream merge window. We have a good mixture this time. Here are
some of the features:
- Fix a problem with RO mounts writing to the journal.
- Further improvements to quotas on GFS2.
- Added support for rename2 and RENAME_EXCHANGE on GFS2.
- Increase performance by making glock lru_list less of a bottleneck.
- Increase performance by avoiding unnecessary buffer_head releases.
- Increase performance by using average glock round trip time from all CPUs.
- Fixes for some compiler warnings and minor white space issues.
- Other misc bug fixes"
* tag 'gfs2-merge-window' of git://git.kernel.org:/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
GFS2: Don't brelse rgrp buffer_heads every allocation
GFS2: Don't add all glocks to the lru
gfs2: Don't support fallocate on jdata files
gfs2: s64 cast for negative quota value
gfs2: limit quota log messages
gfs2: fix quota updates on block boundaries
gfs2: fix shadow warning in gfs2_rbm_find()
gfs2: kerneldoc warning fixes
gfs2: convert simple_str to kstr
GFS2: make sure S_NOSEC flag isn't overwritten
GFS2: add support for rename2 and RENAME_EXCHANGE
gfs2: handle NULL rgd in set_rgrp_preferences
GFS2: inode.c: indent with TABs, not spaces
GFS2: mark the journal idle to fix ro mounts
GFS2: Average in only non-zero round-trip times for congestion stats
GFS2: Use average srttb value in congestion calculations
Diffstat (limited to 'fs/gfs2/quota.c')
-rw-r--r-- | fs/gfs2/quota.c | 212 |
1 files changed, 129 insertions, 83 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index e3065cb9ab08..9b61f92fcfdf 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -649,9 +649,117 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) | |||
649 | slot_hold(qd); | 649 | slot_hold(qd); |
650 | } | 650 | } |
651 | 651 | ||
652 | if (change < 0) /* Reset quiet flag if we freed some blocks */ | ||
653 | clear_bit(QDF_QMSG_QUIET, &qd->qd_flags); | ||
652 | mutex_unlock(&sdp->sd_quota_mutex); | 654 | mutex_unlock(&sdp->sd_quota_mutex); |
653 | } | 655 | } |
654 | 656 | ||
657 | static int gfs2_write_buf_to_page(struct gfs2_inode *ip, unsigned long index, | ||
658 | unsigned off, void *buf, unsigned bytes) | ||
659 | { | ||
660 | struct inode *inode = &ip->i_inode; | ||
661 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
662 | struct address_space *mapping = inode->i_mapping; | ||
663 | struct page *page; | ||
664 | struct buffer_head *bh; | ||
665 | void *kaddr; | ||
666 | u64 blk; | ||
667 | unsigned bsize = sdp->sd_sb.sb_bsize, bnum = 0, boff = 0; | ||
668 | unsigned to_write = bytes, pg_off = off; | ||
669 | int done = 0; | ||
670 | |||
671 | blk = index << (PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift); | ||
672 | boff = off % bsize; | ||
673 | |||
674 | page = find_or_create_page(mapping, index, GFP_NOFS); | ||
675 | if (!page) | ||
676 | return -ENOMEM; | ||
677 | if (!page_has_buffers(page)) | ||
678 | create_empty_buffers(page, bsize, 0); | ||
679 | |||
680 | bh = page_buffers(page); | ||
681 | while (!done) { | ||
682 | /* Find the beginning block within the page */ | ||
683 | if (pg_off >= ((bnum * bsize) + bsize)) { | ||
684 | bh = bh->b_this_page; | ||
685 | bnum++; | ||
686 | blk++; | ||
687 | continue; | ||
688 | } | ||
689 | if (!buffer_mapped(bh)) { | ||
690 | gfs2_block_map(inode, blk, bh, 1); | ||
691 | if (!buffer_mapped(bh)) | ||
692 | goto unlock_out; | ||
693 | /* If it's a newly allocated disk block, zero it */ | ||
694 | if (buffer_new(bh)) | ||
695 | zero_user(page, bnum * bsize, bh->b_size); | ||
696 | } | ||
697 | if (PageUptodate(page)) | ||
698 | set_buffer_uptodate(bh); | ||
699 | if (!buffer_uptodate(bh)) { | ||
700 | ll_rw_block(READ | REQ_META, 1, &bh); | ||
701 | wait_on_buffer(bh); | ||
702 | if (!buffer_uptodate(bh)) | ||
703 | goto unlock_out; | ||
704 | } | ||
705 | gfs2_trans_add_data(ip->i_gl, bh); | ||
706 | |||
707 | /* If we need to write to the next block as well */ | ||
708 | if (to_write > (bsize - boff)) { | ||
709 | pg_off += (bsize - boff); | ||
710 | to_write -= (bsize - boff); | ||
711 | boff = pg_off % bsize; | ||
712 | continue; | ||
713 | } | ||
714 | done = 1; | ||
715 | } | ||
716 | |||
717 | /* Write to the page, now that we have setup the buffer(s) */ | ||
718 | kaddr = kmap_atomic(page); | ||
719 | memcpy(kaddr + off, buf, bytes); | ||
720 | flush_dcache_page(page); | ||
721 | kunmap_atomic(kaddr); | ||
722 | unlock_page(page); | ||
723 | page_cache_release(page); | ||
724 | |||
725 | return 0; | ||
726 | |||
727 | unlock_out: | ||
728 | unlock_page(page); | ||
729 | page_cache_release(page); | ||
730 | return -EIO; | ||
731 | } | ||
732 | |||
733 | static int gfs2_write_disk_quota(struct gfs2_inode *ip, struct gfs2_quota *qp, | ||
734 | loff_t loc) | ||
735 | { | ||
736 | unsigned long pg_beg; | ||
737 | unsigned pg_off, nbytes, overflow = 0; | ||
738 | int pg_oflow = 0, error; | ||
739 | void *ptr; | ||
740 | |||
741 | nbytes = sizeof(struct gfs2_quota); | ||
742 | |||
743 | pg_beg = loc >> PAGE_CACHE_SHIFT; | ||
744 | pg_off = loc % PAGE_CACHE_SIZE; | ||
745 | |||
746 | /* If the quota straddles a page boundary, split the write in two */ | ||
747 | if ((pg_off + nbytes) > PAGE_CACHE_SIZE) { | ||
748 | pg_oflow = 1; | ||
749 | overflow = (pg_off + nbytes) - PAGE_CACHE_SIZE; | ||
750 | } | ||
751 | |||
752 | ptr = qp; | ||
753 | error = gfs2_write_buf_to_page(ip, pg_beg, pg_off, ptr, | ||
754 | nbytes - overflow); | ||
755 | /* If there's an overflow, write the remaining bytes to the next page */ | ||
756 | if (!error && pg_oflow) | ||
757 | error = gfs2_write_buf_to_page(ip, pg_beg + 1, 0, | ||
758 | ptr + nbytes - overflow, | ||
759 | overflow); | ||
760 | return error; | ||
761 | } | ||
762 | |||
655 | /** | 763 | /** |
656 | * gfs2_adjust_quota - adjust record of current block usage | 764 | * gfs2_adjust_quota - adjust record of current block usage |
657 | * @ip: The quota inode | 765 | * @ip: The quota inode |
@@ -672,15 +780,8 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
672 | { | 780 | { |
673 | struct inode *inode = &ip->i_inode; | 781 | struct inode *inode = &ip->i_inode; |
674 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 782 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
675 | struct address_space *mapping = inode->i_mapping; | ||
676 | unsigned long index = loc >> PAGE_CACHE_SHIFT; | ||
677 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); | ||
678 | unsigned blocksize, iblock, pos; | ||
679 | struct buffer_head *bh; | ||
680 | struct page *page; | ||
681 | void *kaddr, *ptr; | ||
682 | struct gfs2_quota q; | 783 | struct gfs2_quota q; |
683 | int err, nbytes; | 784 | int err; |
684 | u64 size; | 785 | u64 size; |
685 | 786 | ||
686 | if (gfs2_is_stuffed(ip)) { | 787 | if (gfs2_is_stuffed(ip)) { |
@@ -694,8 +795,11 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
694 | if (err < 0) | 795 | if (err < 0) |
695 | return err; | 796 | return err; |
696 | 797 | ||
798 | loc -= sizeof(q); /* gfs2_internal_read would've advanced the loc ptr */ | ||
697 | err = -EIO; | 799 | err = -EIO; |
698 | be64_add_cpu(&q.qu_value, change); | 800 | be64_add_cpu(&q.qu_value, change); |
801 | if (((s64)be64_to_cpu(q.qu_value)) < 0) | ||
802 | q.qu_value = 0; /* Never go negative on quota usage */ | ||
699 | qd->qd_qb.qb_value = q.qu_value; | 803 | qd->qd_qb.qb_value = q.qu_value; |
700 | if (fdq) { | 804 | if (fdq) { |
701 | if (fdq->d_fieldmask & QC_SPC_SOFT) { | 805 | if (fdq->d_fieldmask & QC_SPC_SOFT) { |
@@ -712,79 +816,16 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
712 | } | 816 | } |
713 | } | 817 | } |
714 | 818 | ||
715 | /* Write the quota into the quota file on disk */ | 819 | err = gfs2_write_disk_quota(ip, &q, loc); |
716 | ptr = &q; | 820 | if (!err) { |
717 | nbytes = sizeof(struct gfs2_quota); | 821 | size = loc + sizeof(struct gfs2_quota); |
718 | get_a_page: | 822 | if (size > inode->i_size) |
719 | page = find_or_create_page(mapping, index, GFP_NOFS); | 823 | i_size_write(inode, size); |
720 | if (!page) | 824 | inode->i_mtime = inode->i_atime = CURRENT_TIME; |
721 | return -ENOMEM; | 825 | mark_inode_dirty(inode); |
722 | 826 | set_bit(QDF_REFRESH, &qd->qd_flags); | |
723 | blocksize = inode->i_sb->s_blocksize; | ||
724 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); | ||
725 | |||
726 | if (!page_has_buffers(page)) | ||
727 | create_empty_buffers(page, blocksize, 0); | ||
728 | |||
729 | bh = page_buffers(page); | ||
730 | pos = blocksize; | ||
731 | while (offset >= pos) { | ||
732 | bh = bh->b_this_page; | ||
733 | iblock++; | ||
734 | pos += blocksize; | ||
735 | } | ||
736 | |||
737 | if (!buffer_mapped(bh)) { | ||
738 | gfs2_block_map(inode, iblock, bh, 1); | ||
739 | if (!buffer_mapped(bh)) | ||
740 | goto unlock_out; | ||
741 | /* If it's a newly allocated disk block for quota, zero it */ | ||
742 | if (buffer_new(bh)) | ||
743 | zero_user(page, pos - blocksize, bh->b_size); | ||
744 | } | ||
745 | |||
746 | if (PageUptodate(page)) | ||
747 | set_buffer_uptodate(bh); | ||
748 | |||
749 | if (!buffer_uptodate(bh)) { | ||
750 | ll_rw_block(READ | REQ_META, 1, &bh); | ||
751 | wait_on_buffer(bh); | ||
752 | if (!buffer_uptodate(bh)) | ||
753 | goto unlock_out; | ||
754 | } | ||
755 | |||
756 | gfs2_trans_add_data(ip->i_gl, bh); | ||
757 | |||
758 | kaddr = kmap_atomic(page); | ||
759 | if (offset + sizeof(struct gfs2_quota) > PAGE_CACHE_SIZE) | ||
760 | nbytes = PAGE_CACHE_SIZE - offset; | ||
761 | memcpy(kaddr + offset, ptr, nbytes); | ||
762 | flush_dcache_page(page); | ||
763 | kunmap_atomic(kaddr); | ||
764 | unlock_page(page); | ||
765 | page_cache_release(page); | ||
766 | |||
767 | /* If quota straddles page boundary, we need to update the rest of the | ||
768 | * quota at the beginning of the next page */ | ||
769 | if ((offset + sizeof(struct gfs2_quota)) > PAGE_CACHE_SIZE) { | ||
770 | ptr = ptr + nbytes; | ||
771 | nbytes = sizeof(struct gfs2_quota) - nbytes; | ||
772 | offset = 0; | ||
773 | index++; | ||
774 | goto get_a_page; | ||
775 | } | 827 | } |
776 | 828 | ||
777 | size = loc + sizeof(struct gfs2_quota); | ||
778 | if (size > inode->i_size) | ||
779 | i_size_write(inode, size); | ||
780 | inode->i_mtime = inode->i_atime = CURRENT_TIME; | ||
781 | mark_inode_dirty(inode); | ||
782 | set_bit(QDF_REFRESH, &qd->qd_flags); | ||
783 | return 0; | ||
784 | |||
785 | unlock_out: | ||
786 | unlock_page(page); | ||
787 | page_cache_release(page); | ||
788 | return err; | 829 | return err; |
789 | } | 830 | } |
790 | 831 | ||
@@ -1148,10 +1189,13 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid, | |||
1148 | /* If no min_target specified or we don't meet | 1189 | /* If no min_target specified or we don't meet |
1149 | * min_target, return -EDQUOT */ | 1190 | * min_target, return -EDQUOT */ |
1150 | if (!ap->min_target || ap->min_target > ap->allowed) { | 1191 | if (!ap->min_target || ap->min_target > ap->allowed) { |
1151 | print_message(qd, "exceeded"); | 1192 | if (!test_and_set_bit(QDF_QMSG_QUIET, |
1152 | quota_send_warning(qd->qd_id, | 1193 | &qd->qd_flags)) { |
1153 | sdp->sd_vfs->s_dev, | 1194 | print_message(qd, "exceeded"); |
1154 | QUOTA_NL_BHARDWARN); | 1195 | quota_send_warning(qd->qd_id, |
1196 | sdp->sd_vfs->s_dev, | ||
1197 | QUOTA_NL_BHARDWARN); | ||
1198 | } | ||
1155 | error = -EDQUOT; | 1199 | error = -EDQUOT; |
1156 | break; | 1200 | break; |
1157 | } | 1201 | } |
@@ -1648,6 +1692,8 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, | |||
1648 | 1692 | ||
1649 | /* Apply changes */ | 1693 | /* Apply changes */ |
1650 | error = gfs2_adjust_quota(ip, offset, 0, qd, fdq); | 1694 | error = gfs2_adjust_quota(ip, offset, 0, qd, fdq); |
1695 | if (!error) | ||
1696 | clear_bit(QDF_QMSG_QUIET, &qd->qd_flags); | ||
1651 | 1697 | ||
1652 | gfs2_trans_end(sdp); | 1698 | gfs2_trans_end(sdp); |
1653 | out_release: | 1699 | out_release: |