diff options
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/kmem.c | 18 | ||||
| -rw-r--r-- | fs/xfs/kmem.h | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 34 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap_btree.c | 6 | ||||
| -rw-r--r-- | fs/xfs/xfs_aops.c | 59 | ||||
| -rw-r--r-- | fs/xfs/xfs_icache.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 25 | ||||
| -rw-r--r-- | fs/xfs/xfs_itable.c | 6 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_reflink.c | 23 | ||||
| -rw-r--r-- | fs/xfs/xfs_reflink.h | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c | 2 |
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 | */ | ||
| 31 | void * | ||
| 32 | kmem_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 | |||
| 46 | void * | 28 | void * |
| 47 | kmem_alloc(size_t size, xfs_km_flags_t flags) | 29 | kmem_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 | ||
| 72 | extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); | ||
| 73 | |||
| 74 | static inline void * | 72 | static inline void * |
| 75 | kmem_zalloc(size_t size, xfs_km_flags_t flags) | 73 | kmem_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) { |
| 766 | try_another_ag: | ||
| 767 | args.type = XFS_ALLOCTYPE_START_BNO; | 766 | args.type = XFS_ALLOCTYPE_START_BNO; |
| 767 | try_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 | */ | ||
| 4153 | int | 4170 | int |
| 4154 | xfs_bmapi_reserve_delalloc( | 4171 | xfs_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 | ||
| 4263 | out_unreserve_blocks: | 4271 | out_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); |
| 450 | try_another_ag: | ||
| 451 | args.type = XFS_ALLOCTYPE_START_BNO; | 450 | args.type = XFS_ALLOCTYPE_START_BNO; |
| 451 | try_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 | ||
| 324 | done: | 317 | done: |
| 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); |
| 634 | done: | 639 | done: |
| 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 | |||
| 513 | xfs_set_inoalignment(xfs_mount_t *mp) | 513 | xfs_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 | */ |
| 553 | int | 556 | int |
| 554 | xfs_reflink_cancel_cow_blocks( | 557 | xfs_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 | */ |
| 626 | int | 633 | int |
| 627 | xfs_reflink_cancel_cow_range( | 634 | xfs_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 | ||
| 40 | extern int xfs_reflink_cancel_cow_blocks(struct xfs_inode *ip, | 40 | extern 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); |
| 43 | extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset, | 43 | extern 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); |
| 45 | extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, | 45 | extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, |
| 46 | xfs_off_t count); | 46 | xfs_off_t count); |
| 47 | extern int xfs_reflink_recover_cow(struct xfs_mount *mp); | 47 | extern 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.", |
