diff options
author | Dave Chinner <dchinner@redhat.com> | 2012-03-27 10:34:50 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-05-14 17:20:21 -0400 |
commit | 507630b29f13a3d8689895618b12015308402e22 (patch) | |
tree | c090f5d2592d6f453ab7dd0f2f61da2a7482e59a /fs/xfs/xfs_iomap.c | |
parent | 193aec10504e4c24521449c46317282141fb36e8 (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.c | 45 |
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; | 246 | out_unlock: |
247 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
248 | return error; | ||
253 | 249 | ||
254 | error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ | 250 | out_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 | 253 | out_trans_cancel: | |
258 | error1: /* 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; | |
261 | error_out: | ||
262 | return XFS_ERROR(error); | ||
263 | } | 256 | } |
264 | 257 | ||
265 | /* | 258 | /* |