diff options
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r-- | fs/xfs/xfs_iomap.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 7f537663365b..add06b4e9a63 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "xfs_utils.h" | 41 | #include "xfs_utils.h" |
42 | #include "xfs_iomap.h" | 42 | #include "xfs_iomap.h" |
43 | #include "xfs_trace.h" | 43 | #include "xfs_trace.h" |
44 | #include "xfs_icache.h" | ||
44 | 45 | ||
45 | 46 | ||
46 | #define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ | 47 | #define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ |
@@ -373,7 +374,7 @@ xfs_iomap_write_delay( | |||
373 | xfs_extlen_t extsz; | 374 | xfs_extlen_t extsz; |
374 | int nimaps; | 375 | int nimaps; |
375 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; | 376 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; |
376 | int prealloc, flushed = 0; | 377 | int prealloc; |
377 | int error; | 378 | int error; |
378 | 379 | ||
379 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 380 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
@@ -434,31 +435,29 @@ retry: | |||
434 | } | 435 | } |
435 | 436 | ||
436 | /* | 437 | /* |
437 | * If bmapi returned us nothing, we got either ENOSPC or EDQUOT. For | 438 | * If bmapi returned us nothing, we got either ENOSPC or EDQUOT. Retry |
438 | * ENOSPC, * flush all other inodes with delalloc blocks to free up | ||
439 | * some of the excess reserved metadata space. For both cases, retry | ||
440 | * without EOF preallocation. | 439 | * without EOF preallocation. |
441 | */ | 440 | */ |
442 | if (nimaps == 0) { | 441 | if (nimaps == 0) { |
443 | trace_xfs_delalloc_enospc(ip, offset, count); | 442 | trace_xfs_delalloc_enospc(ip, offset, count); |
444 | if (flushed) | 443 | if (prealloc) { |
445 | return XFS_ERROR(error ? error : ENOSPC); | 444 | prealloc = 0; |
446 | 445 | error = 0; | |
447 | if (error == ENOSPC) { | 446 | goto retry; |
448 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
449 | xfs_flush_inodes(ip); | ||
450 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
451 | } | 447 | } |
452 | 448 | return XFS_ERROR(error ? error : ENOSPC); | |
453 | flushed = 1; | ||
454 | error = 0; | ||
455 | prealloc = 0; | ||
456 | goto retry; | ||
457 | } | 449 | } |
458 | 450 | ||
459 | if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip))) | 451 | if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip))) |
460 | return xfs_alert_fsblock_zero(ip, &imap[0]); | 452 | return xfs_alert_fsblock_zero(ip, &imap[0]); |
461 | 453 | ||
454 | /* | ||
455 | * Tag the inode as speculatively preallocated so we can reclaim this | ||
456 | * space on demand, if necessary. | ||
457 | */ | ||
458 | if (prealloc) | ||
459 | xfs_inode_set_eofblocks_tag(ip); | ||
460 | |||
462 | *ret_imap = imap[0]; | 461 | *ret_imap = imap[0]; |
463 | return 0; | 462 | return 0; |
464 | } | 463 | } |