|
@@ -4514,8 +4514,6 @@ xfs_bmapi_write(
|
|
|
int n; /* current extent index */
|
|
|
xfs_fileoff_t obno; /* old block number (offset) */
|
|
|
int whichfork; /* data or attr fork */
|
|
|
- char inhole; /* current location is hole in file */
|
|
|
- char wasdelay; /* old extent was delayed */
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
xfs_fileoff_t orig_bno; /* original block number value */
|
|
@@ -4603,22 +4601,44 @@ xfs_bmapi_write(
|
|
|
bma.firstblock = firstblock;
|
|
|
|
|
|
while (bno < end && n < *nmap) {
|
|
|
- inhole = eof || bma.got.br_startoff > bno;
|
|
|
- wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
|
|
|
+ bool need_alloc = false, wasdelay = false;
|
|
|
|
|
|
- /*
|
|
|
- * Make sure we only reflink into a hole.
|
|
|
- */
|
|
|
- if (flags & XFS_BMAPI_REMAP)
|
|
|
- ASSERT(inhole);
|
|
|
- if (flags & XFS_BMAPI_COWFORK)
|
|
|
- ASSERT(!inhole);
|
|
|
+ /* in hole or beyoned EOF? */
|
|
|
+ if (eof || bma.got.br_startoff > bno) {
|
|
|
+ if (flags & XFS_BMAPI_DELALLOC) {
|
|
|
+ /*
|
|
|
+ * For the COW fork we can reasonably get a
|
|
|
+ * request for converting an extent that races
|
|
|
+ * with other threads already having converted
|
|
|
+ * part of it, as there converting COW to
|
|
|
+ * regular blocks is not protected using the
|
|
|
+ * IOLOCK.
|
|
|
+ */
|
|
|
+ ASSERT(flags & XFS_BMAPI_COWFORK);
|
|
|
+ if (!(flags & XFS_BMAPI_COWFORK)) {
|
|
|
+ error = -EIO;
|
|
|
+ goto error0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (eof || bno >= end)
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ need_alloc = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * Make sure we only reflink into a hole.
|
|
|
+ */
|
|
|
+ ASSERT(!(flags & XFS_BMAPI_REMAP));
|
|
|
+ if (isnullstartblock(bma.got.br_startblock))
|
|
|
+ wasdelay = true;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* First, deal with the hole before the allocated space
|
|
|
* that we found, if any.
|
|
|
*/
|
|
|
- if (inhole || wasdelay) {
|
|
|
+ if (need_alloc || wasdelay) {
|
|
|
bma.eof = eof;
|
|
|
bma.conv = !!(flags & XFS_BMAPI_CONVERT);
|
|
|
bma.wasdel = wasdelay;
|