Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 307707
b: refs/heads/master
c: 507630b
h: refs/heads/master
i:
  307705: 05daacb
  307703: e9c404d
v: v3
  • Loading branch information
Dave Chinner authored and Ben Myers committed May 14, 2012
1 parent 881f98c commit fa317f9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 193aec10504e4c24521449c46317282141fb36e8
refs/heads/master: 507630b29f13a3d8689895618b12015308402e22
30 changes: 26 additions & 4 deletions trunk/fs/xfs/xfs_aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1146,7 +1146,14 @@ __xfs_get_blocks(
if (!create && direct && offset >= i_size_read(inode))
return 0;

if (create) {
/*
* Direct I/O is usually done on preallocated files, so try getting
* a block mapping without an exclusive lock first. For buffered
* writes we already have the exclusive iolock anyway, so avoiding
* a lock roundtrip here by taking the ilock exclusive from the
* beginning is a useful micro optimization.
*/
if (create && !direct) {
lockmode = XFS_ILOCK_EXCL;
xfs_ilock(ip, lockmode);
} else {
Expand All @@ -1169,22 +1176,37 @@ __xfs_get_blocks(
(imap.br_startblock == HOLESTARTBLOCK ||
imap.br_startblock == DELAYSTARTBLOCK))) {
if (direct) {
/*
* Drop the ilock in preparation for starting the block
* allocation transaction. It will be retaken
* exclusively inside xfs_iomap_write_direct for the
* actual allocation.
*/
xfs_iunlock(ip, lockmode);
error = xfs_iomap_write_direct(ip, offset, size,
&imap, nimaps);
if (error)
return -error;
} else {
/*
* Delalloc reservations do not require a transaction,
* we can go on without dropping the lock here.
*/
error = xfs_iomap_write_delay(ip, offset, size, &imap);
if (error)
goto out_unlock;

xfs_iunlock(ip, lockmode);
}
if (error)
goto out_unlock;

trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap);
} else if (nimaps) {
trace_xfs_get_blocks_found(ip, offset, size, 0, &imap);
xfs_iunlock(ip, lockmode);
} else {
trace_xfs_get_blocks_notfound(ip, offset, size);
goto out_unlock;
}
xfs_iunlock(ip, lockmode);

if (imap.br_startblock != HOLESTARTBLOCK &&
imap.br_startblock != DELAYSTARTBLOCK) {
Expand Down
45 changes: 19 additions & 26 deletions trunk/fs/xfs/xfs_iomap.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,7 @@ xfs_iomap_write_direct(
int committed;
int error;

/*
* Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read.
*/
error = xfs_qm_dqattach_locked(ip, 0);
error = xfs_qm_dqattach(ip, 0);
if (error)
return XFS_ERROR(error);

Expand All @@ -158,7 +154,7 @@ xfs_iomap_write_direct(
if ((offset + count) > XFS_ISIZE(ip)) {
error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb);
if (error)
goto error_out;
return XFS_ERROR(error);
} else {
if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
last_fsb = MIN(last_fsb, (xfs_fileoff_t)
Expand Down Expand Up @@ -190,7 +186,6 @@ xfs_iomap_write_direct(
/*
* Allocate and setup the transaction
*/
xfs_iunlock(ip, XFS_ILOCK_EXCL);
tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
error = xfs_trans_reserve(tp, resblks,
XFS_WRITE_LOG_RES(mp), resrtextents,
Expand All @@ -199,15 +194,16 @@ xfs_iomap_write_direct(
/*
* Check for running out of space, note: need lock to return
*/
if (error)
if (error) {
xfs_trans_cancel(tp, 0);
return XFS_ERROR(error);
}

xfs_ilock(ip, XFS_ILOCK_EXCL);
if (error)
goto error_out;

error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
if (error)
goto error1;
goto out_trans_cancel;

xfs_trans_ijoin(tp, ip, 0);

Expand All @@ -224,42 +220,39 @@ xfs_iomap_write_direct(
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flag,
&firstfsb, 0, imap, &nimaps, &free_list);
if (error)
goto error0;
goto out_bmap_cancel;

/*
* Complete the transaction
*/
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error)
goto error0;
goto out_bmap_cancel;
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
if (error)
goto error_out;
goto out_unlock;

/*
* Copy any maps to caller's array and return any error.
*/
if (nimaps == 0) {
error = ENOSPC;
goto error_out;
error = XFS_ERROR(ENOSPC);
goto out_unlock;
}

if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) {
if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip)))
error = xfs_alert_fsblock_zero(ip, imap);
goto error_out;
}

return 0;
out_unlock:
xfs_iunlock(ip, XFS_ILOCK_EXCL);
return error;

error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
out_bmap_cancel:
xfs_bmap_cancel(&free_list);
xfs_trans_unreserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);

error1: /* Just cancel transaction */
out_trans_cancel:
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);

error_out:
return XFS_ERROR(error);
goto out_unlock;
}

/*
Expand Down

0 comments on commit fa317f9

Please sign in to comment.