]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/xfs/xfs_iomap.c
Merge branch 'xfs-dax-updates' into for-next
[karo-tx-linux.git] / fs / xfs / xfs_iomap.c
index c3cb5a552c4eb2fae269bbed95e40c86fa8a93f5..f4f5b43cf64712cf8fe46924820142fc75a33e86 100644 (file)
@@ -132,6 +132,7 @@ xfs_iomap_write_direct(
        int             committed;
        int             error;
        int             lockmode;
+       int             bmapi_flags = XFS_BMAPI_PREALLOC;
 
        rt = XFS_IS_REALTIME_INODE(ip);
        extsz = xfs_get_extsz_hint(ip);
@@ -195,6 +196,23 @@ xfs_iomap_write_direct(
         * Allocate and setup the transaction
         */
        tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
+
+       /*
+        * For DAX, we do not allocate unwritten extents, but instead we zero
+        * the block before we commit the transaction.  Ideally we'd like to do
+        * this outside the transaction context, but if we commit and then crash
+        * we may not have zeroed the blocks and this will be exposed on
+        * recovery of the allocation. Hence we must zero before commit.
+        * Further, if we are mapping unwritten extents here, we need to zero
+        * and convert them to written so that we don't need an unwritten extent
+        * callback for DAX. This also means that we need to be able to dip into
+        * the reserve block pool if there is no space left but we need to do
+        * unwritten extent conversion.
+        */
+       if (IS_DAX(VFS_I(ip))) {
+               bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO;
+               tp->t_flags |= XFS_TRANS_RESERVE;
+       }
        error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write,
                                  resblks, resrtextents);
        /*
@@ -221,7 +239,7 @@ xfs_iomap_write_direct(
        xfs_bmap_init(&free_list, &firstfsb);
        nimaps = 1;
        error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
-                               XFS_BMAPI_PREALLOC, &firstfsb, resblks, imap,
+                               bmapi_flags, &firstfsb, resblks, imap,
                                &nimaps, &free_list);
        if (error)
                goto out_bmap_cancel;
@@ -232,6 +250,7 @@ xfs_iomap_write_direct(
        error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error)
                goto out_bmap_cancel;
+
        error = xfs_trans_commit(tp);
        if (error)
                goto out_unlock;