diff options
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r-- | fs/gfs2/super.c | 134 |
1 files changed, 79 insertions, 55 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index b7beadd9ba4c..71e420989f77 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -752,51 +752,77 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
752 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 752 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
753 | struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); | 753 | struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); |
754 | struct backing_dev_info *bdi = metamapping->backing_dev_info; | 754 | struct backing_dev_info *bdi = metamapping->backing_dev_info; |
755 | struct gfs2_holder gh; | 755 | int ret = 0; |
756 | |||
757 | if (wbc->sync_mode == WB_SYNC_ALL) | ||
758 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | ||
759 | if (bdi->dirty_exceeded) | ||
760 | gfs2_ail1_flush(sdp, wbc); | ||
761 | else | ||
762 | filemap_fdatawrite(metamapping); | ||
763 | if (wbc->sync_mode == WB_SYNC_ALL) | ||
764 | ret = filemap_fdatawait(metamapping); | ||
765 | if (ret) | ||
766 | mark_inode_dirty_sync(inode); | ||
767 | return ret; | ||
768 | } | ||
769 | |||
770 | /** | ||
771 | * gfs2_dirty_inode - check for atime updates | ||
772 | * @inode: The inode in question | ||
773 | * @flags: The type of dirty | ||
774 | * | ||
775 | * Unfortunately it can be called under any combination of inode | ||
776 | * glock and transaction lock, so we have to check carefully. | ||
777 | * | ||
778 | * At the moment this deals only with atime - it should be possible | ||
779 | * to expand that role in future, once a review of the locking has | ||
780 | * been carried out. | ||
781 | */ | ||
782 | |||
783 | static void gfs2_dirty_inode(struct inode *inode, int flags) | ||
784 | { | ||
785 | struct gfs2_inode *ip = GFS2_I(inode); | ||
786 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
756 | struct buffer_head *bh; | 787 | struct buffer_head *bh; |
757 | struct timespec atime; | 788 | struct gfs2_holder gh; |
758 | struct gfs2_dinode *di; | 789 | int need_unlock = 0; |
759 | int ret = -EAGAIN; | 790 | int need_endtrans = 0; |
760 | int unlock_required = 0; | 791 | int ret; |
761 | 792 | ||
762 | /* Skip timestamp update, if this is from a memalloc */ | 793 | if (!(flags & (I_DIRTY_DATASYNC|I_DIRTY_SYNC))) |
763 | if (current->flags & PF_MEMALLOC) | 794 | return; |
764 | goto do_flush; | 795 | |
765 | if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { | 796 | if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { |
766 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 797 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
767 | if (ret) | 798 | if (ret) { |
768 | goto do_flush; | 799 | fs_err(sdp, "dirty_inode: glock %d\n", ret); |
769 | unlock_required = 1; | 800 | return; |
801 | } | ||
802 | need_unlock = 1; | ||
770 | } | 803 | } |
771 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); | 804 | |
772 | if (ret) | 805 | if (current->journal_info == NULL) { |
773 | goto do_unlock; | 806 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); |
807 | if (ret) { | ||
808 | fs_err(sdp, "dirty_inode: gfs2_trans_begin %d\n", ret); | ||
809 | goto out; | ||
810 | } | ||
811 | need_endtrans = 1; | ||
812 | } | ||
813 | |||
774 | ret = gfs2_meta_inode_buffer(ip, &bh); | 814 | ret = gfs2_meta_inode_buffer(ip, &bh); |
775 | if (ret == 0) { | 815 | if (ret == 0) { |
776 | di = (struct gfs2_dinode *)bh->b_data; | 816 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
777 | atime.tv_sec = be64_to_cpu(di->di_atime); | 817 | gfs2_dinode_out(ip, bh->b_data); |
778 | atime.tv_nsec = be32_to_cpu(di->di_atime_nsec); | ||
779 | if (timespec_compare(&inode->i_atime, &atime) > 0) { | ||
780 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | ||
781 | gfs2_dinode_out(ip, bh->b_data); | ||
782 | } | ||
783 | brelse(bh); | 818 | brelse(bh); |
784 | } | 819 | } |
785 | gfs2_trans_end(sdp); | 820 | |
786 | do_unlock: | 821 | if (need_endtrans) |
787 | if (unlock_required) | 822 | gfs2_trans_end(sdp); |
823 | out: | ||
824 | if (need_unlock) | ||
788 | gfs2_glock_dq_uninit(&gh); | 825 | gfs2_glock_dq_uninit(&gh); |
789 | do_flush: | ||
790 | if (wbc->sync_mode == WB_SYNC_ALL) | ||
791 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | ||
792 | filemap_fdatawrite(metamapping); | ||
793 | if (bdi->dirty_exceeded) | ||
794 | gfs2_ail1_flush(sdp, wbc); | ||
795 | if (!ret && (wbc->sync_mode == WB_SYNC_ALL)) | ||
796 | ret = filemap_fdatawait(metamapping); | ||
797 | if (ret) | ||
798 | mark_inode_dirty_sync(inode); | ||
799 | return ret; | ||
800 | } | 826 | } |
801 | 827 | ||
802 | /** | 828 | /** |
@@ -1011,7 +1037,6 @@ static int statfs_slow_fill(struct gfs2_rgrpd *rgd, | |||
1011 | 1037 | ||
1012 | static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) | 1038 | static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) |
1013 | { | 1039 | { |
1014 | struct gfs2_holder ri_gh; | ||
1015 | struct gfs2_rgrpd *rgd_next; | 1040 | struct gfs2_rgrpd *rgd_next; |
1016 | struct gfs2_holder *gha, *gh; | 1041 | struct gfs2_holder *gha, *gh; |
1017 | unsigned int slots = 64; | 1042 | unsigned int slots = 64; |
@@ -1024,10 +1049,6 @@ static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host | |||
1024 | if (!gha) | 1049 | if (!gha) |
1025 | return -ENOMEM; | 1050 | return -ENOMEM; |
1026 | 1051 | ||
1027 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
1028 | if (error) | ||
1029 | goto out; | ||
1030 | |||
1031 | rgd_next = gfs2_rgrpd_get_first(sdp); | 1052 | rgd_next = gfs2_rgrpd_get_first(sdp); |
1032 | 1053 | ||
1033 | for (;;) { | 1054 | for (;;) { |
@@ -1070,9 +1091,6 @@ static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host | |||
1070 | yield(); | 1091 | yield(); |
1071 | } | 1092 | } |
1072 | 1093 | ||
1073 | gfs2_glock_dq_uninit(&ri_gh); | ||
1074 | |||
1075 | out: | ||
1076 | kfree(gha); | 1094 | kfree(gha); |
1077 | return error; | 1095 | return error; |
1078 | } | 1096 | } |
@@ -1124,6 +1142,10 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
1124 | struct gfs2_statfs_change_host sc; | 1142 | struct gfs2_statfs_change_host sc; |
1125 | int error; | 1143 | int error; |
1126 | 1144 | ||
1145 | error = gfs2_rindex_update(sdp); | ||
1146 | if (error) | ||
1147 | return error; | ||
1148 | |||
1127 | if (gfs2_tune_get(sdp, gt_statfs_slow)) | 1149 | if (gfs2_tune_get(sdp, gt_statfs_slow)) |
1128 | error = gfs2_statfs_slow(sdp, &sc); | 1150 | error = gfs2_statfs_slow(sdp, &sc); |
1129 | else | 1151 | else |
@@ -1394,21 +1416,17 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip) | |||
1394 | if (error) | 1416 | if (error) |
1395 | goto out; | 1417 | goto out; |
1396 | 1418 | ||
1397 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | ||
1398 | if (error) | ||
1399 | goto out_qs; | ||
1400 | |||
1401 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); | 1419 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); |
1402 | if (!rgd) { | 1420 | if (!rgd) { |
1403 | gfs2_consist_inode(ip); | 1421 | gfs2_consist_inode(ip); |
1404 | error = -EIO; | 1422 | error = -EIO; |
1405 | goto out_rindex_relse; | 1423 | goto out_qs; |
1406 | } | 1424 | } |
1407 | 1425 | ||
1408 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, | 1426 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, |
1409 | &al->al_rgd_gh); | 1427 | &al->al_rgd_gh); |
1410 | if (error) | 1428 | if (error) |
1411 | goto out_rindex_relse; | 1429 | goto out_qs; |
1412 | 1430 | ||
1413 | error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, | 1431 | error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, |
1414 | sdp->sd_jdesc->jd_blocks); | 1432 | sdp->sd_jdesc->jd_blocks); |
@@ -1423,8 +1441,6 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip) | |||
1423 | 1441 | ||
1424 | out_rg_gunlock: | 1442 | out_rg_gunlock: |
1425 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1443 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1426 | out_rindex_relse: | ||
1427 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
1428 | out_qs: | 1444 | out_qs: |
1429 | gfs2_quota_unhold(ip); | 1445 | gfs2_quota_unhold(ip); |
1430 | out: | 1446 | out: |
@@ -1471,9 +1487,11 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1471 | goto out; | 1487 | goto out; |
1472 | } | 1488 | } |
1473 | 1489 | ||
1474 | error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED); | 1490 | if (!test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) { |
1475 | if (error) | 1491 | error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED); |
1476 | goto out_truncate; | 1492 | if (error) |
1493 | goto out_truncate; | ||
1494 | } | ||
1477 | 1495 | ||
1478 | if (test_bit(GIF_INVALID, &ip->i_flags)) { | 1496 | if (test_bit(GIF_INVALID, &ip->i_flags)) { |
1479 | error = gfs2_inode_refresh(ip); | 1497 | error = gfs2_inode_refresh(ip); |
@@ -1513,6 +1531,10 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1513 | goto out_unlock; | 1531 | goto out_unlock; |
1514 | 1532 | ||
1515 | out_truncate: | 1533 | out_truncate: |
1534 | gfs2_log_flush(sdp, ip->i_gl); | ||
1535 | write_inode_now(inode, 1); | ||
1536 | gfs2_ail_flush(ip->i_gl, 0); | ||
1537 | |||
1516 | /* Case 2 starts here */ | 1538 | /* Case 2 starts here */ |
1517 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | 1539 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
1518 | if (error) | 1540 | if (error) |
@@ -1552,6 +1574,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb) | |||
1552 | if (ip) { | 1574 | if (ip) { |
1553 | ip->i_flags = 0; | 1575 | ip->i_flags = 0; |
1554 | ip->i_gl = NULL; | 1576 | ip->i_gl = NULL; |
1577 | ip->i_rgd = NULL; | ||
1555 | } | 1578 | } |
1556 | return &ip->i_inode; | 1579 | return &ip->i_inode; |
1557 | } | 1580 | } |
@@ -1572,6 +1595,7 @@ const struct super_operations gfs2_super_ops = { | |||
1572 | .alloc_inode = gfs2_alloc_inode, | 1595 | .alloc_inode = gfs2_alloc_inode, |
1573 | .destroy_inode = gfs2_destroy_inode, | 1596 | .destroy_inode = gfs2_destroy_inode, |
1574 | .write_inode = gfs2_write_inode, | 1597 | .write_inode = gfs2_write_inode, |
1598 | .dirty_inode = gfs2_dirty_inode, | ||
1575 | .evict_inode = gfs2_evict_inode, | 1599 | .evict_inode = gfs2_evict_inode, |
1576 | .put_super = gfs2_put_super, | 1600 | .put_super = gfs2_put_super, |
1577 | .sync_fs = gfs2_sync_fs, | 1601 | .sync_fs = gfs2_sync_fs, |