diff options
| -rw-r--r-- | fs/gfs2/aops.c | 39 | ||||
| -rw-r--r-- | fs/gfs2/super.c | 39 | ||||
| -rw-r--r-- | fs/gfs2/super.h | 4 |
3 files changed, 68 insertions, 14 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; |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0a6801336470..552e321cee5e 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
| @@ -353,7 +353,7 @@ fail: | |||
| 353 | return error; | 353 | return error; |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) | 356 | void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) |
| 357 | { | 357 | { |
| 358 | const struct gfs2_statfs_change *str = buf; | 358 | const struct gfs2_statfs_change *str = buf; |
| 359 | 359 | ||
| @@ -441,6 +441,29 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
| 441 | brelse(l_bh); | 441 | brelse(l_bh); |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | ||
| 445 | struct buffer_head *l_bh) | ||
| 446 | { | ||
| 447 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 448 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | ||
| 449 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
| 450 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
| 451 | |||
| 452 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | ||
| 453 | |||
| 454 | spin_lock(&sdp->sd_statfs_spin); | ||
| 455 | m_sc->sc_total += l_sc->sc_total; | ||
| 456 | m_sc->sc_free += l_sc->sc_free; | ||
| 457 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
| 458 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
| 459 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
| 460 | 0, sizeof(struct gfs2_statfs_change)); | ||
| 461 | spin_unlock(&sdp->sd_statfs_spin); | ||
| 462 | |||
| 463 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
| 464 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
| 465 | } | ||
| 466 | |||
| 444 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) | 467 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) |
| 445 | { | 468 | { |
| 446 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | 469 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); |
| @@ -477,19 +500,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) | |||
| 477 | if (error) | 500 | if (error) |
| 478 | goto out_bh2; | 501 | goto out_bh2; |
| 479 | 502 | ||
| 480 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | 503 | update_statfs(sdp, m_bh, l_bh); |
| 481 | |||
| 482 | spin_lock(&sdp->sd_statfs_spin); | ||
| 483 | m_sc->sc_total += l_sc->sc_total; | ||
| 484 | m_sc->sc_free += l_sc->sc_free; | ||
| 485 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
| 486 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
| 487 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
| 488 | 0, sizeof(struct gfs2_statfs_change)); | ||
| 489 | spin_unlock(&sdp->sd_statfs_spin); | ||
| 490 | |||
| 491 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
| 492 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
| 493 | 504 | ||
| 494 | gfs2_trans_end(sdp); | 505 | gfs2_trans_end(sdp); |
| 495 | 506 | ||
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index b56413e3e40d..22e0417ed996 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
| @@ -40,6 +40,10 @@ extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp); | |||
| 40 | extern int gfs2_statfs_init(struct gfs2_sbd *sdp); | 40 | extern int gfs2_statfs_init(struct gfs2_sbd *sdp); |
| 41 | extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | 41 | extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, |
| 42 | s64 dinodes); | 42 | s64 dinodes); |
| 43 | extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, | ||
| 44 | const void *buf); | ||
| 45 | extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | ||
| 46 | struct buffer_head *l_bh); | ||
| 43 | extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); | 47 | extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); |
| 44 | 48 | ||
| 45 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); | 49 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); |
