diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-12-10 03:42:21 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-12-16 17:05:53 -0500 |
commit | 8ff2957d581582890693affc09920108a67cb05d (patch) | |
tree | 02e20726040eebef830731ecd61cb8a8f7844ade /fs/xfs | |
parent | a206c817c864583c44e2f418db8e6c7a000fbc38 (diff) |
xfs: simplify xfs_map_blocks
No need to lock the extent map exclusive when performing an
overwrite, we know the extent map must already have been loaded by
get_blocks. Apply the non-blocking inode semantics to all mapping
types instead of just delayed allocations. Remove the handling of
not yet allocated blocks for the IO_UNWRITTEN case - if an extent is
marked as unwritten allocated in the buffer it must already have an
extent on disk.
Add asserts to verify all the assumptions above in debug builds.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 77 |
1 files changed, 25 insertions, 52 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 365040f61d89..1252a8443429 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -313,81 +313,54 @@ xfs_map_blocks( | |||
313 | struct xfs_mount *mp = ip->i_mount; | 313 | struct xfs_mount *mp = ip->i_mount; |
314 | xfs_fileoff_t offset_fsb, end_fsb; | 314 | xfs_fileoff_t offset_fsb, end_fsb; |
315 | int error = 0; | 315 | int error = 0; |
316 | int lockmode = 0; | ||
317 | int bmapi_flags = XFS_BMAPI_ENTIRE; | 316 | int bmapi_flags = XFS_BMAPI_ENTIRE; |
318 | int nimaps = 1; | 317 | int nimaps = 1; |
319 | 318 | ||
320 | if (XFS_FORCED_SHUTDOWN(mp)) | 319 | if (XFS_FORCED_SHUTDOWN(mp)) |
321 | return -XFS_ERROR(EIO); | 320 | return -XFS_ERROR(EIO); |
322 | 321 | ||
323 | switch (type) { | 322 | if (type == IO_UNWRITTEN) |
324 | case IO_OVERWRITE: | ||
325 | lockmode = xfs_ilock_map_shared(ip); | ||
326 | break; | ||
327 | case IO_UNWRITTEN: | ||
328 | lockmode = XFS_ILOCK_EXCL; | ||
329 | bmapi_flags |= XFS_BMAPI_IGSTATE; | 323 | bmapi_flags |= XFS_BMAPI_IGSTATE; |
330 | xfs_ilock(ip, lockmode); | 324 | |
331 | break; | 325 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { |
332 | case IO_DELALLOC: | 326 | if (nonblocking) |
333 | lockmode = XFS_ILOCK_SHARED; | 327 | return -XFS_ERROR(EAGAIN); |
334 | 328 | xfs_ilock(ip, XFS_ILOCK_SHARED); | |
335 | if (!xfs_ilock_nowait(ip, lockmode)) { | ||
336 | if (nonblocking) | ||
337 | return -XFS_ERROR(EAGAIN); | ||
338 | xfs_ilock(ip, lockmode); | ||
339 | } | ||
340 | break; | ||
341 | } | 329 | } |
342 | 330 | ||
331 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || | ||
332 | (ip->i_df.if_flags & XFS_IFEXTENTS)); | ||
343 | ASSERT(offset <= mp->m_maxioffset); | 333 | ASSERT(offset <= mp->m_maxioffset); |
334 | |||
344 | if (offset + count > mp->m_maxioffset) | 335 | if (offset + count > mp->m_maxioffset) |
345 | count = mp->m_maxioffset - offset; | 336 | count = mp->m_maxioffset - offset; |
346 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 337 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
347 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 338 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
348 | |||
349 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, | 339 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, |
350 | bmapi_flags, NULL, 0, imap, &nimaps, NULL); | 340 | bmapi_flags, NULL, 0, imap, &nimaps, NULL); |
351 | if (error) | 341 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
352 | goto out; | ||
353 | |||
354 | switch (type) { | ||
355 | case IO_UNWRITTEN: | ||
356 | /* If we found an extent, return it */ | ||
357 | if (nimaps && | ||
358 | (imap->br_startblock != HOLESTARTBLOCK) && | ||
359 | (imap->br_startblock != DELAYSTARTBLOCK)) { | ||
360 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
361 | break; | ||
362 | } | ||
363 | 342 | ||
364 | error = xfs_iomap_write_delay(ip, offset, count, imap); | 343 | if (error) |
365 | if (!error) | 344 | return -XFS_ERROR(error); |
366 | trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); | ||
367 | break; | ||
368 | case IO_DELALLOC: | ||
369 | /* If we found an extent, return it */ | ||
370 | xfs_iunlock(ip, lockmode); | ||
371 | lockmode = 0; | ||
372 | |||
373 | if (nimaps && !isnullstartblock(imap->br_startblock)) { | ||
374 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
375 | break; | ||
376 | } | ||
377 | 345 | ||
346 | if (type == IO_DELALLOC && | ||
347 | (!nimaps || isnullstartblock(imap->br_startblock))) { | ||
378 | error = xfs_iomap_write_allocate(ip, offset, count, imap); | 348 | error = xfs_iomap_write_allocate(ip, offset, count, imap); |
379 | if (!error) | 349 | if (!error) |
380 | trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); | 350 | trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); |
381 | break; | 351 | return -XFS_ERROR(error); |
382 | default: | ||
383 | if (nimaps) | ||
384 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
385 | } | 352 | } |
386 | 353 | ||
387 | out: | 354 | #ifdef DEBUG |
388 | if (lockmode) | 355 | if (type == IO_UNWRITTEN) { |
389 | xfs_iunlock(ip, lockmode); | 356 | ASSERT(nimaps); |
390 | return -XFS_ERROR(error); | 357 | ASSERT(imap->br_startblock != HOLESTARTBLOCK); |
358 | ASSERT(imap->br_startblock != DELAYSTARTBLOCK); | ||
359 | } | ||
360 | #endif | ||
361 | if (nimaps) | ||
362 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
363 | return 0; | ||
391 | } | 364 | } |
392 | 365 | ||
393 | STATIC int | 366 | STATIC int |