aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iomap.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-03-27 10:34:50 -0400
committerBen Myers <bpm@sgi.com>2012-05-14 17:20:21 -0400
commit507630b29f13a3d8689895618b12015308402e22 (patch)
treec090f5d2592d6f453ab7dd0f2f61da2a7482e59a /fs/xfs/xfs_iomap.c
parent193aec10504e4c24521449c46317282141fb36e8 (diff)
xfs: use shared ilock mode for direct IO writes by default
For the direct IO write path, we only really need the ilock to be taken in exclusive mode during IO submission if we need to do extent allocation instead of all the time. Change the block mapping code to take the ilock in shared mode for the initial block mapping, and only retake it exclusively when we actually have to perform extent allocations. We were already dropping the ilock for the transaction allocation, so this doesn't introduce new race windows. Based on an earlier patch from Dave Chinner. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r--fs/xfs/xfs_iomap.c45
1 files changed, 19 insertions, 26 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 71a464503c43..47e714a7bf92 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -142,11 +142,7 @@ xfs_iomap_write_direct(
142 int committed; 142 int committed;
143 int error; 143 int error;
144 144
145 /* 145 error = xfs_qm_dqattach(ip, 0);
146 * Make sure that the dquots are there. This doesn't hold
147 * the ilock across a disk read.
148 */
149 error = xfs_qm_dqattach_locked(ip, 0);
150 if (error) 146 if (error)
151 return XFS_ERROR(error); 147 return XFS_ERROR(error);
152 148
@@ -158,7 +154,7 @@ xfs_iomap_write_direct(
158 if ((offset + count) > XFS_ISIZE(ip)) { 154 if ((offset + count) > XFS_ISIZE(ip)) {
159 error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb); 155 error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb);
160 if (error) 156 if (error)
161 goto error_out; 157 return XFS_ERROR(error);
162 } else { 158 } else {
163 if (nmaps && (imap->br_startblock == HOLESTARTBLOCK)) 159 if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
164 last_fsb = MIN(last_fsb, (xfs_fileoff_t) 160 last_fsb = MIN(last_fsb, (xfs_fileoff_t)
@@ -190,7 +186,6 @@ xfs_iomap_write_direct(
190 /* 186 /*
191 * Allocate and setup the transaction 187 * Allocate and setup the transaction
192 */ 188 */
193 xfs_iunlock(ip, XFS_ILOCK_EXCL);
194 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); 189 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
195 error = xfs_trans_reserve(tp, resblks, 190 error = xfs_trans_reserve(tp, resblks,
196 XFS_WRITE_LOG_RES(mp), resrtextents, 191 XFS_WRITE_LOG_RES(mp), resrtextents,
@@ -199,15 +194,16 @@ xfs_iomap_write_direct(
199 /* 194 /*
200 * Check for running out of space, note: need lock to return 195 * Check for running out of space, note: need lock to return
201 */ 196 */
202 if (error) 197 if (error) {
203 xfs_trans_cancel(tp, 0); 198 xfs_trans_cancel(tp, 0);
199 return XFS_ERROR(error);
200 }
201
204 xfs_ilock(ip, XFS_ILOCK_EXCL); 202 xfs_ilock(ip, XFS_ILOCK_EXCL);
205 if (error)
206 goto error_out;
207 203
208 error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag); 204 error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
209 if (error) 205 if (error)
210 goto error1; 206 goto out_trans_cancel;
211 207
212 xfs_trans_ijoin(tp, ip, 0); 208 xfs_trans_ijoin(tp, ip, 0);
213 209
@@ -224,42 +220,39 @@ xfs_iomap_write_direct(
224 error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flag, 220 error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flag,
225 &firstfsb, 0, imap, &nimaps, &free_list); 221 &firstfsb, 0, imap, &nimaps, &free_list);
226 if (error) 222 if (error)
227 goto error0; 223 goto out_bmap_cancel;
228 224
229 /* 225 /*
230 * Complete the transaction 226 * Complete the transaction
231 */ 227 */
232 error = xfs_bmap_finish(&tp, &free_list, &committed); 228 error = xfs_bmap_finish(&tp, &free_list, &committed);
233 if (error) 229 if (error)
234 goto error0; 230 goto out_bmap_cancel;
235 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 231 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
236 if (error) 232 if (error)
237 goto error_out; 233 goto out_unlock;
238 234
239 /* 235 /*
240 * Copy any maps to caller's array and return any error. 236 * Copy any maps to caller's array and return any error.
241 */ 237 */
242 if (nimaps == 0) { 238 if (nimaps == 0) {
243 error = ENOSPC; 239 error = XFS_ERROR(ENOSPC);
244 goto error_out; 240 goto out_unlock;
245 } 241 }
246 242
247 if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) { 243 if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip)))
248 error = xfs_alert_fsblock_zero(ip, imap); 244 error = xfs_alert_fsblock_zero(ip, imap);
249 goto error_out;
250 }
251 245
252 return 0; 246out_unlock:
247 xfs_iunlock(ip, XFS_ILOCK_EXCL);
248 return error;
253 249
254error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ 250out_bmap_cancel:
255 xfs_bmap_cancel(&free_list); 251 xfs_bmap_cancel(&free_list);
256 xfs_trans_unreserve_quota_nblks(tp, ip, qblocks, 0, quota_flag); 252 xfs_trans_unreserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
257 253out_trans_cancel:
258error1: /* Just cancel transaction */
259 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 254 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
260 255 goto out_unlock;
261error_out:
262 return XFS_ERROR(error);
263} 256}
264 257
265/* 258/*