aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/kmem.c18
-rw-r--r--fs/xfs/kmem.h2
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c34
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c6
-rw-r--r--fs/xfs/xfs_aops.c59
-rw-r--r--fs/xfs/xfs_icache.c2
-rw-r--r--fs/xfs/xfs_inode.c2
-rw-r--r--fs/xfs/xfs_iomap.c25
-rw-r--r--fs/xfs/xfs_itable.c6
-rw-r--r--fs/xfs/xfs_mount.c3
-rw-r--r--fs/xfs/xfs_reflink.c23
-rw-r--r--fs/xfs/xfs_reflink.h4
-rw-r--r--fs/xfs/xfs_super.c2
13 files changed, 93 insertions, 93 deletions
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c
index 2dfdc62f795e..70a5b55e0870 100644
--- a/fs/xfs/kmem.c
+++ b/fs/xfs/kmem.c
@@ -25,24 +25,6 @@
25#include "kmem.h" 25#include "kmem.h"
26#include "xfs_message.h" 26#include "xfs_message.h"
27 27
28/*
29 * Greedy allocation. May fail and may return vmalloced memory.
30 */
31void *
32kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
33{
34 void *ptr;
35 size_t kmsize = maxsize;
36
37 while (!(ptr = vzalloc(kmsize))) {
38 if ((kmsize >>= 1) <= minsize)
39 kmsize = minsize;
40 }
41 if (ptr)
42 *size = kmsize;
43 return ptr;
44}
45
46void * 28void *
47kmem_alloc(size_t size, xfs_km_flags_t flags) 29kmem_alloc(size_t size, xfs_km_flags_t flags)
48{ 30{
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
index 689f746224e7..f0fc84fcaac2 100644
--- a/fs/xfs/kmem.h
+++ b/fs/xfs/kmem.h
@@ -69,8 +69,6 @@ static inline void kmem_free(const void *ptr)
69} 69}
70 70
71 71
72extern void *kmem_zalloc_greedy(size_t *, size_t, size_t);
73
74static inline void * 72static inline void *
75kmem_zalloc(size_t size, xfs_km_flags_t flags) 73kmem_zalloc(size_t size, xfs_km_flags_t flags)
76{ 74{
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index a9c66d47757a..9bd104f32908 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -763,8 +763,8 @@ xfs_bmap_extents_to_btree(
763 args.type = XFS_ALLOCTYPE_START_BNO; 763 args.type = XFS_ALLOCTYPE_START_BNO;
764 args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); 764 args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
765 } else if (dfops->dop_low) { 765 } else if (dfops->dop_low) {
766try_another_ag:
767 args.type = XFS_ALLOCTYPE_START_BNO; 766 args.type = XFS_ALLOCTYPE_START_BNO;
767try_another_ag:
768 args.fsbno = *firstblock; 768 args.fsbno = *firstblock;
769 } else { 769 } else {
770 args.type = XFS_ALLOCTYPE_NEAR_BNO; 770 args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -790,13 +790,17 @@ try_another_ag:
790 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && 790 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) &&
791 args.fsbno == NULLFSBLOCK && 791 args.fsbno == NULLFSBLOCK &&
792 args.type == XFS_ALLOCTYPE_NEAR_BNO) { 792 args.type == XFS_ALLOCTYPE_NEAR_BNO) {
793 dfops->dop_low = true; 793 args.type = XFS_ALLOCTYPE_FIRST_AG;
794 goto try_another_ag; 794 goto try_another_ag;
795 } 795 }
796 if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
797 xfs_iroot_realloc(ip, -1, whichfork);
798 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
799 return -ENOSPC;
800 }
796 /* 801 /*
797 * Allocation can't fail, the space was reserved. 802 * Allocation can't fail, the space was reserved.
798 */ 803 */
799 ASSERT(args.fsbno != NULLFSBLOCK);
800 ASSERT(*firstblock == NULLFSBLOCK || 804 ASSERT(*firstblock == NULLFSBLOCK ||
801 args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock)); 805 args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock));
802 *firstblock = cur->bc_private.b.firstblock = args.fsbno; 806 *firstblock = cur->bc_private.b.firstblock = args.fsbno;
@@ -4150,6 +4154,19 @@ xfs_bmapi_read(
4150 return 0; 4154 return 0;
4151} 4155}
4152 4156
4157/*
4158 * Add a delayed allocation extent to an inode. Blocks are reserved from the
4159 * global pool and the extent inserted into the inode in-core extent tree.
4160 *
4161 * On entry, got refers to the first extent beyond the offset of the extent to
4162 * allocate or eof is specified if no such extent exists. On return, got refers
4163 * to the extent record that was inserted to the inode fork.
4164 *
4165 * Note that the allocated extent may have been merged with contiguous extents
4166 * during insertion into the inode fork. Thus, got does not reflect the current
4167 * state of the inode fork on return. If necessary, the caller can use lastx to
4168 * look up the updated record in the inode fork.
4169 */
4153int 4170int
4154xfs_bmapi_reserve_delalloc( 4171xfs_bmapi_reserve_delalloc(
4155 struct xfs_inode *ip, 4172 struct xfs_inode *ip,
@@ -4236,13 +4253,8 @@ xfs_bmapi_reserve_delalloc(
4236 got->br_startblock = nullstartblock(indlen); 4253 got->br_startblock = nullstartblock(indlen);
4237 got->br_blockcount = alen; 4254 got->br_blockcount = alen;
4238 got->br_state = XFS_EXT_NORM; 4255 got->br_state = XFS_EXT_NORM;
4239 xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got);
4240 4256
4241 /* 4257 xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got);
4242 * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay
4243 * might have merged it into one of the neighbouring ones.
4244 */
4245 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
4246 4258
4247 /* 4259 /*
4248 * Tag the inode if blocks were preallocated. Note that COW fork 4260 * Tag the inode if blocks were preallocated. Note that COW fork
@@ -4254,10 +4266,6 @@ xfs_bmapi_reserve_delalloc(
4254 if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len)) 4266 if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len))
4255 xfs_inode_set_cowblocks_tag(ip); 4267 xfs_inode_set_cowblocks_tag(ip);
4256 4268
4257 ASSERT(got->br_startoff <= aoff);
4258 ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
4259 ASSERT(isnullstartblock(got->br_startblock));
4260 ASSERT(got->br_state == XFS_EXT_NORM);
4261 return 0; 4269 return 0;
4262 4270
4263out_unreserve_blocks: 4271out_unreserve_blocks:
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index f93072b58a58..fd55db479385 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -447,8 +447,8 @@ xfs_bmbt_alloc_block(
447 447
448 if (args.fsbno == NULLFSBLOCK) { 448 if (args.fsbno == NULLFSBLOCK) {
449 args.fsbno = be64_to_cpu(start->l); 449 args.fsbno = be64_to_cpu(start->l);
450try_another_ag:
451 args.type = XFS_ALLOCTYPE_START_BNO; 450 args.type = XFS_ALLOCTYPE_START_BNO;
451try_another_ag:
452 /* 452 /*
453 * Make sure there is sufficient room left in the AG to 453 * Make sure there is sufficient room left in the AG to
454 * complete a full tree split for an extent insert. If 454 * complete a full tree split for an extent insert. If
@@ -488,8 +488,8 @@ try_another_ag:
488 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && 488 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) &&
489 args.fsbno == NULLFSBLOCK && 489 args.fsbno == NULLFSBLOCK &&
490 args.type == XFS_ALLOCTYPE_NEAR_BNO) { 490 args.type == XFS_ALLOCTYPE_NEAR_BNO) {
491 cur->bc_private.b.dfops->dop_low = true;
492 args.fsbno = cur->bc_private.b.firstblock; 491 args.fsbno = cur->bc_private.b.firstblock;
492 args.type = XFS_ALLOCTYPE_FIRST_AG;
493 goto try_another_ag; 493 goto try_another_ag;
494 } 494 }
495 495
@@ -506,7 +506,7 @@ try_another_ag:
506 goto error0; 506 goto error0;
507 cur->bc_private.b.dfops->dop_low = true; 507 cur->bc_private.b.dfops->dop_low = true;
508 } 508 }
509 if (args.fsbno == NULLFSBLOCK) { 509 if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
510 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 510 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
511 *stat = 0; 511 *stat = 0;
512 return 0; 512 return 0;
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index bf65a9ea8642..61494295d92f 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -274,54 +274,49 @@ xfs_end_io(
274 struct xfs_ioend *ioend = 274 struct xfs_ioend *ioend =
275 container_of(work, struct xfs_ioend, io_work); 275 container_of(work, struct xfs_ioend, io_work);
276 struct xfs_inode *ip = XFS_I(ioend->io_inode); 276 struct xfs_inode *ip = XFS_I(ioend->io_inode);
277 xfs_off_t offset = ioend->io_offset;
278 size_t size = ioend->io_size;
277 int error = ioend->io_bio->bi_error; 279 int error = ioend->io_bio->bi_error;
278 280
279 /* 281 /*
280 * Set an error if the mount has shut down and proceed with end I/O 282 * Just clean up the in-memory strutures if the fs has been shut down.
281 * processing so it can perform whatever cleanups are necessary.
282 */ 283 */
283 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 284 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
284 error = -EIO; 285 error = -EIO;
286 goto done;
287 }
285 288
286 /* 289 /*
287 * For a CoW extent, we need to move the mapping from the CoW fork 290 * Clean up any COW blocks on an I/O error.
288 * to the data fork. If instead an error happened, just dump the
289 * new blocks.
290 */ 291 */
291 if (ioend->io_type == XFS_IO_COW) { 292 if (unlikely(error)) {
292 if (error) 293 switch (ioend->io_type) {
293 goto done; 294 case XFS_IO_COW:
294 if (ioend->io_bio->bi_error) { 295 xfs_reflink_cancel_cow_range(ip, offset, size, true);
295 error = xfs_reflink_cancel_cow_range(ip, 296 break;
296 ioend->io_offset, ioend->io_size);
297 goto done;
298 } 297 }
299 error = xfs_reflink_end_cow(ip, ioend->io_offset, 298
300 ioend->io_size); 299 goto done;
301 if (error)
302 goto done;
303 } 300 }
304 301
305 /* 302 /*
306 * For unwritten extents we need to issue transactions to convert a 303 * Success: commit the COW or unwritten blocks if needed.
307 * range to normal written extens after the data I/O has finished.
308 * Detecting and handling completion IO errors is done individually
309 * for each case as different cleanup operations need to be performed
310 * on error.
311 */ 304 */
312 if (ioend->io_type == XFS_IO_UNWRITTEN) { 305 switch (ioend->io_type) {
313 if (error) 306 case XFS_IO_COW:
314 goto done; 307 error = xfs_reflink_end_cow(ip, offset, size);
315 error = xfs_iomap_write_unwritten(ip, ioend->io_offset, 308 break;
316 ioend->io_size); 309 case XFS_IO_UNWRITTEN:
317 } else if (ioend->io_append_trans) { 310 error = xfs_iomap_write_unwritten(ip, offset, size);
318 error = xfs_setfilesize_ioend(ioend, error); 311 break;
319 } else { 312 default:
320 ASSERT(!xfs_ioend_is_append(ioend) || 313 ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans);
321 ioend->io_type == XFS_IO_COW); 314 break;
322 } 315 }
323 316
324done: 317done:
318 if (ioend->io_append_trans)
319 error = xfs_setfilesize_ioend(ioend, error);
325 xfs_destroy_ioend(ioend, error); 320 xfs_destroy_ioend(ioend, error);
326} 321}
327 322
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 7234b9748c36..3531f8f72fa5 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1608,7 +1608,7 @@ xfs_inode_free_cowblocks(
1608 xfs_ilock(ip, XFS_IOLOCK_EXCL); 1608 xfs_ilock(ip, XFS_IOLOCK_EXCL);
1609 xfs_ilock(ip, XFS_MMAPLOCK_EXCL); 1609 xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
1610 1610
1611 ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF); 1611 ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, false);
1612 1612
1613 xfs_iunlock(ip, XFS_MMAPLOCK_EXCL); 1613 xfs_iunlock(ip, XFS_MMAPLOCK_EXCL);
1614 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 1614 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index edfa6a55b064..7eaf1ef74e3c 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1615,7 +1615,7 @@ xfs_itruncate_extents(
1615 1615
1616 /* Remove all pending CoW reservations. */ 1616 /* Remove all pending CoW reservations. */
1617 error = xfs_reflink_cancel_cow_blocks(ip, &tp, first_unmap_block, 1617 error = xfs_reflink_cancel_cow_blocks(ip, &tp, first_unmap_block,
1618 last_block); 1618 last_block, true);
1619 if (error) 1619 if (error)
1620 goto out; 1620 goto out;
1621 1621
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 41662fb14e87..288ee5b840d7 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -630,6 +630,11 @@ retry:
630 goto out_unlock; 630 goto out_unlock;
631 } 631 }
632 632
633 /*
634 * Flag newly allocated delalloc blocks with IOMAP_F_NEW so we punch
635 * them out if the write happens to fail.
636 */
637 iomap->flags = IOMAP_F_NEW;
633 trace_xfs_iomap_alloc(ip, offset, count, 0, &got); 638 trace_xfs_iomap_alloc(ip, offset, count, 0, &got);
634done: 639done:
635 if (isnullstartblock(got.br_startblock)) 640 if (isnullstartblock(got.br_startblock))
@@ -1071,16 +1076,22 @@ xfs_file_iomap_end_delalloc(
1071 struct xfs_inode *ip, 1076 struct xfs_inode *ip,
1072 loff_t offset, 1077 loff_t offset,
1073 loff_t length, 1078 loff_t length,
1074 ssize_t written) 1079 ssize_t written,
1080 struct iomap *iomap)
1075{ 1081{
1076 struct xfs_mount *mp = ip->i_mount; 1082 struct xfs_mount *mp = ip->i_mount;
1077 xfs_fileoff_t start_fsb; 1083 xfs_fileoff_t start_fsb;
1078 xfs_fileoff_t end_fsb; 1084 xfs_fileoff_t end_fsb;
1079 int error = 0; 1085 int error = 0;
1080 1086
1081 /* behave as if the write failed if drop writes is enabled */ 1087 /*
1082 if (xfs_mp_drop_writes(mp)) 1088 * Behave as if the write failed if drop writes is enabled. Set the NEW
1089 * flag to force delalloc cleanup.
1090 */
1091 if (xfs_mp_drop_writes(mp)) {
1092 iomap->flags |= IOMAP_F_NEW;
1083 written = 0; 1093 written = 0;
1094 }
1084 1095
1085 /* 1096 /*
1086 * start_fsb refers to the first unused block after a short write. If 1097 * start_fsb refers to the first unused block after a short write. If
@@ -1094,14 +1105,14 @@ xfs_file_iomap_end_delalloc(
1094 end_fsb = XFS_B_TO_FSB(mp, offset + length); 1105 end_fsb = XFS_B_TO_FSB(mp, offset + length);
1095 1106
1096 /* 1107 /*
1097 * Trim back delalloc blocks if we didn't manage to write the whole 1108 * Trim delalloc blocks if they were allocated by this write and we
1098 * range reserved. 1109 * didn't manage to write the whole range.
1099 * 1110 *
1100 * We don't need to care about racing delalloc as we hold i_mutex 1111 * We don't need to care about racing delalloc as we hold i_mutex
1101 * across the reserve/allocate/unreserve calls. If there are delalloc 1112 * across the reserve/allocate/unreserve calls. If there are delalloc
1102 * blocks in the range, they are ours. 1113 * blocks in the range, they are ours.
1103 */ 1114 */
1104 if (start_fsb < end_fsb) { 1115 if ((iomap->flags & IOMAP_F_NEW) && start_fsb < end_fsb) {
1105 truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb), 1116 truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb),
1106 XFS_FSB_TO_B(mp, end_fsb) - 1); 1117 XFS_FSB_TO_B(mp, end_fsb) - 1);
1107 1118
@@ -1131,7 +1142,7 @@ xfs_file_iomap_end(
1131{ 1142{
1132 if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC) 1143 if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC)
1133 return xfs_file_iomap_end_delalloc(XFS_I(inode), offset, 1144 return xfs_file_iomap_end_delalloc(XFS_I(inode), offset,
1134 length, written); 1145 length, written, iomap);
1135 return 0; 1146 return 0;
1136} 1147}
1137 1148
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 66e881790c17..2a6d9b1558e0 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -361,7 +361,6 @@ xfs_bulkstat(
361 xfs_agino_t agino; /* inode # in allocation group */ 361 xfs_agino_t agino; /* inode # in allocation group */
362 xfs_agnumber_t agno; /* allocation group number */ 362 xfs_agnumber_t agno; /* allocation group number */
363 xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ 363 xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */
364 size_t irbsize; /* size of irec buffer in bytes */
365 xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ 364 xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */
366 int nirbuf; /* size of irbuf */ 365 int nirbuf; /* size of irbuf */
367 int ubcount; /* size of user's buffer */ 366 int ubcount; /* size of user's buffer */
@@ -388,11 +387,10 @@ xfs_bulkstat(
388 *ubcountp = 0; 387 *ubcountp = 0;
389 *done = 0; 388 *done = 0;
390 389
391 irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4); 390 irbuf = kmem_zalloc_large(PAGE_SIZE * 4, KM_SLEEP);
392 if (!irbuf) 391 if (!irbuf)
393 return -ENOMEM; 392 return -ENOMEM;
394 393 nirbuf = (PAGE_SIZE * 4) / sizeof(*irbuf);
395 nirbuf = irbsize / sizeof(*irbuf);
396 394
397 /* 395 /*
398 * Loop over the allocation groups, starting from the last 396 * Loop over the allocation groups, starting from the last
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 450bde68bb75..688ebff1f663 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -513,8 +513,7 @@ STATIC void
513xfs_set_inoalignment(xfs_mount_t *mp) 513xfs_set_inoalignment(xfs_mount_t *mp)
514{ 514{
515 if (xfs_sb_version_hasalign(&mp->m_sb) && 515 if (xfs_sb_version_hasalign(&mp->m_sb) &&
516 mp->m_sb.sb_inoalignmt >= 516 mp->m_sb.sb_inoalignmt >= xfs_icluster_size_fsb(mp))
517 XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
518 mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1; 517 mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1;
519 else 518 else
520 mp->m_inoalign_mask = 0; 519 mp->m_inoalign_mask = 0;
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index da6d08fb359c..4a84c5ea266d 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -548,14 +548,18 @@ xfs_reflink_trim_irec_to_next_cow(
548} 548}
549 549
550/* 550/*
551 * Cancel all pending CoW reservations for some block range of an inode. 551 * Cancel CoW reservations for some block range of an inode.
552 *
553 * If cancel_real is true this function cancels all COW fork extents for the
554 * inode; if cancel_real is false, real extents are not cleared.
552 */ 555 */
553int 556int
554xfs_reflink_cancel_cow_blocks( 557xfs_reflink_cancel_cow_blocks(
555 struct xfs_inode *ip, 558 struct xfs_inode *ip,
556 struct xfs_trans **tpp, 559 struct xfs_trans **tpp,
557 xfs_fileoff_t offset_fsb, 560 xfs_fileoff_t offset_fsb,
558 xfs_fileoff_t end_fsb) 561 xfs_fileoff_t end_fsb,
562 bool cancel_real)
559{ 563{
560 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); 564 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
561 struct xfs_bmbt_irec got, del; 565 struct xfs_bmbt_irec got, del;
@@ -579,7 +583,7 @@ xfs_reflink_cancel_cow_blocks(
579 &idx, &got, &del); 583 &idx, &got, &del);
580 if (error) 584 if (error)
581 break; 585 break;
582 } else { 586 } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
583 xfs_trans_ijoin(*tpp, ip, 0); 587 xfs_trans_ijoin(*tpp, ip, 0);
584 xfs_defer_init(&dfops, &firstfsb); 588 xfs_defer_init(&dfops, &firstfsb);
585 589
@@ -621,13 +625,17 @@ xfs_reflink_cancel_cow_blocks(
621} 625}
622 626
623/* 627/*
624 * Cancel all pending CoW reservations for some byte range of an inode. 628 * Cancel CoW reservations for some byte range of an inode.
629 *
630 * If cancel_real is true this function cancels all COW fork extents for the
631 * inode; if cancel_real is false, real extents are not cleared.
625 */ 632 */
626int 633int
627xfs_reflink_cancel_cow_range( 634xfs_reflink_cancel_cow_range(
628 struct xfs_inode *ip, 635 struct xfs_inode *ip,
629 xfs_off_t offset, 636 xfs_off_t offset,
630 xfs_off_t count) 637 xfs_off_t count,
638 bool cancel_real)
631{ 639{
632 struct xfs_trans *tp; 640 struct xfs_trans *tp;
633 xfs_fileoff_t offset_fsb; 641 xfs_fileoff_t offset_fsb;
@@ -653,7 +661,8 @@ xfs_reflink_cancel_cow_range(
653 xfs_trans_ijoin(tp, ip, 0); 661 xfs_trans_ijoin(tp, ip, 0);
654 662
655 /* Scrape out the old CoW reservations */ 663 /* Scrape out the old CoW reservations */
656 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb); 664 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb,
665 cancel_real);
657 if (error) 666 if (error)
658 goto out_cancel; 667 goto out_cancel;
659 668
@@ -1450,7 +1459,7 @@ next:
1450 * We didn't find any shared blocks so turn off the reflink flag. 1459 * We didn't find any shared blocks so turn off the reflink flag.
1451 * First, get rid of any leftover CoW mappings. 1460 * First, get rid of any leftover CoW mappings.
1452 */ 1461 */
1453 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF); 1462 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true);
1454 if (error) 1463 if (error)
1455 return error; 1464 return error;
1456 1465
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index 33ac9b8db683..d29a7967f029 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -39,9 +39,9 @@ extern void xfs_reflink_trim_irec_to_next_cow(struct xfs_inode *ip,
39 39
40extern int xfs_reflink_cancel_cow_blocks(struct xfs_inode *ip, 40extern int xfs_reflink_cancel_cow_blocks(struct xfs_inode *ip,
41 struct xfs_trans **tpp, xfs_fileoff_t offset_fsb, 41 struct xfs_trans **tpp, xfs_fileoff_t offset_fsb,
42 xfs_fileoff_t end_fsb); 42 xfs_fileoff_t end_fsb, bool cancel_real);
43extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset, 43extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset,
44 xfs_off_t count); 44 xfs_off_t count, bool cancel_real);
45extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, 45extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
46 xfs_off_t count); 46 xfs_off_t count);
47extern int xfs_reflink_recover_cow(struct xfs_mount *mp); 47extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 890862f2447c..685c042a120f 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -953,7 +953,7 @@ xfs_fs_destroy_inode(
953 XFS_STATS_INC(ip->i_mount, vn_remove); 953 XFS_STATS_INC(ip->i_mount, vn_remove);
954 954
955 if (xfs_is_reflink_inode(ip)) { 955 if (xfs_is_reflink_inode(ip)) {
956 error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF); 956 error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true);
957 if (error && !XFS_FORCED_SHUTDOWN(ip->i_mount)) 957 if (error && !XFS_FORCED_SHUTDOWN(ip->i_mount))
958 xfs_warn(ip->i_mount, 958 xfs_warn(ip->i_mount,
959"Error %d while evicting CoW blocks for inode %llu.", 959"Error %d while evicting CoW blocks for inode %llu.",