]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_bmap.c
xfs: force writes to delalloc regions to unwritten
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_bmap.c
index ba2f7d0a0bca572428b5ae281187010bbb28d2c4..f4706b64f5fe3cc2c74c467e1b3acf94a8785633 100644 (file)
@@ -4138,17 +4138,7 @@ xfs_bmapi_allocate(
        bma->got.br_blockcount = bma->length;
        bma->got.br_state = XFS_EXT_NORM;
 
-       /*
-        * In the data fork, a wasdelay extent has been initialized, so
-        * shouldn't be flagged as unwritten.
-        *
-        * For the cow fork, however, we convert delalloc reservations
-        * (extents allocated for speculative preallocation) to
-        * allocated unwritten extents, and only convert the unwritten
-        * extents to real extents when we're about to write the data.
-        */
-       if ((!bma->wasdel || (bma->flags & XFS_BMAPI_COWFORK)) &&
-           (bma->flags & XFS_BMAPI_PREALLOC))
+       if (bma->flags & XFS_BMAPI_PREALLOC)
                bma->got.br_state = XFS_EXT_UNWRITTEN;
 
        if (bma->wasdel)
@@ -4556,8 +4546,23 @@ xfs_bmapi_convert_delalloc(
        bma.offset = bma.got.br_startoff;
        bma.length = max_t(xfs_filblks_t, bma.got.br_blockcount, MAXEXTLEN);
        bma.minleft = xfs_bmapi_minleft(tp, ip, whichfork);
+
+       /*
+        * When we're converting the delalloc reservations backing dirty pages
+        * in the page cache, we must be careful about how we create the new
+        * extents:
+        *
+        * New CoW fork extents are created unwritten, turned into real extents
+        * when we're about to write the data to disk, and mapped into the data
+        * fork after the write finishes.  End of story.
+        *
+        * New data fork extents must be mapped in as unwritten and converted
+        * to real extents after the write succeeds to avoid exposing stale
+        * disk contents if we crash.
+        */
+       bma.flags = XFS_BMAPI_PREALLOC;
        if (whichfork == XFS_COW_FORK)
-               bma.flags = XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC;
+               bma.flags |= XFS_BMAPI_COWFORK;
 
        if (!xfs_iext_peek_prev_extent(ifp, &bma.icur, &bma.prev))
                bma.prev.br_startoff = NULLFILEOFF;