|
@@ -131,20 +131,29 @@ xfs_iomap_write_direct(
|
|
uint qblocks, resblks, resrtextents;
|
|
uint qblocks, resblks, resrtextents;
|
|
int committed;
|
|
int committed;
|
|
int error;
|
|
int error;
|
|
-
|
|
|
|
- error = xfs_qm_dqattach(ip, 0);
|
|
|
|
- if (error)
|
|
|
|
- return error;
|
|
|
|
|
|
+ int lockmode;
|
|
|
|
|
|
rt = XFS_IS_REALTIME_INODE(ip);
|
|
rt = XFS_IS_REALTIME_INODE(ip);
|
|
extsz = xfs_get_extsz_hint(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);
|
|
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
|
last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
|
|
last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
|
|
if ((offset + count) > XFS_ISIZE(ip)) {
|
|
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);
|
|
error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb);
|
|
if (error)
|
|
if (error)
|
|
- return error;
|
|
|
|
|
|
+ goto out_unlock;
|
|
} else {
|
|
} else {
|
|
if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
|
|
if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
|
|
last_fsb = MIN(last_fsb, (xfs_fileoff_t)
|
|
last_fsb = MIN(last_fsb, (xfs_fileoff_t)
|
|
@@ -173,6 +182,15 @@ xfs_iomap_write_direct(
|
|
quota_flag = XFS_QMOPT_RES_REGBLKS;
|
|
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
|
|
* Allocate and setup the transaction
|
|
*/
|
|
*/
|
|
@@ -187,7 +205,8 @@ xfs_iomap_write_direct(
|
|
return error;
|
|
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);
|
|
error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
|
|
if (error)
|
|
if (error)
|
|
@@ -229,7 +248,7 @@ xfs_iomap_write_direct(
|
|
error = xfs_alert_fsblock_zero(ip, imap);
|
|
error = xfs_alert_fsblock_zero(ip, imap);
|
|
|
|
|
|
out_unlock:
|
|
out_unlock:
|
|
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
|
|
|
|
+ xfs_iunlock(ip, lockmode);
|
|
return error;
|
|
return error;
|
|
|
|
|
|
out_bmap_cancel:
|
|
out_bmap_cancel:
|