diff options
Diffstat (limited to 'fs/gfs2/aops.c')
| -rw-r--r-- | fs/gfs2/aops.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 03ebb439ace0..7ebae9a4ecc0 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
| @@ -624,6 +624,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 624 | { | 624 | { |
| 625 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 625 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
| 626 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); | 626 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); |
| 627 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 627 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; | 628 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; |
| 628 | int alloc_required; | 629 | int alloc_required; |
| 629 | int error = 0; | 630 | int error = 0; |
| @@ -637,6 +638,14 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 637 | error = gfs2_glock_nq(&ip->i_gh); | 638 | error = gfs2_glock_nq(&ip->i_gh); |
| 638 | if (unlikely(error)) | 639 | if (unlikely(error)) |
| 639 | goto out_uninit; | 640 | goto out_uninit; |
| 641 | if (&ip->i_inode == sdp->sd_rindex) { | ||
| 642 | error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, | ||
| 643 | GL_NOCACHE, &m_ip->i_gh); | ||
| 644 | if (unlikely(error)) { | ||
| 645 | gfs2_glock_dq(&ip->i_gh); | ||
| 646 | goto out_uninit; | ||
| 647 | } | ||
| 648 | } | ||
| 640 | 649 | ||
| 641 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); | 650 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); |
| 642 | if (error) | 651 | if (error) |
| @@ -667,6 +676,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 667 | rblocks += data_blocks ? data_blocks : 1; | 676 | rblocks += data_blocks ? data_blocks : 1; |
| 668 | if (ind_blocks || data_blocks) | 677 | if (ind_blocks || data_blocks) |
| 669 | rblocks += RES_STATFS + RES_QUOTA; | 678 | rblocks += RES_STATFS + RES_QUOTA; |
| 679 | if (&ip->i_inode == sdp->sd_rindex) | ||
| 680 | rblocks += 2 * RES_STATFS; | ||
| 670 | 681 | ||
| 671 | error = gfs2_trans_begin(sdp, rblocks, | 682 | error = gfs2_trans_begin(sdp, rblocks, |
| 672 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); | 683 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); |
| @@ -712,6 +723,10 @@ out_alloc_put: | |||
| 712 | gfs2_alloc_put(ip); | 723 | gfs2_alloc_put(ip); |
| 713 | } | 724 | } |
| 714 | out_unlock: | 725 | out_unlock: |
| 726 | if (&ip->i_inode == sdp->sd_rindex) { | ||
| 727 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 728 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 729 | } | ||
| 715 | gfs2_glock_dq(&ip->i_gh); | 730 | gfs2_glock_dq(&ip->i_gh); |
| 716 | out_uninit: | 731 | out_uninit: |
| 717 | gfs2_holder_uninit(&ip->i_gh); | 732 | gfs2_holder_uninit(&ip->i_gh); |
| @@ -725,14 +740,21 @@ out_uninit: | |||
| 725 | static void adjust_fs_space(struct inode *inode) | 740 | static void adjust_fs_space(struct inode *inode) |
| 726 | { | 741 | { |
| 727 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | 742 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; |
| 743 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 744 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | ||
| 728 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | 745 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; |
| 729 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | 746 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; |
| 747 | struct buffer_head *m_bh, *l_bh; | ||
| 730 | u64 fs_total, new_free; | 748 | u64 fs_total, new_free; |
| 731 | 749 | ||
| 732 | /* Total up the file system space, according to the latest rindex. */ | 750 | /* Total up the file system space, according to the latest rindex. */ |
| 733 | fs_total = gfs2_ri_total(sdp); | 751 | fs_total = gfs2_ri_total(sdp); |
| 752 | if (gfs2_meta_inode_buffer(m_ip, &m_bh) != 0) | ||
| 753 | return; | ||
| 734 | 754 | ||
| 735 | spin_lock(&sdp->sd_statfs_spin); | 755 | spin_lock(&sdp->sd_statfs_spin); |
| 756 | gfs2_statfs_change_in(m_sc, m_bh->b_data + | ||
| 757 | sizeof(struct gfs2_dinode)); | ||
| 736 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) | 758 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) |
| 737 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); | 759 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); |
| 738 | else | 760 | else |
| @@ -741,6 +763,13 @@ static void adjust_fs_space(struct inode *inode) | |||
| 741 | fs_warn(sdp, "File system extended by %llu blocks.\n", | 763 | fs_warn(sdp, "File system extended by %llu blocks.\n", |
| 742 | (unsigned long long)new_free); | 764 | (unsigned long long)new_free); |
| 743 | gfs2_statfs_change(sdp, new_free, new_free, 0); | 765 | gfs2_statfs_change(sdp, new_free, new_free, 0); |
| 766 | |||
| 767 | if (gfs2_meta_inode_buffer(l_ip, &l_bh) != 0) | ||
| 768 | goto out; | ||
| 769 | update_statfs(sdp, m_bh, l_bh); | ||
| 770 | brelse(l_bh); | ||
| 771 | out: | ||
| 772 | brelse(m_bh); | ||
| 744 | } | 773 | } |
| 745 | 774 | ||
| 746 | /** | 775 | /** |
| @@ -763,6 +792,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
| 763 | { | 792 | { |
| 764 | struct gfs2_inode *ip = GFS2_I(inode); | 793 | struct gfs2_inode *ip = GFS2_I(inode); |
| 765 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 794 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 795 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 766 | u64 to = pos + copied; | 796 | u64 to = pos + copied; |
| 767 | void *kaddr; | 797 | void *kaddr; |
| 768 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); | 798 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); |
| @@ -794,6 +824,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
| 794 | 824 | ||
| 795 | brelse(dibh); | 825 | brelse(dibh); |
| 796 | gfs2_trans_end(sdp); | 826 | gfs2_trans_end(sdp); |
| 827 | if (inode == sdp->sd_rindex) { | ||
| 828 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 829 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 830 | } | ||
| 797 | gfs2_glock_dq(&ip->i_gh); | 831 | gfs2_glock_dq(&ip->i_gh); |
| 798 | gfs2_holder_uninit(&ip->i_gh); | 832 | gfs2_holder_uninit(&ip->i_gh); |
| 799 | return copied; | 833 | return copied; |
| @@ -823,6 +857,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
| 823 | struct inode *inode = page->mapping->host; | 857 | struct inode *inode = page->mapping->host; |
| 824 | struct gfs2_inode *ip = GFS2_I(inode); | 858 | struct gfs2_inode *ip = GFS2_I(inode); |
| 825 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 859 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 860 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 826 | struct buffer_head *dibh; | 861 | struct buffer_head *dibh; |
| 827 | struct gfs2_alloc *al = ip->i_alloc; | 862 | struct gfs2_alloc *al = ip->i_alloc; |
| 828 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); | 863 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); |
| @@ -865,6 +900,10 @@ failed: | |||
| 865 | gfs2_quota_unlock(ip); | 900 | gfs2_quota_unlock(ip); |
| 866 | gfs2_alloc_put(ip); | 901 | gfs2_alloc_put(ip); |
| 867 | } | 902 | } |
| 903 | if (inode == sdp->sd_rindex) { | ||
| 904 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 905 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 906 | } | ||
| 868 | gfs2_glock_dq(&ip->i_gh); | 907 | gfs2_glock_dq(&ip->i_gh); |
| 869 | gfs2_holder_uninit(&ip->i_gh); | 908 | gfs2_holder_uninit(&ip->i_gh); |
| 870 | return ret; | 909 | return ret; |
