diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 79 |
1 files changed, 28 insertions, 51 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index b572f7e840e0..578f3f59b789 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -538,9 +538,8 @@ xfs_readlink_bmap( | |||
538 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); | 538 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); |
539 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); | 539 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); |
540 | 540 | ||
541 | bp = xfs_buf_read_flags(mp->m_ddev_targp, d, BTOBB(byte_cnt), | 541 | bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), |
542 | XBF_LOCK | XBF_MAPPED | | 542 | XBF_LOCK | XBF_MAPPED | XBF_DONT_BLOCK); |
543 | XBF_DONT_BLOCK); | ||
544 | error = XFS_BUF_GETERROR(bp); | 543 | error = XFS_BUF_GETERROR(bp); |
545 | if (error) { | 544 | if (error) { |
546 | xfs_ioerror_alert("xfs_readlink", | 545 | xfs_ioerror_alert("xfs_readlink", |
@@ -709,6 +708,11 @@ xfs_fsync( | |||
709 | } | 708 | } |
710 | 709 | ||
711 | /* | 710 | /* |
711 | * Flags for xfs_free_eofblocks | ||
712 | */ | ||
713 | #define XFS_FREE_EOF_TRYLOCK (1<<0) | ||
714 | |||
715 | /* | ||
712 | * This is called by xfs_inactive to free any blocks beyond eof | 716 | * This is called by xfs_inactive to free any blocks beyond eof |
713 | * when the link count isn't zero and by xfs_dm_punch_hole() when | 717 | * when the link count isn't zero and by xfs_dm_punch_hole() when |
714 | * punching a hole to EOF. | 718 | * punching a hole to EOF. |
@@ -726,7 +730,6 @@ xfs_free_eofblocks( | |||
726 | xfs_filblks_t map_len; | 730 | xfs_filblks_t map_len; |
727 | int nimaps; | 731 | int nimaps; |
728 | xfs_bmbt_irec_t imap; | 732 | xfs_bmbt_irec_t imap; |
729 | int use_iolock = (flags & XFS_FREE_EOF_LOCK); | ||
730 | 733 | ||
731 | /* | 734 | /* |
732 | * Figure out if there are any blocks beyond the end | 735 | * Figure out if there are any blocks beyond the end |
@@ -768,14 +771,19 @@ xfs_free_eofblocks( | |||
768 | * cache and we can't | 771 | * cache and we can't |
769 | * do that within a transaction. | 772 | * do that within a transaction. |
770 | */ | 773 | */ |
771 | if (use_iolock) | 774 | if (flags & XFS_FREE_EOF_TRYLOCK) { |
775 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) { | ||
776 | xfs_trans_cancel(tp, 0); | ||
777 | return 0; | ||
778 | } | ||
779 | } else { | ||
772 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 780 | xfs_ilock(ip, XFS_IOLOCK_EXCL); |
781 | } | ||
773 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, | 782 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, |
774 | ip->i_size); | 783 | ip->i_size); |
775 | if (error) { | 784 | if (error) { |
776 | xfs_trans_cancel(tp, 0); | 785 | xfs_trans_cancel(tp, 0); |
777 | if (use_iolock) | 786 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
778 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
779 | return error; | 787 | return error; |
780 | } | 788 | } |
781 | 789 | ||
@@ -812,8 +820,7 @@ xfs_free_eofblocks( | |||
812 | error = xfs_trans_commit(tp, | 820 | error = xfs_trans_commit(tp, |
813 | XFS_TRANS_RELEASE_LOG_RES); | 821 | XFS_TRANS_RELEASE_LOG_RES); |
814 | } | 822 | } |
815 | xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL) | 823 | xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL); |
816 | : XFS_ILOCK_EXCL)); | ||
817 | } | 824 | } |
818 | return error; | 825 | return error; |
819 | } | 826 | } |
@@ -1113,7 +1120,17 @@ xfs_release( | |||
1113 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && | 1120 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && |
1114 | (!(ip->i_d.di_flags & | 1121 | (!(ip->i_d.di_flags & |
1115 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { | 1122 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { |
1116 | error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); | 1123 | |
1124 | /* | ||
1125 | * If we can't get the iolock just skip truncating | ||
1126 | * the blocks past EOF because we could deadlock | ||
1127 | * with the mmap_sem otherwise. We'll get another | ||
1128 | * chance to drop them once the last reference to | ||
1129 | * the inode is dropped, so we'll never leak blocks | ||
1130 | * permanently. | ||
1131 | */ | ||
1132 | error = xfs_free_eofblocks(mp, ip, | ||
1133 | XFS_FREE_EOF_TRYLOCK); | ||
1117 | if (error) | 1134 | if (error) |
1118 | return error; | 1135 | return error; |
1119 | } | 1136 | } |
@@ -1184,7 +1201,7 @@ xfs_inactive( | |||
1184 | (!(ip->i_d.di_flags & | 1201 | (!(ip->i_d.di_flags & |
1185 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || | 1202 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || |
1186 | (ip->i_delayed_blks != 0)))) { | 1203 | (ip->i_delayed_blks != 0)))) { |
1187 | error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); | 1204 | error = xfs_free_eofblocks(mp, ip, 0); |
1188 | if (error) | 1205 | if (error) |
1189 | return VN_INACTIVE_CACHE; | 1206 | return VN_INACTIVE_CACHE; |
1190 | } | 1207 | } |
@@ -2456,46 +2473,6 @@ xfs_set_dmattrs( | |||
2456 | return error; | 2473 | return error; |
2457 | } | 2474 | } |
2458 | 2475 | ||
2459 | int | ||
2460 | xfs_reclaim( | ||
2461 | xfs_inode_t *ip) | ||
2462 | { | ||
2463 | |||
2464 | xfs_itrace_entry(ip); | ||
2465 | |||
2466 | ASSERT(!VN_MAPPED(VFS_I(ip))); | ||
2467 | |||
2468 | /* bad inode, get out here ASAP */ | ||
2469 | if (is_bad_inode(VFS_I(ip))) { | ||
2470 | xfs_ireclaim(ip); | ||
2471 | return 0; | ||
2472 | } | ||
2473 | |||
2474 | xfs_ioend_wait(ip); | ||
2475 | |||
2476 | ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); | ||
2477 | |||
2478 | /* | ||
2479 | * If we have nothing to flush with this inode then complete the | ||
2480 | * teardown now, otherwise break the link between the xfs inode and the | ||
2481 | * linux inode and clean up the xfs inode later. This avoids flushing | ||
2482 | * the inode to disk during the delete operation itself. | ||
2483 | * | ||
2484 | * When breaking the link, we need to set the XFS_IRECLAIMABLE flag | ||
2485 | * first to ensure that xfs_iunpin() will never see an xfs inode | ||
2486 | * that has a linux inode being reclaimed. Synchronisation is provided | ||
2487 | * by the i_flags_lock. | ||
2488 | */ | ||
2489 | if (!ip->i_update_core && (ip->i_itemp == NULL)) { | ||
2490 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
2491 | xfs_iflock(ip); | ||
2492 | xfs_iflags_set(ip, XFS_IRECLAIMABLE); | ||
2493 | return xfs_reclaim_inode(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC); | ||
2494 | } | ||
2495 | xfs_inode_set_reclaim_tag(ip); | ||
2496 | return 0; | ||
2497 | } | ||
2498 | |||
2499 | /* | 2476 | /* |
2500 | * xfs_alloc_file_space() | 2477 | * xfs_alloc_file_space() |
2501 | * This routine allocates disk space for the given file. | 2478 | * This routine allocates disk space for the given file. |