diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 48 |
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; |