]> 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 b48c6b525e776b20d7dc5649b933863cd6966203..f4f5b43cf64712cf8fe46924820142fc75a33e86 100644 (file)
@@ -131,21 +131,30 @@ xfs_iomap_write_direct(
        uint            qblocks, resblks, resrtextents;
        int             committed;
        int             error;
+       int             lockmode;
        int             bmapi_flags = XFS_BMAPI_PREALLOC;
 
-       error = xfs_qm_dqattach(ip, 0);
-       if (error)
-               return error;
-
        rt = XFS_IS_REALTIME_INODE(ip);
        extsz = xfs_get_extsz_hint(ip);
+       lockmode = XFS_ILOCK_SHARED;    /* locked by caller */
+
+       ASSERT(xfs_isilocked(ip, lockmode));
 
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
        last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
        if ((offset + count) > XFS_ISIZE(ip)) {
+               /*
+                * Assert that the in-core extent list is present since this can
+                * call xfs_iread_extents() and we only have the ilock shared.
+                * This should be safe because the lock was held around a bmapi
+                * call in the caller and we only need it to access the in-core
+                * list.
+                */
+               ASSERT(XFS_IFORK_PTR(ip, XFS_DATA_FORK)->if_flags &
+                                                               XFS_IFEXTENTS);
                error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb);
                if (error)
-                       return error;
+                       goto out_unlock;
        } else {
                if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
                        last_fsb = MIN(last_fsb, (xfs_fileoff_t)
@@ -174,6 +183,15 @@ xfs_iomap_write_direct(
                quota_flag = XFS_QMOPT_RES_REGBLKS;
        }
 
+       /*
+        * Drop the shared lock acquired by the caller, attach the dquot if
+        * necessary and move on to transaction setup.
+        */
+       xfs_iunlock(ip, lockmode);
+       error = xfs_qm_dqattach(ip, 0);
+       if (error)
+               return error;
+
        /*
         * Allocate and setup the transaction
         */
@@ -205,7 +223,8 @@ xfs_iomap_write_direct(
                return error;
        }
 
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       lockmode = XFS_ILOCK_EXCL;
+       xfs_ilock(ip, lockmode);
 
        error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
        if (error)
@@ -220,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,
-                               bmapi_flags, &firstfsb, 0, imap,
+                               bmapi_flags, &firstfsb, resblks, imap,
                                &nimaps, &free_list);
        if (error)
                goto out_bmap_cancel;
@@ -248,7 +267,7 @@ xfs_iomap_write_direct(
                error = xfs_alert_fsblock_zero(ip, imap);
 
 out_unlock:
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       xfs_iunlock(ip, lockmode);
        return error;
 
 out_bmap_cancel:
@@ -689,7 +708,7 @@ xfs_iomap_write_allocate(
        count_fsb = imap->br_blockcount;
        map_start_fsb = imap->br_startoff;
 
-       XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
+       XFS_STATS_ADD(mp, xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
 
        while (count_fsb != 0) {
                /*
@@ -769,9 +788,9 @@ xfs_iomap_write_allocate(
                         * pointer that the caller gave to us.
                         */
                        error = xfs_bmapi_write(tp, ip, map_start_fsb,
-                                               count_fsb, 0,
-                                               &first_block, 1,
-                                               imap, &nimaps, &free_list);
+                                               count_fsb, 0, &first_block,
+                                               nres, imap, &nimaps,
+                                               &free_list);
                        if (error)
                                goto trans_cancel;
 
@@ -796,7 +815,7 @@ xfs_iomap_write_allocate(
                if ((offset_fsb >= imap->br_startoff) &&
                    (offset_fsb < (imap->br_startoff +
                                   imap->br_blockcount))) {
-                       XFS_STATS_INC(xs_xstrat_quick);
+                       XFS_STATS_INC(mp, xs_xstrat_quick);
                        return 0;
                }
 
@@ -885,8 +904,8 @@ xfs_iomap_write_unwritten(
                xfs_bmap_init(&free_list, &firstfsb);
                nimaps = 1;
                error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
-                                 XFS_BMAPI_CONVERT, &firstfsb,
-                                 1, &imap, &nimaps, &free_list);
+                                       XFS_BMAPI_CONVERT, &firstfsb, resblks,
+                                       &imap, &nimaps, &free_list);
                if (error)
                        goto error_on_bmapi_transaction;