aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c87
1 files changed, 29 insertions, 58 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index b572f7e840e0..6558ffd8d140 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -53,6 +53,7 @@
53#include "xfs_log_priv.h" 53#include "xfs_log_priv.h"
54#include "xfs_filestream.h" 54#include "xfs_filestream.h"
55#include "xfs_vnodeops.h" 55#include "xfs_vnodeops.h"
56#include "xfs_trace.h"
56 57
57int 58int
58xfs_setattr( 59xfs_setattr(
@@ -538,9 +539,8 @@ xfs_readlink_bmap(
538 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); 539 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
539 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); 540 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
540 541
541 bp = xfs_buf_read_flags(mp->m_ddev_targp, d, BTOBB(byte_cnt), 542 bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt),
542 XBF_LOCK | XBF_MAPPED | 543 XBF_LOCK | XBF_MAPPED | XBF_DONT_BLOCK);
543 XBF_DONT_BLOCK);
544 error = XFS_BUF_GETERROR(bp); 544 error = XFS_BUF_GETERROR(bp);
545 if (error) { 545 if (error) {
546 xfs_ioerror_alert("xfs_readlink", 546 xfs_ioerror_alert("xfs_readlink",
@@ -709,6 +709,11 @@ xfs_fsync(
709} 709}
710 710
711/* 711/*
712 * Flags for xfs_free_eofblocks
713 */
714#define XFS_FREE_EOF_TRYLOCK (1<<0)
715
716/*
712 * This is called by xfs_inactive to free any blocks beyond eof 717 * 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 718 * when the link count isn't zero and by xfs_dm_punch_hole() when
714 * punching a hole to EOF. 719 * punching a hole to EOF.
@@ -726,7 +731,6 @@ xfs_free_eofblocks(
726 xfs_filblks_t map_len; 731 xfs_filblks_t map_len;
727 int nimaps; 732 int nimaps;
728 xfs_bmbt_irec_t imap; 733 xfs_bmbt_irec_t imap;
729 int use_iolock = (flags & XFS_FREE_EOF_LOCK);
730 734
731 /* 735 /*
732 * Figure out if there are any blocks beyond the end 736 * Figure out if there are any blocks beyond the end
@@ -768,14 +772,19 @@ xfs_free_eofblocks(
768 * cache and we can't 772 * cache and we can't
769 * do that within a transaction. 773 * do that within a transaction.
770 */ 774 */
771 if (use_iolock) 775 if (flags & XFS_FREE_EOF_TRYLOCK) {
776 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
777 xfs_trans_cancel(tp, 0);
778 return 0;
779 }
780 } else {
772 xfs_ilock(ip, XFS_IOLOCK_EXCL); 781 xfs_ilock(ip, XFS_IOLOCK_EXCL);
782 }
773 error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 783 error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
774 ip->i_size); 784 ip->i_size);
775 if (error) { 785 if (error) {
776 xfs_trans_cancel(tp, 0); 786 xfs_trans_cancel(tp, 0);
777 if (use_iolock) 787 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
778 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
779 return error; 788 return error;
780 } 789 }
781 790
@@ -812,8 +821,7 @@ xfs_free_eofblocks(
812 error = xfs_trans_commit(tp, 821 error = xfs_trans_commit(tp,
813 XFS_TRANS_RELEASE_LOG_RES); 822 XFS_TRANS_RELEASE_LOG_RES);
814 } 823 }
815 xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL) 824 xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
816 : XFS_ILOCK_EXCL));
817 } 825 }
818 return error; 826 return error;
819} 827}
@@ -1113,7 +1121,17 @@ xfs_release(
1113 (ip->i_df.if_flags & XFS_IFEXTENTS)) && 1121 (ip->i_df.if_flags & XFS_IFEXTENTS)) &&
1114 (!(ip->i_d.di_flags & 1122 (!(ip->i_d.di_flags &
1115 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { 1123 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
1116 error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); 1124
1125 /*
1126 * If we can't get the iolock just skip truncating
1127 * the blocks past EOF because we could deadlock
1128 * with the mmap_sem otherwise. We'll get another
1129 * chance to drop them once the last reference to
1130 * the inode is dropped, so we'll never leak blocks
1131 * permanently.
1132 */
1133 error = xfs_free_eofblocks(mp, ip,
1134 XFS_FREE_EOF_TRYLOCK);
1117 if (error) 1135 if (error)
1118 return error; 1136 return error;
1119 } 1137 }
@@ -1184,7 +1202,7 @@ xfs_inactive(
1184 (!(ip->i_d.di_flags & 1202 (!(ip->i_d.di_flags &
1185 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || 1203 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
1186 (ip->i_delayed_blks != 0)))) { 1204 (ip->i_delayed_blks != 0)))) {
1187 error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); 1205 error = xfs_free_eofblocks(mp, ip, 0);
1188 if (error) 1206 if (error)
1189 return VN_INACTIVE_CACHE; 1207 return VN_INACTIVE_CACHE;
1190 } 1208 }
@@ -1380,7 +1398,6 @@ xfs_lookup(
1380 if (error) 1398 if (error)
1381 goto out_free_name; 1399 goto out_free_name;
1382 1400
1383 xfs_itrace_ref(*ipp);
1384 return 0; 1401 return 0;
1385 1402
1386out_free_name: 1403out_free_name:
@@ -1526,7 +1543,6 @@ xfs_create(
1526 * At this point, we've gotten a newly allocated inode. 1543 * At this point, we've gotten a newly allocated inode.
1527 * It is locked (and joined to the transaction). 1544 * It is locked (and joined to the transaction).
1528 */ 1545 */
1529 xfs_itrace_ref(ip);
1530 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 1546 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
1531 1547
1532 /* 1548 /*
@@ -1986,9 +2002,6 @@ xfs_remove(
1986 if (!is_dir && link_zero && xfs_inode_is_filestream(ip)) 2002 if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
1987 xfs_filestream_deassociate(ip); 2003 xfs_filestream_deassociate(ip);
1988 2004
1989 xfs_itrace_exit(ip);
1990 xfs_itrace_exit(dp);
1991
1992 std_return: 2005 std_return:
1993 if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) { 2006 if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
1994 XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL, 2007 XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
@@ -2285,7 +2298,6 @@ xfs_symlink(
2285 goto error_return; 2298 goto error_return;
2286 goto error1; 2299 goto error1;
2287 } 2300 }
2288 xfs_itrace_ref(ip);
2289 2301
2290 /* 2302 /*
2291 * An error after we've joined dp to the transaction will result in the 2303 * An error after we've joined dp to the transaction will result in the
@@ -2456,46 +2468,6 @@ xfs_set_dmattrs(
2456 return error; 2468 return error;
2457} 2469}
2458 2470
2459int
2460xfs_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/* 2471/*
2500 * xfs_alloc_file_space() 2472 * xfs_alloc_file_space()
2501 * This routine allocates disk space for the given file. 2473 * This routine allocates disk space for the given file.
@@ -2868,7 +2840,6 @@ xfs_free_file_space(
2868 ioffset = offset & ~(rounding - 1); 2840 ioffset = offset & ~(rounding - 1);
2869 2841
2870 if (VN_CACHED(VFS_I(ip)) != 0) { 2842 if (VN_CACHED(VFS_I(ip)) != 0) {
2871 xfs_inval_cached_trace(ip, ioffset, -1, ioffset, -1);
2872 error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED); 2843 error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED);
2873 if (error) 2844 if (error)
2874 goto out_unlock_iolock; 2845 goto out_unlock_iolock;