aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs/xfs_bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 44773c9eb957..bfc00de5c6f1 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -3629,7 +3629,7 @@ xfs_bmap_btalloc(
3629 align = xfs_get_cowextsz_hint(ap->ip); 3629 align = xfs_get_cowextsz_hint(ap->ip);
3630 else if (xfs_alloc_is_userdata(ap->datatype)) 3630 else if (xfs_alloc_is_userdata(ap->datatype))
3631 align = xfs_get_extsz_hint(ap->ip); 3631 align = xfs_get_extsz_hint(ap->ip);
3632 if (unlikely(align)) { 3632 if (align) {
3633 error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, 3633 error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
3634 align, 0, ap->eof, 0, ap->conv, 3634 align, 0, ap->eof, 0, ap->conv,
3635 &ap->offset, &ap->length); 3635 &ap->offset, &ap->length);
@@ -3701,7 +3701,7 @@ xfs_bmap_btalloc(
3701 args.minlen = ap->minlen; 3701 args.minlen = ap->minlen;
3702 } 3702 }
3703 /* apply extent size hints if obtained earlier */ 3703 /* apply extent size hints if obtained earlier */
3704 if (unlikely(align)) { 3704 if (align) {
3705 args.prod = align; 3705 args.prod = align;
3706 if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod))) 3706 if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
3707 args.mod = (xfs_extlen_t)(args.prod - args.mod); 3707 args.mod = (xfs_extlen_t)(args.prod - args.mod);
@@ -4514,8 +4514,6 @@ xfs_bmapi_write(
4514 int n; /* current extent index */ 4514 int n; /* current extent index */
4515 xfs_fileoff_t obno; /* old block number (offset) */ 4515 xfs_fileoff_t obno; /* old block number (offset) */
4516 int whichfork; /* data or attr fork */ 4516 int whichfork; /* data or attr fork */
4517 char inhole; /* current location is hole in file */
4518 char wasdelay; /* old extent was delayed */
4519 4517
4520#ifdef DEBUG 4518#ifdef DEBUG
4521 xfs_fileoff_t orig_bno; /* original block number value */ 4519 xfs_fileoff_t orig_bno; /* original block number value */
@@ -4603,22 +4601,44 @@ xfs_bmapi_write(
4603 bma.firstblock = firstblock; 4601 bma.firstblock = firstblock;
4604 4602
4605 while (bno < end && n < *nmap) { 4603 while (bno < end && n < *nmap) {
4606 inhole = eof || bma.got.br_startoff > bno; 4604 bool need_alloc = false, wasdelay = false;
4607 wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
4608 4605
4609 /* 4606 /* in hole or beyoned EOF? */
4610 * Make sure we only reflink into a hole. 4607 if (eof || bma.got.br_startoff > bno) {
4611 */ 4608 if (flags & XFS_BMAPI_DELALLOC) {
4612 if (flags & XFS_BMAPI_REMAP) 4609 /*
4613 ASSERT(inhole); 4610 * For the COW fork we can reasonably get a
4614 if (flags & XFS_BMAPI_COWFORK) 4611 * request for converting an extent that races
4615 ASSERT(!inhole); 4612 * with other threads already having converted
4613 * part of it, as there converting COW to
4614 * regular blocks is not protected using the
4615 * IOLOCK.
4616 */
4617 ASSERT(flags & XFS_BMAPI_COWFORK);
4618 if (!(flags & XFS_BMAPI_COWFORK)) {
4619 error = -EIO;
4620 goto error0;
4621 }
4622
4623 if (eof || bno >= end)
4624 break;
4625 } else {
4626 need_alloc = true;
4627 }
4628 } else {
4629 /*
4630 * Make sure we only reflink into a hole.
4631 */
4632 ASSERT(!(flags & XFS_BMAPI_REMAP));
4633 if (isnullstartblock(bma.got.br_startblock))
4634 wasdelay = true;
4635 }
4616 4636
4617 /* 4637 /*
4618 * First, deal with the hole before the allocated space 4638 * First, deal with the hole before the allocated space
4619 * that we found, if any. 4639 * that we found, if any.
4620 */ 4640 */
4621 if (inhole || wasdelay) { 4641 if (need_alloc || wasdelay) {
4622 bma.eof = eof; 4642 bma.eof = eof;
4623 bma.conv = !!(flags & XFS_BMAPI_CONVERT); 4643 bma.conv = !!(flags & XFS_BMAPI_CONVERT);
4624 bma.wasdel = wasdelay; 4644 bma.wasdel = wasdelay;