aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iomap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r--fs/xfs/xfs_iomap.c75
1 files changed, 33 insertions, 42 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 1aa3abd67b36..41662fb14e87 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -162,7 +162,7 @@ xfs_iomap_write_direct(
162 xfs_fileoff_t last_fsb; 162 xfs_fileoff_t last_fsb;
163 xfs_filblks_t count_fsb, resaligned; 163 xfs_filblks_t count_fsb, resaligned;
164 xfs_fsblock_t firstfsb; 164 xfs_fsblock_t firstfsb;
165 xfs_extlen_t extsz, temp; 165 xfs_extlen_t extsz;
166 int nimaps; 166 int nimaps;
167 int quota_flag; 167 int quota_flag;
168 int rt; 168 int rt;
@@ -203,14 +203,7 @@ xfs_iomap_write_direct(
203 } 203 }
204 count_fsb = last_fsb - offset_fsb; 204 count_fsb = last_fsb - offset_fsb;
205 ASSERT(count_fsb > 0); 205 ASSERT(count_fsb > 0);
206 206 resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb, extsz);
207 resaligned = count_fsb;
208 if (unlikely(extsz)) {
209 if ((temp = do_mod(offset_fsb, extsz)))
210 resaligned += temp;
211 if ((temp = do_mod(resaligned, extsz)))
212 resaligned += extsz - temp;
213 }
214 207
215 if (unlikely(rt)) { 208 if (unlikely(rt)) {
216 resrtextents = qblocks = resaligned; 209 resrtextents = qblocks = resaligned;
@@ -685,7 +678,7 @@ xfs_iomap_write_allocate(
685 int nres; 678 int nres;
686 679
687 if (whichfork == XFS_COW_FORK) 680 if (whichfork == XFS_COW_FORK)
688 flags |= XFS_BMAPI_COWFORK; 681 flags |= XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC;
689 682
690 /* 683 /*
691 * Make sure that the dquots are there. 684 * Make sure that the dquots are there.
@@ -1002,47 +995,31 @@ xfs_file_iomap_begin(
1002 offset_fsb = XFS_B_TO_FSBT(mp, offset); 995 offset_fsb = XFS_B_TO_FSBT(mp, offset);
1003 end_fsb = XFS_B_TO_FSB(mp, offset + length); 996 end_fsb = XFS_B_TO_FSB(mp, offset + length);
1004 997
1005 if (xfs_is_reflink_inode(ip) &&
1006 (flags & IOMAP_WRITE) && (flags & IOMAP_DIRECT)) {
1007 shared = xfs_reflink_find_cow_mapping(ip, offset, &imap);
1008 if (shared) {
1009 xfs_iunlock(ip, lockmode);
1010 goto alloc_done;
1011 }
1012 ASSERT(!isnullstartblock(imap.br_startblock));
1013 }
1014
1015 error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap, 998 error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
1016 &nimaps, 0); 999 &nimaps, 0);
1017 if (error) 1000 if (error)
1018 goto out_unlock; 1001 goto out_unlock;
1019 1002
1020 if ((flags & IOMAP_REPORT) || 1003 if (flags & IOMAP_REPORT) {
1021 (xfs_is_reflink_inode(ip) &&
1022 (flags & IOMAP_WRITE) && (flags & IOMAP_DIRECT))) {
1023 /* Trim the mapping to the nearest shared extent boundary. */ 1004 /* Trim the mapping to the nearest shared extent boundary. */
1024 error = xfs_reflink_trim_around_shared(ip, &imap, &shared, 1005 error = xfs_reflink_trim_around_shared(ip, &imap, &shared,
1025 &trimmed); 1006 &trimmed);
1026 if (error) 1007 if (error)
1027 goto out_unlock; 1008 goto out_unlock;
1028
1029 /*
1030 * We're here because we're trying to do a directio write to a
1031 * region that isn't aligned to a filesystem block. If the
1032 * extent is shared, fall back to buffered mode to handle the
1033 * RMW.
1034 */
1035 if (!(flags & IOMAP_REPORT) && shared) {
1036 trace_xfs_reflink_bounce_dio_write(ip, &imap);
1037 error = -EREMCHG;
1038 goto out_unlock;
1039 }
1040 } 1009 }
1041 1010
1042 if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) { 1011 if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
1043 error = xfs_reflink_reserve_cow(ip, &imap, &shared); 1012 if (flags & IOMAP_DIRECT) {
1044 if (error) 1013 /* may drop and re-acquire the ilock */
1045 goto out_unlock; 1014 error = xfs_reflink_allocate_cow(ip, &imap, &shared,
1015 &lockmode);
1016 if (error)
1017 goto out_unlock;
1018 } else {
1019 error = xfs_reflink_reserve_cow(ip, &imap, &shared);
1020 if (error)
1021 goto out_unlock;
1022 }
1046 1023
1047 end_fsb = imap.br_startoff + imap.br_blockcount; 1024 end_fsb = imap.br_startoff + imap.br_blockcount;
1048 length = XFS_FSB_TO_B(mp, end_fsb) - offset; 1025 length = XFS_FSB_TO_B(mp, end_fsb) - offset;
@@ -1071,7 +1048,6 @@ xfs_file_iomap_begin(
1071 if (error) 1048 if (error)
1072 return error; 1049 return error;
1073 1050
1074alloc_done:
1075 iomap->flags = IOMAP_F_NEW; 1051 iomap->flags = IOMAP_F_NEW;
1076 trace_xfs_iomap_alloc(ip, offset, length, 0, &imap); 1052 trace_xfs_iomap_alloc(ip, offset, length, 0, &imap);
1077 } else { 1053 } else {
@@ -1102,7 +1078,19 @@ xfs_file_iomap_end_delalloc(
1102 xfs_fileoff_t end_fsb; 1078 xfs_fileoff_t end_fsb;
1103 int error = 0; 1079 int error = 0;
1104 1080
1105 start_fsb = XFS_B_TO_FSB(mp, offset + written); 1081 /* behave as if the write failed if drop writes is enabled */
1082 if (xfs_mp_drop_writes(mp))
1083 written = 0;
1084
1085 /*
1086 * start_fsb refers to the first unused block after a short write. If
1087 * nothing was written, round offset down to point at the first block in
1088 * the range.
1089 */
1090 if (unlikely(!written))
1091 start_fsb = XFS_B_TO_FSBT(mp, offset);
1092 else
1093 start_fsb = XFS_B_TO_FSB(mp, offset + written);
1106 end_fsb = XFS_B_TO_FSB(mp, offset + length); 1094 end_fsb = XFS_B_TO_FSB(mp, offset + length);
1107 1095
1108 /* 1096 /*
@@ -1114,6 +1102,9 @@ xfs_file_iomap_end_delalloc(
1114 * blocks in the range, they are ours. 1102 * blocks in the range, they are ours.
1115 */ 1103 */
1116 if (start_fsb < end_fsb) { 1104 if (start_fsb < end_fsb) {
1105 truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb),
1106 XFS_FSB_TO_B(mp, end_fsb) - 1);
1107
1117 xfs_ilock(ip, XFS_ILOCK_EXCL); 1108 xfs_ilock(ip, XFS_ILOCK_EXCL);
1118 error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1109 error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
1119 end_fsb - start_fsb); 1110 end_fsb - start_fsb);
@@ -1144,7 +1135,7 @@ xfs_file_iomap_end(
1144 return 0; 1135 return 0;
1145} 1136}
1146 1137
1147struct iomap_ops xfs_iomap_ops = { 1138const struct iomap_ops xfs_iomap_ops = {
1148 .iomap_begin = xfs_file_iomap_begin, 1139 .iomap_begin = xfs_file_iomap_begin,
1149 .iomap_end = xfs_file_iomap_end, 1140 .iomap_end = xfs_file_iomap_end,
1150}; 1141};
@@ -1190,6 +1181,6 @@ out_unlock:
1190 return error; 1181 return error;
1191} 1182}
1192 1183
1193struct iomap_ops xfs_xattr_iomap_ops = { 1184const struct iomap_ops xfs_xattr_iomap_ops = {
1194 .iomap_begin = xfs_xattr_iomap_begin, 1185 .iomap_begin = xfs_xattr_iomap_begin,
1195}; 1186};