diff options
Diffstat (limited to 'fs/xfs/xfs_aops.c')
| -rw-r--r-- | fs/xfs/xfs_aops.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index e562dd43f41f..e57e2daa357c 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
| @@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) | |||
| 481 | * | 481 | * |
| 482 | * The fix is two passes across the ioend list - one to start writeback on the | 482 | * The fix is two passes across the ioend list - one to start writeback on the |
| 483 | * buffer_heads, and then submit them for I/O on the second pass. | 483 | * buffer_heads, and then submit them for I/O on the second pass. |
| 484 | * | ||
| 485 | * If @fail is non-zero, it means that we have a situation where some part of | ||
| 486 | * the submission process has failed after we have marked paged for writeback | ||
| 487 | * and unlocked them. In this situation, we need to fail the ioend chain rather | ||
| 488 | * than submit it to IO. This typically only happens on a filesystem shutdown. | ||
| 484 | */ | 489 | */ |
| 485 | STATIC void | 490 | STATIC void |
| 486 | xfs_submit_ioend( | 491 | xfs_submit_ioend( |
| 487 | struct writeback_control *wbc, | 492 | struct writeback_control *wbc, |
| 488 | xfs_ioend_t *ioend) | 493 | xfs_ioend_t *ioend, |
| 494 | int fail) | ||
| 489 | { | 495 | { |
| 490 | xfs_ioend_t *head = ioend; | 496 | xfs_ioend_t *head = ioend; |
| 491 | xfs_ioend_t *next; | 497 | xfs_ioend_t *next; |
| @@ -506,6 +512,18 @@ xfs_submit_ioend( | |||
| 506 | next = ioend->io_list; | 512 | next = ioend->io_list; |
| 507 | bio = NULL; | 513 | bio = NULL; |
| 508 | 514 | ||
| 515 | /* | ||
| 516 | * If we are failing the IO now, just mark the ioend with an | ||
| 517 | * error and finish it. This will run IO completion immediately | ||
| 518 | * as there is only one reference to the ioend at this point in | ||
| 519 | * time. | ||
| 520 | */ | ||
| 521 | if (fail) { | ||
| 522 | ioend->io_error = -fail; | ||
| 523 | xfs_finish_ioend(ioend); | ||
| 524 | continue; | ||
| 525 | } | ||
| 526 | |||
| 509 | for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { | 527 | for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { |
| 510 | 528 | ||
| 511 | if (!bio) { | 529 | if (!bio) { |
| @@ -1060,7 +1078,18 @@ xfs_vm_writepage( | |||
| 1060 | 1078 | ||
| 1061 | xfs_start_page_writeback(page, 1, count); | 1079 | xfs_start_page_writeback(page, 1, count); |
| 1062 | 1080 | ||
| 1063 | if (ioend && imap_valid) { | 1081 | /* if there is no IO to be submitted for this page, we are done */ |
| 1082 | if (!ioend) | ||
| 1083 | return 0; | ||
| 1084 | |||
| 1085 | ASSERT(iohead); | ||
| 1086 | |||
| 1087 | /* | ||
| 1088 | * Any errors from this point onwards need tobe reported through the IO | ||
| 1089 | * completion path as we have marked the initial page as under writeback | ||
| 1090 | * and unlocked it. | ||
| 1091 | */ | ||
| 1092 | if (imap_valid) { | ||
| 1064 | xfs_off_t end_index; | 1093 | xfs_off_t end_index; |
| 1065 | 1094 | ||
| 1066 | end_index = imap.br_startoff + imap.br_blockcount; | 1095 | end_index = imap.br_startoff + imap.br_blockcount; |
| @@ -1079,20 +1108,15 @@ xfs_vm_writepage( | |||
| 1079 | wbc, end_index); | 1108 | wbc, end_index); |
| 1080 | } | 1109 | } |
| 1081 | 1110 | ||
| 1082 | if (iohead) { | ||
| 1083 | /* | ||
| 1084 | * Reserve log space if we might write beyond the on-disk | ||
| 1085 | * inode size. | ||
| 1086 | */ | ||
| 1087 | if (ioend->io_type != XFS_IO_UNWRITTEN && | ||
| 1088 | xfs_ioend_is_append(ioend)) { | ||
| 1089 | err = xfs_setfilesize_trans_alloc(ioend); | ||
| 1090 | if (err) | ||
| 1091 | goto error; | ||
| 1092 | } | ||
| 1093 | 1111 | ||
| 1094 | xfs_submit_ioend(wbc, iohead); | 1112 | /* |
| 1095 | } | 1113 | * Reserve log space if we might write beyond the on-disk inode size. |
| 1114 | */ | ||
| 1115 | err = 0; | ||
| 1116 | if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend)) | ||
| 1117 | err = xfs_setfilesize_trans_alloc(ioend); | ||
| 1118 | |||
| 1119 | xfs_submit_ioend(wbc, iohead, err); | ||
| 1096 | 1120 | ||
| 1097 | return 0; | 1121 | return 0; |
| 1098 | 1122 | ||
