diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-31 06:07:15 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-31 06:07:15 -0400 |
commit | e37c83c06c2690157a989df40dc99a6b61c9ea15 (patch) | |
tree | 024dfb8b2c9abeec9ca7cb0c0136c276d9aacc91 /fs/xfs/xfs_log.c | |
parent | ce1f7d30766f6549db6fa0b9e595e0d26a5b7d9a (diff) | |
parent | 67a3e12b05e055c0415c556a315a3d3eb637e29e (diff) |
Merge commit 'v2.6.35-rc1' into for-2.6.36
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r-- | fs/xfs/xfs_log.c | 834 |
1 files changed, 546 insertions, 288 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index e8fba92d7cd9..5215abc8023a 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -44,13 +44,8 @@ | |||
44 | 44 | ||
45 | kmem_zone_t *xfs_log_ticket_zone; | 45 | kmem_zone_t *xfs_log_ticket_zone; |
46 | 46 | ||
47 | #define xlog_write_adv_cnt(ptr, len, off, bytes) \ | ||
48 | { (ptr) += (bytes); \ | ||
49 | (len) -= (bytes); \ | ||
50 | (off) += (bytes);} | ||
51 | |||
52 | /* Local miscellaneous function prototypes */ | 47 | /* Local miscellaneous function prototypes */ |
53 | STATIC int xlog_commit_record(xfs_mount_t *mp, xlog_ticket_t *ticket, | 48 | STATIC int xlog_commit_record(struct log *log, struct xlog_ticket *ticket, |
54 | xlog_in_core_t **, xfs_lsn_t *); | 49 | xlog_in_core_t **, xfs_lsn_t *); |
55 | STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, | 50 | STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, |
56 | xfs_buftarg_t *log_target, | 51 | xfs_buftarg_t *log_target, |
@@ -59,11 +54,6 @@ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, | |||
59 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); | 54 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); |
60 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); | 55 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); |
61 | STATIC void xlog_dealloc_log(xlog_t *log); | 56 | STATIC void xlog_dealloc_log(xlog_t *log); |
62 | STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[], | ||
63 | int nentries, struct xlog_ticket *tic, | ||
64 | xfs_lsn_t *start_lsn, | ||
65 | xlog_in_core_t **commit_iclog, | ||
66 | uint flags); | ||
67 | 57 | ||
68 | /* local state machine functions */ | 58 | /* local state machine functions */ |
69 | STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); | 59 | STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); |
@@ -93,16 +83,8 @@ STATIC int xlog_regrant_write_log_space(xlog_t *log, | |||
93 | STATIC void xlog_ungrant_log_space(xlog_t *log, | 83 | STATIC void xlog_ungrant_log_space(xlog_t *log, |
94 | xlog_ticket_t *ticket); | 84 | xlog_ticket_t *ticket); |
95 | 85 | ||
96 | |||
97 | /* local ticket functions */ | ||
98 | STATIC xlog_ticket_t *xlog_ticket_alloc(xlog_t *log, | ||
99 | int unit_bytes, | ||
100 | int count, | ||
101 | char clientid, | ||
102 | uint flags); | ||
103 | |||
104 | #if defined(DEBUG) | 86 | #if defined(DEBUG) |
105 | STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr); | 87 | STATIC void xlog_verify_dest_ptr(xlog_t *log, char *ptr); |
106 | STATIC void xlog_verify_grant_head(xlog_t *log, int equals); | 88 | STATIC void xlog_verify_grant_head(xlog_t *log, int equals); |
107 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, | 89 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, |
108 | int count, boolean_t syncing); | 90 | int count, boolean_t syncing); |
@@ -258,7 +240,7 @@ xfs_log_done( | |||
258 | * If we get an error, just continue and give back the log ticket. | 240 | * If we get an error, just continue and give back the log ticket. |
259 | */ | 241 | */ |
260 | (((ticket->t_flags & XLOG_TIC_INITED) == 0) && | 242 | (((ticket->t_flags & XLOG_TIC_INITED) == 0) && |
261 | (xlog_commit_record(mp, ticket, iclog, &lsn)))) { | 243 | (xlog_commit_record(log, ticket, iclog, &lsn)))) { |
262 | lsn = (xfs_lsn_t) -1; | 244 | lsn = (xfs_lsn_t) -1; |
263 | if (ticket->t_flags & XLOG_TIC_PERM_RESERV) { | 245 | if (ticket->t_flags & XLOG_TIC_PERM_RESERV) { |
264 | flags |= XFS_LOG_REL_PERM_RESERV; | 246 | flags |= XFS_LOG_REL_PERM_RESERV; |
@@ -367,6 +349,15 @@ xfs_log_reserve( | |||
367 | ASSERT(flags & XFS_LOG_PERM_RESERV); | 349 | ASSERT(flags & XFS_LOG_PERM_RESERV); |
368 | internal_ticket = *ticket; | 350 | internal_ticket = *ticket; |
369 | 351 | ||
352 | /* | ||
353 | * this is a new transaction on the ticket, so we need to | ||
354 | * change the transaction ID so that the next transaction has a | ||
355 | * different TID in the log. Just add one to the existing tid | ||
356 | * so that we can see chains of rolling transactions in the log | ||
357 | * easily. | ||
358 | */ | ||
359 | internal_ticket->t_tid++; | ||
360 | |||
370 | trace_xfs_log_reserve(log, internal_ticket); | 361 | trace_xfs_log_reserve(log, internal_ticket); |
371 | 362 | ||
372 | xlog_grant_push_ail(mp, internal_ticket->t_unit_res); | 363 | xlog_grant_push_ail(mp, internal_ticket->t_unit_res); |
@@ -374,7 +365,8 @@ xfs_log_reserve( | |||
374 | } else { | 365 | } else { |
375 | /* may sleep if need to allocate more tickets */ | 366 | /* may sleep if need to allocate more tickets */ |
376 | internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt, | 367 | internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt, |
377 | client, flags); | 368 | client, flags, |
369 | KM_SLEEP|KM_MAYFAIL); | ||
378 | if (!internal_ticket) | 370 | if (!internal_ticket) |
379 | return XFS_ERROR(ENOMEM); | 371 | return XFS_ERROR(ENOMEM); |
380 | internal_ticket->t_trans_type = t_type; | 372 | internal_ticket->t_trans_type = t_type; |
@@ -459,6 +451,13 @@ xfs_log_mount( | |||
459 | /* Normal transactions can now occur */ | 451 | /* Normal transactions can now occur */ |
460 | mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY; | 452 | mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY; |
461 | 453 | ||
454 | /* | ||
455 | * Now the log has been fully initialised and we know were our | ||
456 | * space grant counters are, we can initialise the permanent ticket | ||
457 | * needed for delayed logging to work. | ||
458 | */ | ||
459 | xlog_cil_init_post_recovery(mp->m_log); | ||
460 | |||
462 | return 0; | 461 | return 0; |
463 | 462 | ||
464 | out_destroy_ail: | 463 | out_destroy_ail: |
@@ -516,18 +515,10 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
516 | #ifdef DEBUG | 515 | #ifdef DEBUG |
517 | xlog_in_core_t *first_iclog; | 516 | xlog_in_core_t *first_iclog; |
518 | #endif | 517 | #endif |
519 | xfs_log_iovec_t reg[1]; | ||
520 | xlog_ticket_t *tic = NULL; | 518 | xlog_ticket_t *tic = NULL; |
521 | xfs_lsn_t lsn; | 519 | xfs_lsn_t lsn; |
522 | int error; | 520 | int error; |
523 | 521 | ||
524 | /* the data section must be 32 bit size aligned */ | ||
525 | struct { | ||
526 | __uint16_t magic; | ||
527 | __uint16_t pad1; | ||
528 | __uint32_t pad2; /* may as well make it 64 bits */ | ||
529 | } magic = { XLOG_UNMOUNT_TYPE, 0, 0 }; | ||
530 | |||
531 | /* | 522 | /* |
532 | * Don't write out unmount record on read-only mounts. | 523 | * Don't write out unmount record on read-only mounts. |
533 | * Or, if we are doing a forced umount (typically because of IO errors). | 524 | * Or, if we are doing a forced umount (typically because of IO errors). |
@@ -549,16 +540,30 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
549 | } while (iclog != first_iclog); | 540 | } while (iclog != first_iclog); |
550 | #endif | 541 | #endif |
551 | if (! (XLOG_FORCED_SHUTDOWN(log))) { | 542 | if (! (XLOG_FORCED_SHUTDOWN(log))) { |
552 | reg[0].i_addr = (void*)&magic; | ||
553 | reg[0].i_len = sizeof(magic); | ||
554 | reg[0].i_type = XLOG_REG_TYPE_UNMOUNT; | ||
555 | |||
556 | error = xfs_log_reserve(mp, 600, 1, &tic, | 543 | error = xfs_log_reserve(mp, 600, 1, &tic, |
557 | XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE); | 544 | XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE); |
558 | if (!error) { | 545 | if (!error) { |
546 | /* the data section must be 32 bit size aligned */ | ||
547 | struct { | ||
548 | __uint16_t magic; | ||
549 | __uint16_t pad1; | ||
550 | __uint32_t pad2; /* may as well make it 64 bits */ | ||
551 | } magic = { | ||
552 | .magic = XLOG_UNMOUNT_TYPE, | ||
553 | }; | ||
554 | struct xfs_log_iovec reg = { | ||
555 | .i_addr = (void *)&magic, | ||
556 | .i_len = sizeof(magic), | ||
557 | .i_type = XLOG_REG_TYPE_UNMOUNT, | ||
558 | }; | ||
559 | struct xfs_log_vec vec = { | ||
560 | .lv_niovecs = 1, | ||
561 | .lv_iovecp = ®, | ||
562 | }; | ||
563 | |||
559 | /* remove inited flag */ | 564 | /* remove inited flag */ |
560 | ((xlog_ticket_t *)tic)->t_flags = 0; | 565 | tic->t_flags = 0; |
561 | error = xlog_write(mp, reg, 1, tic, &lsn, | 566 | error = xlog_write(log, &vec, tic, &lsn, |
562 | NULL, XLOG_UNMOUNT_TRANS); | 567 | NULL, XLOG_UNMOUNT_TRANS); |
563 | /* | 568 | /* |
564 | * At this point, we're umounting anyway, | 569 | * At this point, we're umounting anyway, |
@@ -648,10 +653,30 @@ xfs_log_unmount(xfs_mount_t *mp) | |||
648 | xlog_dealloc_log(mp->m_log); | 653 | xlog_dealloc_log(mp->m_log); |
649 | } | 654 | } |
650 | 655 | ||
656 | void | ||
657 | xfs_log_item_init( | ||
658 | struct xfs_mount *mp, | ||
659 | struct xfs_log_item *item, | ||
660 | int type, | ||
661 | struct xfs_item_ops *ops) | ||
662 | { | ||
663 | item->li_mountp = mp; | ||
664 | item->li_ailp = mp->m_ail; | ||
665 | item->li_type = type; | ||
666 | item->li_ops = ops; | ||
667 | item->li_lv = NULL; | ||
668 | |||
669 | INIT_LIST_HEAD(&item->li_ail); | ||
670 | INIT_LIST_HEAD(&item->li_cil); | ||
671 | } | ||
672 | |||
651 | /* | 673 | /* |
652 | * Write region vectors to log. The write happens using the space reservation | 674 | * Write region vectors to log. The write happens using the space reservation |
653 | * of the ticket (tic). It is not a requirement that all writes for a given | 675 | * of the ticket (tic). It is not a requirement that all writes for a given |
654 | * transaction occur with one call to xfs_log_write(). | 676 | * transaction occur with one call to xfs_log_write(). However, it is important |
677 | * to note that the transaction reservation code makes an assumption about the | ||
678 | * number of log headers a transaction requires that may be violated if you | ||
679 | * don't pass all the transaction vectors in one call.... | ||
655 | */ | 680 | */ |
656 | int | 681 | int |
657 | xfs_log_write( | 682 | xfs_log_write( |
@@ -663,11 +688,15 @@ xfs_log_write( | |||
663 | { | 688 | { |
664 | struct log *log = mp->m_log; | 689 | struct log *log = mp->m_log; |
665 | int error; | 690 | int error; |
691 | struct xfs_log_vec vec = { | ||
692 | .lv_niovecs = nentries, | ||
693 | .lv_iovecp = reg, | ||
694 | }; | ||
666 | 695 | ||
667 | if (XLOG_FORCED_SHUTDOWN(log)) | 696 | if (XLOG_FORCED_SHUTDOWN(log)) |
668 | return XFS_ERROR(EIO); | 697 | return XFS_ERROR(EIO); |
669 | 698 | ||
670 | error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0); | 699 | error = xlog_write(log, &vec, tic, start_lsn, NULL, 0); |
671 | if (error) | 700 | if (error) |
672 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | 701 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
673 | return error; | 702 | return error; |
@@ -745,9 +774,16 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
745 | 774 | ||
746 | /* | 775 | /* |
747 | * Determine if we have a transaction that has gone to disk | 776 | * Determine if we have a transaction that has gone to disk |
748 | * that needs to be covered. Log activity needs to be idle (no AIL and | 777 | * that needs to be covered. To begin the transition to the idle state |
749 | * nothing in the iclogs). And, we need to be in the right state indicating | 778 | * firstly the log needs to be idle (no AIL and nothing in the iclogs). |
750 | * something has gone out. | 779 | * If we are then in a state where covering is needed, the caller is informed |
780 | * that dummy transactions are required to move the log into the idle state. | ||
781 | * | ||
782 | * Because this is called as part of the sync process, we should also indicate | ||
783 | * that dummy transactions should be issued in anything but the covered or | ||
784 | * idle states. This ensures that the log tail is accurately reflected in | ||
785 | * the log at the end of the sync, hence if a crash occurrs avoids replay | ||
786 | * of transactions where the metadata is already on disk. | ||
751 | */ | 787 | */ |
752 | int | 788 | int |
753 | xfs_log_need_covered(xfs_mount_t *mp) | 789 | xfs_log_need_covered(xfs_mount_t *mp) |
@@ -759,17 +795,24 @@ xfs_log_need_covered(xfs_mount_t *mp) | |||
759 | return 0; | 795 | return 0; |
760 | 796 | ||
761 | spin_lock(&log->l_icloglock); | 797 | spin_lock(&log->l_icloglock); |
762 | if (((log->l_covered_state == XLOG_STATE_COVER_NEED) || | 798 | switch (log->l_covered_state) { |
763 | (log->l_covered_state == XLOG_STATE_COVER_NEED2)) | 799 | case XLOG_STATE_COVER_DONE: |
764 | && !xfs_trans_ail_tail(log->l_ailp) | 800 | case XLOG_STATE_COVER_DONE2: |
765 | && xlog_iclogs_empty(log)) { | 801 | case XLOG_STATE_COVER_IDLE: |
766 | if (log->l_covered_state == XLOG_STATE_COVER_NEED) | 802 | break; |
767 | log->l_covered_state = XLOG_STATE_COVER_DONE; | 803 | case XLOG_STATE_COVER_NEED: |
768 | else { | 804 | case XLOG_STATE_COVER_NEED2: |
769 | ASSERT(log->l_covered_state == XLOG_STATE_COVER_NEED2); | 805 | if (!xfs_trans_ail_tail(log->l_ailp) && |
770 | log->l_covered_state = XLOG_STATE_COVER_DONE2; | 806 | xlog_iclogs_empty(log)) { |
807 | if (log->l_covered_state == XLOG_STATE_COVER_NEED) | ||
808 | log->l_covered_state = XLOG_STATE_COVER_DONE; | ||
809 | else | ||
810 | log->l_covered_state = XLOG_STATE_COVER_DONE2; | ||
771 | } | 811 | } |
812 | /* FALLTHRU */ | ||
813 | default: | ||
772 | needed = 1; | 814 | needed = 1; |
815 | break; | ||
773 | } | 816 | } |
774 | spin_unlock(&log->l_icloglock); | 817 | spin_unlock(&log->l_icloglock); |
775 | return needed; | 818 | return needed; |
@@ -1006,6 +1049,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1006 | int i; | 1049 | int i; |
1007 | int iclogsize; | 1050 | int iclogsize; |
1008 | int error = ENOMEM; | 1051 | int error = ENOMEM; |
1052 | uint log2_size = 0; | ||
1009 | 1053 | ||
1010 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); | 1054 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); |
1011 | if (!log) { | 1055 | if (!log) { |
@@ -1031,29 +1075,30 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1031 | 1075 | ||
1032 | error = EFSCORRUPTED; | 1076 | error = EFSCORRUPTED; |
1033 | if (xfs_sb_version_hassector(&mp->m_sb)) { | 1077 | if (xfs_sb_version_hassector(&mp->m_sb)) { |
1034 | log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; | 1078 | log2_size = mp->m_sb.sb_logsectlog; |
1035 | if (log->l_sectbb_log < 0 || | 1079 | if (log2_size < BBSHIFT) { |
1036 | log->l_sectbb_log > mp->m_sectbb_log) { | 1080 | xlog_warn("XFS: Log sector size too small " |
1037 | xlog_warn("XFS: Log sector size (0x%x) out of range.", | 1081 | "(0x%x < 0x%x)", log2_size, BBSHIFT); |
1038 | log->l_sectbb_log); | ||
1039 | goto out_free_log; | 1082 | goto out_free_log; |
1040 | } | 1083 | } |
1041 | 1084 | ||
1042 | /* for larger sector sizes, must have v2 or external log */ | 1085 | log2_size -= BBSHIFT; |
1043 | if (log->l_sectbb_log != 0 && | 1086 | if (log2_size > mp->m_sectbb_log) { |
1044 | (log->l_logBBstart != 0 && | 1087 | xlog_warn("XFS: Log sector size too large " |
1045 | !xfs_sb_version_haslogv2(&mp->m_sb))) { | 1088 | "(0x%x > 0x%x)", log2_size, mp->m_sectbb_log); |
1046 | xlog_warn("XFS: log sector size (0x%x) invalid " | ||
1047 | "for configuration.", log->l_sectbb_log); | ||
1048 | goto out_free_log; | 1089 | goto out_free_log; |
1049 | } | 1090 | } |
1050 | if (mp->m_sb.sb_logsectlog < BBSHIFT) { | 1091 | |
1051 | xlog_warn("XFS: Log sector log (0x%x) too small.", | 1092 | /* for larger sector sizes, must have v2 or external log */ |
1052 | mp->m_sb.sb_logsectlog); | 1093 | if (log2_size && log->l_logBBstart > 0 && |
1094 | !xfs_sb_version_haslogv2(&mp->m_sb)) { | ||
1095 | |||
1096 | xlog_warn("XFS: log sector size (0x%x) invalid " | ||
1097 | "for configuration.", log2_size); | ||
1053 | goto out_free_log; | 1098 | goto out_free_log; |
1054 | } | 1099 | } |
1055 | } | 1100 | } |
1056 | log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; | 1101 | log->l_sectBBsize = 1 << log2_size; |
1057 | 1102 | ||
1058 | xlog_get_iclog_buffer_size(mp, log); | 1103 | xlog_get_iclog_buffer_size(mp, log); |
1059 | 1104 | ||
@@ -1133,6 +1178,9 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1133 | *iclogp = log->l_iclog; /* complete ring */ | 1178 | *iclogp = log->l_iclog; /* complete ring */ |
1134 | log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */ | 1179 | log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */ |
1135 | 1180 | ||
1181 | error = xlog_cil_init(log); | ||
1182 | if (error) | ||
1183 | goto out_free_iclog; | ||
1136 | return log; | 1184 | return log; |
1137 | 1185 | ||
1138 | out_free_iclog: | 1186 | out_free_iclog: |
@@ -1160,26 +1208,31 @@ out: | |||
1160 | * ticket. Return the lsn of the commit record. | 1208 | * ticket. Return the lsn of the commit record. |
1161 | */ | 1209 | */ |
1162 | STATIC int | 1210 | STATIC int |
1163 | xlog_commit_record(xfs_mount_t *mp, | 1211 | xlog_commit_record( |
1164 | xlog_ticket_t *ticket, | 1212 | struct log *log, |
1165 | xlog_in_core_t **iclog, | 1213 | struct xlog_ticket *ticket, |
1166 | xfs_lsn_t *commitlsnp) | 1214 | struct xlog_in_core **iclog, |
1215 | xfs_lsn_t *commitlsnp) | ||
1167 | { | 1216 | { |
1168 | int error; | 1217 | struct xfs_mount *mp = log->l_mp; |
1169 | xfs_log_iovec_t reg[1]; | 1218 | int error; |
1170 | 1219 | struct xfs_log_iovec reg = { | |
1171 | reg[0].i_addr = NULL; | 1220 | .i_addr = NULL, |
1172 | reg[0].i_len = 0; | 1221 | .i_len = 0, |
1173 | reg[0].i_type = XLOG_REG_TYPE_COMMIT; | 1222 | .i_type = XLOG_REG_TYPE_COMMIT, |
1223 | }; | ||
1224 | struct xfs_log_vec vec = { | ||
1225 | .lv_niovecs = 1, | ||
1226 | .lv_iovecp = ®, | ||
1227 | }; | ||
1174 | 1228 | ||
1175 | ASSERT_ALWAYS(iclog); | 1229 | ASSERT_ALWAYS(iclog); |
1176 | if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, | 1230 | error = xlog_write(log, &vec, ticket, commitlsnp, iclog, |
1177 | iclog, XLOG_COMMIT_TRANS))) { | 1231 | XLOG_COMMIT_TRANS); |
1232 | if (error) | ||
1178 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | 1233 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
1179 | } | ||
1180 | return error; | 1234 | return error; |
1181 | } /* xlog_commit_record */ | 1235 | } |
1182 | |||
1183 | 1236 | ||
1184 | /* | 1237 | /* |
1185 | * Push on the buffer cache code if we ever use more than 75% of the on-disk | 1238 | * Push on the buffer cache code if we ever use more than 75% of the on-disk |
@@ -1454,6 +1507,8 @@ xlog_dealloc_log(xlog_t *log) | |||
1454 | xlog_in_core_t *iclog, *next_iclog; | 1507 | xlog_in_core_t *iclog, *next_iclog; |
1455 | int i; | 1508 | int i; |
1456 | 1509 | ||
1510 | xlog_cil_destroy(log); | ||
1511 | |||
1457 | iclog = log->l_iclog; | 1512 | iclog = log->l_iclog; |
1458 | for (i=0; i<log->l_iclog_bufs; i++) { | 1513 | for (i=0; i<log->l_iclog_bufs; i++) { |
1459 | sv_destroy(&iclog->ic_force_wait); | 1514 | sv_destroy(&iclog->ic_force_wait); |
@@ -1496,8 +1551,10 @@ xlog_state_finish_copy(xlog_t *log, | |||
1496 | * print out info relating to regions written which consume | 1551 | * print out info relating to regions written which consume |
1497 | * the reservation | 1552 | * the reservation |
1498 | */ | 1553 | */ |
1499 | STATIC void | 1554 | void |
1500 | xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) | 1555 | xlog_print_tic_res( |
1556 | struct xfs_mount *mp, | ||
1557 | struct xlog_ticket *ticket) | ||
1501 | { | 1558 | { |
1502 | uint i; | 1559 | uint i; |
1503 | uint ophdr_spc = ticket->t_res_num_ophdrs * (uint)sizeof(xlog_op_header_t); | 1560 | uint ophdr_spc = ticket->t_res_num_ophdrs * (uint)sizeof(xlog_op_header_t); |
@@ -1597,6 +1654,196 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) | |||
1597 | "bad-rtype" : res_type_str[r_type-1]), | 1654 | "bad-rtype" : res_type_str[r_type-1]), |
1598 | ticket->t_res_arr[i].r_len); | 1655 | ticket->t_res_arr[i].r_len); |
1599 | } | 1656 | } |
1657 | |||
1658 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, | ||
1659 | "xfs_log_write: reservation ran out. Need to up reservation"); | ||
1660 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
1661 | } | ||
1662 | |||
1663 | /* | ||
1664 | * Calculate the potential space needed by the log vector. Each region gets | ||
1665 | * its own xlog_op_header_t and may need to be double word aligned. | ||
1666 | */ | ||
1667 | static int | ||
1668 | xlog_write_calc_vec_length( | ||
1669 | struct xlog_ticket *ticket, | ||
1670 | struct xfs_log_vec *log_vector) | ||
1671 | { | ||
1672 | struct xfs_log_vec *lv; | ||
1673 | int headers = 0; | ||
1674 | int len = 0; | ||
1675 | int i; | ||
1676 | |||
1677 | /* acct for start rec of xact */ | ||
1678 | if (ticket->t_flags & XLOG_TIC_INITED) | ||
1679 | headers++; | ||
1680 | |||
1681 | for (lv = log_vector; lv; lv = lv->lv_next) { | ||
1682 | headers += lv->lv_niovecs; | ||
1683 | |||
1684 | for (i = 0; i < lv->lv_niovecs; i++) { | ||
1685 | struct xfs_log_iovec *vecp = &lv->lv_iovecp[i]; | ||
1686 | |||
1687 | len += vecp->i_len; | ||
1688 | xlog_tic_add_region(ticket, vecp->i_len, vecp->i_type); | ||
1689 | } | ||
1690 | } | ||
1691 | |||
1692 | ticket->t_res_num_ophdrs += headers; | ||
1693 | len += headers * sizeof(struct xlog_op_header); | ||
1694 | |||
1695 | return len; | ||
1696 | } | ||
1697 | |||
1698 | /* | ||
1699 | * If first write for transaction, insert start record We can't be trying to | ||
1700 | * commit if we are inited. We can't have any "partial_copy" if we are inited. | ||
1701 | */ | ||
1702 | static int | ||
1703 | xlog_write_start_rec( | ||
1704 | struct xlog_op_header *ophdr, | ||
1705 | struct xlog_ticket *ticket) | ||
1706 | { | ||
1707 | if (!(ticket->t_flags & XLOG_TIC_INITED)) | ||
1708 | return 0; | ||
1709 | |||
1710 | ophdr->oh_tid = cpu_to_be32(ticket->t_tid); | ||
1711 | ophdr->oh_clientid = ticket->t_clientid; | ||
1712 | ophdr->oh_len = 0; | ||
1713 | ophdr->oh_flags = XLOG_START_TRANS; | ||
1714 | ophdr->oh_res2 = 0; | ||
1715 | |||
1716 | ticket->t_flags &= ~XLOG_TIC_INITED; | ||
1717 | |||
1718 | return sizeof(struct xlog_op_header); | ||
1719 | } | ||
1720 | |||
1721 | static xlog_op_header_t * | ||
1722 | xlog_write_setup_ophdr( | ||
1723 | struct log *log, | ||
1724 | struct xlog_op_header *ophdr, | ||
1725 | struct xlog_ticket *ticket, | ||
1726 | uint flags) | ||
1727 | { | ||
1728 | ophdr->oh_tid = cpu_to_be32(ticket->t_tid); | ||
1729 | ophdr->oh_clientid = ticket->t_clientid; | ||
1730 | ophdr->oh_res2 = 0; | ||
1731 | |||
1732 | /* are we copying a commit or unmount record? */ | ||
1733 | ophdr->oh_flags = flags; | ||
1734 | |||
1735 | /* | ||
1736 | * We've seen logs corrupted with bad transaction client ids. This | ||
1737 | * makes sure that XFS doesn't generate them on. Turn this into an EIO | ||
1738 | * and shut down the filesystem. | ||
1739 | */ | ||
1740 | switch (ophdr->oh_clientid) { | ||
1741 | case XFS_TRANSACTION: | ||
1742 | case XFS_VOLUME: | ||
1743 | case XFS_LOG: | ||
1744 | break; | ||
1745 | default: | ||
1746 | xfs_fs_cmn_err(CE_WARN, log->l_mp, | ||
1747 | "Bad XFS transaction clientid 0x%x in ticket 0x%p", | ||
1748 | ophdr->oh_clientid, ticket); | ||
1749 | return NULL; | ||
1750 | } | ||
1751 | |||
1752 | return ophdr; | ||
1753 | } | ||
1754 | |||
1755 | /* | ||
1756 | * Set up the parameters of the region copy into the log. This has | ||
1757 | * to handle region write split across multiple log buffers - this | ||
1758 | * state is kept external to this function so that this code can | ||
1759 | * can be written in an obvious, self documenting manner. | ||
1760 | */ | ||
1761 | static int | ||
1762 | xlog_write_setup_copy( | ||
1763 | struct xlog_ticket *ticket, | ||
1764 | struct xlog_op_header *ophdr, | ||
1765 | int space_available, | ||
1766 | int space_required, | ||
1767 | int *copy_off, | ||
1768 | int *copy_len, | ||
1769 | int *last_was_partial_copy, | ||
1770 | int *bytes_consumed) | ||
1771 | { | ||
1772 | int still_to_copy; | ||
1773 | |||
1774 | still_to_copy = space_required - *bytes_consumed; | ||
1775 | *copy_off = *bytes_consumed; | ||
1776 | |||
1777 | if (still_to_copy <= space_available) { | ||
1778 | /* write of region completes here */ | ||
1779 | *copy_len = still_to_copy; | ||
1780 | ophdr->oh_len = cpu_to_be32(*copy_len); | ||
1781 | if (*last_was_partial_copy) | ||
1782 | ophdr->oh_flags |= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS); | ||
1783 | *last_was_partial_copy = 0; | ||
1784 | *bytes_consumed = 0; | ||
1785 | return 0; | ||
1786 | } | ||
1787 | |||
1788 | /* partial write of region, needs extra log op header reservation */ | ||
1789 | *copy_len = space_available; | ||
1790 | ophdr->oh_len = cpu_to_be32(*copy_len); | ||
1791 | ophdr->oh_flags |= XLOG_CONTINUE_TRANS; | ||
1792 | if (*last_was_partial_copy) | ||
1793 | ophdr->oh_flags |= XLOG_WAS_CONT_TRANS; | ||
1794 | *bytes_consumed += *copy_len; | ||
1795 | (*last_was_partial_copy)++; | ||
1796 | |||
1797 | /* account for new log op header */ | ||
1798 | ticket->t_curr_res -= sizeof(struct xlog_op_header); | ||
1799 | ticket->t_res_num_ophdrs++; | ||
1800 | |||
1801 | return sizeof(struct xlog_op_header); | ||
1802 | } | ||
1803 | |||
1804 | static int | ||
1805 | xlog_write_copy_finish( | ||
1806 | struct log *log, | ||
1807 | struct xlog_in_core *iclog, | ||
1808 | uint flags, | ||
1809 | int *record_cnt, | ||
1810 | int *data_cnt, | ||
1811 | int *partial_copy, | ||
1812 | int *partial_copy_len, | ||
1813 | int log_offset, | ||
1814 | struct xlog_in_core **commit_iclog) | ||
1815 | { | ||
1816 | if (*partial_copy) { | ||
1817 | /* | ||
1818 | * This iclog has already been marked WANT_SYNC by | ||
1819 | * xlog_state_get_iclog_space. | ||
1820 | */ | ||
1821 | xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt); | ||
1822 | *record_cnt = 0; | ||
1823 | *data_cnt = 0; | ||
1824 | return xlog_state_release_iclog(log, iclog); | ||
1825 | } | ||
1826 | |||
1827 | *partial_copy = 0; | ||
1828 | *partial_copy_len = 0; | ||
1829 | |||
1830 | if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) { | ||
1831 | /* no more space in this iclog - push it. */ | ||
1832 | xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt); | ||
1833 | *record_cnt = 0; | ||
1834 | *data_cnt = 0; | ||
1835 | |||
1836 | spin_lock(&log->l_icloglock); | ||
1837 | xlog_state_want_sync(log, iclog); | ||
1838 | spin_unlock(&log->l_icloglock); | ||
1839 | |||
1840 | if (!commit_iclog) | ||
1841 | return xlog_state_release_iclog(log, iclog); | ||
1842 | ASSERT(flags & XLOG_COMMIT_TRANS); | ||
1843 | *commit_iclog = iclog; | ||
1844 | } | ||
1845 | |||
1846 | return 0; | ||
1600 | } | 1847 | } |
1601 | 1848 | ||
1602 | /* | 1849 | /* |
@@ -1639,211 +1886,163 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) | |||
1639 | * we don't update ic_offset until the end when we know exactly how many | 1886 | * we don't update ic_offset until the end when we know exactly how many |
1640 | * bytes have been written out. | 1887 | * bytes have been written out. |
1641 | */ | 1888 | */ |
1642 | STATIC int | 1889 | int |
1643 | xlog_write( | 1890 | xlog_write( |
1644 | struct xfs_mount *mp, | 1891 | struct log *log, |
1645 | struct xfs_log_iovec reg[], | 1892 | struct xfs_log_vec *log_vector, |
1646 | int nentries, | ||
1647 | struct xlog_ticket *ticket, | 1893 | struct xlog_ticket *ticket, |
1648 | xfs_lsn_t *start_lsn, | 1894 | xfs_lsn_t *start_lsn, |
1649 | struct xlog_in_core **commit_iclog, | 1895 | struct xlog_in_core **commit_iclog, |
1650 | uint flags) | 1896 | uint flags) |
1651 | { | 1897 | { |
1652 | xlog_t *log = mp->m_log; | 1898 | struct xlog_in_core *iclog = NULL; |
1653 | xlog_in_core_t *iclog = NULL; /* ptr to current in-core log */ | 1899 | struct xfs_log_iovec *vecp; |
1654 | xlog_op_header_t *logop_head; /* ptr to log operation header */ | 1900 | struct xfs_log_vec *lv; |
1655 | __psint_t ptr; /* copy address into data region */ | 1901 | int len; |
1656 | int len; /* # xlog_write() bytes 2 still copy */ | 1902 | int index; |
1657 | int index; /* region index currently copying */ | 1903 | int partial_copy = 0; |
1658 | int log_offset; /* offset (from 0) into data region */ | 1904 | int partial_copy_len = 0; |
1659 | int start_rec_copy; /* # bytes to copy for start record */ | 1905 | int contwr = 0; |
1660 | int partial_copy; /* did we split a region? */ | 1906 | int record_cnt = 0; |
1661 | int partial_copy_len;/* # bytes copied if split region */ | 1907 | int data_cnt = 0; |
1662 | int need_copy; /* # bytes need to memcpy this region */ | 1908 | int error; |
1663 | int copy_len; /* # bytes actually memcpy'ing */ | ||
1664 | int copy_off; /* # bytes from entry start */ | ||
1665 | int contwr; /* continued write of in-core log? */ | ||
1666 | int error; | ||
1667 | int record_cnt = 0, data_cnt = 0; | ||
1668 | |||
1669 | partial_copy_len = partial_copy = 0; | ||
1670 | |||
1671 | /* Calculate potential maximum space. Each region gets its own | ||
1672 | * xlog_op_header_t and may need to be double word aligned. | ||
1673 | */ | ||
1674 | len = 0; | ||
1675 | if (ticket->t_flags & XLOG_TIC_INITED) { /* acct for start rec of xact */ | ||
1676 | len += sizeof(xlog_op_header_t); | ||
1677 | ticket->t_res_num_ophdrs++; | ||
1678 | } | ||
1679 | |||
1680 | for (index = 0; index < nentries; index++) { | ||
1681 | len += sizeof(xlog_op_header_t); /* each region gets >= 1 */ | ||
1682 | ticket->t_res_num_ophdrs++; | ||
1683 | len += reg[index].i_len; | ||
1684 | xlog_tic_add_region(ticket, reg[index].i_len, reg[index].i_type); | ||
1685 | } | ||
1686 | contwr = *start_lsn = 0; | ||
1687 | 1909 | ||
1688 | if (ticket->t_curr_res < len) { | 1910 | *start_lsn = 0; |
1689 | xlog_print_tic_res(mp, ticket); | ||
1690 | #ifdef DEBUG | ||
1691 | xlog_panic( | ||
1692 | "xfs_log_write: reservation ran out. Need to up reservation"); | ||
1693 | #else | ||
1694 | /* Customer configurable panic */ | ||
1695 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, | ||
1696 | "xfs_log_write: reservation ran out. Need to up reservation"); | ||
1697 | /* If we did not panic, shutdown the filesystem */ | ||
1698 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
1699 | #endif | ||
1700 | } else | ||
1701 | ticket->t_curr_res -= len; | ||
1702 | 1911 | ||
1703 | for (index = 0; index < nentries; ) { | 1912 | len = xlog_write_calc_vec_length(ticket, log_vector); |
1704 | if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket, | 1913 | if (log->l_cilp) { |
1705 | &contwr, &log_offset))) | 1914 | /* |
1706 | return error; | 1915 | * Region headers and bytes are already accounted for. |
1916 | * We only need to take into account start records and | ||
1917 | * split regions in this function. | ||
1918 | */ | ||
1919 | if (ticket->t_flags & XLOG_TIC_INITED) | ||
1920 | ticket->t_curr_res -= sizeof(xlog_op_header_t); | ||
1707 | 1921 | ||
1708 | ASSERT(log_offset <= iclog->ic_size - 1); | 1922 | /* |
1709 | ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset); | 1923 | * Commit record headers need to be accounted for. These |
1924 | * come in as separate writes so are easy to detect. | ||
1925 | */ | ||
1926 | if (flags & (XLOG_COMMIT_TRANS | XLOG_UNMOUNT_TRANS)) | ||
1927 | ticket->t_curr_res -= sizeof(xlog_op_header_t); | ||
1928 | } else | ||
1929 | ticket->t_curr_res -= len; | ||
1930 | |||
1931 | if (ticket->t_curr_res < 0) | ||
1932 | xlog_print_tic_res(log->l_mp, ticket); | ||
1933 | |||
1934 | index = 0; | ||
1935 | lv = log_vector; | ||
1936 | vecp = lv->lv_iovecp; | ||
1937 | while (lv && index < lv->lv_niovecs) { | ||
1938 | void *ptr; | ||
1939 | int log_offset; | ||
1940 | |||
1941 | error = xlog_state_get_iclog_space(log, len, &iclog, ticket, | ||
1942 | &contwr, &log_offset); | ||
1943 | if (error) | ||
1944 | return error; | ||
1710 | 1945 | ||
1711 | /* start_lsn is the first lsn written to. That's all we need. */ | 1946 | ASSERT(log_offset <= iclog->ic_size - 1); |
1712 | if (! *start_lsn) | 1947 | ptr = iclog->ic_datap + log_offset; |
1713 | *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn); | ||
1714 | 1948 | ||
1715 | /* This loop writes out as many regions as can fit in the amount | 1949 | /* start_lsn is the first lsn written to. That's all we need. */ |
1716 | * of space which was allocated by xlog_state_get_iclog_space(). | 1950 | if (!*start_lsn) |
1717 | */ | 1951 | *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn); |
1718 | while (index < nentries) { | ||
1719 | ASSERT(reg[index].i_len % sizeof(__int32_t) == 0); | ||
1720 | ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0); | ||
1721 | start_rec_copy = 0; | ||
1722 | |||
1723 | /* If first write for transaction, insert start record. | ||
1724 | * We can't be trying to commit if we are inited. We can't | ||
1725 | * have any "partial_copy" if we are inited. | ||
1726 | */ | ||
1727 | if (ticket->t_flags & XLOG_TIC_INITED) { | ||
1728 | logop_head = (xlog_op_header_t *)ptr; | ||
1729 | logop_head->oh_tid = cpu_to_be32(ticket->t_tid); | ||
1730 | logop_head->oh_clientid = ticket->t_clientid; | ||
1731 | logop_head->oh_len = 0; | ||
1732 | logop_head->oh_flags = XLOG_START_TRANS; | ||
1733 | logop_head->oh_res2 = 0; | ||
1734 | ticket->t_flags &= ~XLOG_TIC_INITED; /* clear bit */ | ||
1735 | record_cnt++; | ||
1736 | |||
1737 | start_rec_copy = sizeof(xlog_op_header_t); | ||
1738 | xlog_write_adv_cnt(ptr, len, log_offset, start_rec_copy); | ||
1739 | } | ||
1740 | 1952 | ||
1741 | /* Copy log operation header directly into data section */ | 1953 | /* |
1742 | logop_head = (xlog_op_header_t *)ptr; | 1954 | * This loop writes out as many regions as can fit in the amount |
1743 | logop_head->oh_tid = cpu_to_be32(ticket->t_tid); | 1955 | * of space which was allocated by xlog_state_get_iclog_space(). |
1744 | logop_head->oh_clientid = ticket->t_clientid; | 1956 | */ |
1745 | logop_head->oh_res2 = 0; | 1957 | while (lv && index < lv->lv_niovecs) { |
1958 | struct xfs_log_iovec *reg = &vecp[index]; | ||
1959 | struct xlog_op_header *ophdr; | ||
1960 | int start_rec_copy; | ||
1961 | int copy_len; | ||
1962 | int copy_off; | ||
1963 | |||
1964 | ASSERT(reg->i_len % sizeof(__int32_t) == 0); | ||
1965 | ASSERT((unsigned long)ptr % sizeof(__int32_t) == 0); | ||
1966 | |||
1967 | start_rec_copy = xlog_write_start_rec(ptr, ticket); | ||
1968 | if (start_rec_copy) { | ||
1969 | record_cnt++; | ||
1970 | xlog_write_adv_cnt(&ptr, &len, &log_offset, | ||
1971 | start_rec_copy); | ||
1972 | } | ||
1746 | 1973 | ||
1747 | /* header copied directly */ | 1974 | ophdr = xlog_write_setup_ophdr(log, ptr, ticket, flags); |
1748 | xlog_write_adv_cnt(ptr, len, log_offset, sizeof(xlog_op_header_t)); | 1975 | if (!ophdr) |
1976 | return XFS_ERROR(EIO); | ||
1749 | 1977 | ||
1750 | /* are we copying a commit or unmount record? */ | 1978 | xlog_write_adv_cnt(&ptr, &len, &log_offset, |
1751 | logop_head->oh_flags = flags; | 1979 | sizeof(struct xlog_op_header)); |
1980 | |||
1981 | len += xlog_write_setup_copy(ticket, ophdr, | ||
1982 | iclog->ic_size-log_offset, | ||
1983 | reg->i_len, | ||
1984 | ©_off, ©_len, | ||
1985 | &partial_copy, | ||
1986 | &partial_copy_len); | ||
1987 | xlog_verify_dest_ptr(log, ptr); | ||
1988 | |||
1989 | /* copy region */ | ||
1990 | ASSERT(copy_len >= 0); | ||
1991 | memcpy(ptr, reg->i_addr + copy_off, copy_len); | ||
1992 | xlog_write_adv_cnt(&ptr, &len, &log_offset, copy_len); | ||
1993 | |||
1994 | copy_len += start_rec_copy + sizeof(xlog_op_header_t); | ||
1995 | record_cnt++; | ||
1996 | data_cnt += contwr ? copy_len : 0; | ||
1997 | |||
1998 | error = xlog_write_copy_finish(log, iclog, flags, | ||
1999 | &record_cnt, &data_cnt, | ||
2000 | &partial_copy, | ||
2001 | &partial_copy_len, | ||
2002 | log_offset, | ||
2003 | commit_iclog); | ||
2004 | if (error) | ||
2005 | return error; | ||
1752 | 2006 | ||
1753 | /* | 2007 | /* |
1754 | * We've seen logs corrupted with bad transaction client | 2008 | * if we had a partial copy, we need to get more iclog |
1755 | * ids. This makes sure that XFS doesn't generate them on. | 2009 | * space but we don't want to increment the region |
1756 | * Turn this into an EIO and shut down the filesystem. | 2010 | * index because there is still more is this region to |
1757 | */ | 2011 | * write. |
1758 | switch (logop_head->oh_clientid) { | 2012 | * |
1759 | case XFS_TRANSACTION: | 2013 | * If we completed writing this region, and we flushed |
1760 | case XFS_VOLUME: | 2014 | * the iclog (indicated by resetting of the record |
1761 | case XFS_LOG: | 2015 | * count), then we also need to get more log space. If |
1762 | break; | 2016 | * this was the last record, though, we are done and |
1763 | default: | 2017 | * can just return. |
1764 | xfs_fs_cmn_err(CE_WARN, mp, | 2018 | */ |
1765 | "Bad XFS transaction clientid 0x%x in ticket 0x%p", | 2019 | if (partial_copy) |
1766 | logop_head->oh_clientid, ticket); | 2020 | break; |
1767 | return XFS_ERROR(EIO); | ||
1768 | } | ||
1769 | 2021 | ||
1770 | /* Partial write last time? => (partial_copy != 0) | 2022 | if (++index == lv->lv_niovecs) { |
1771 | * need_copy is the amount we'd like to copy if everything could | 2023 | lv = lv->lv_next; |
1772 | * fit in the current memcpy. | 2024 | index = 0; |
1773 | */ | 2025 | if (lv) |
1774 | need_copy = reg[index].i_len - partial_copy_len; | 2026 | vecp = lv->lv_iovecp; |
1775 | 2027 | } | |
1776 | copy_off = partial_copy_len; | 2028 | if (record_cnt == 0) { |
1777 | if (need_copy <= iclog->ic_size - log_offset) { /*complete write */ | 2029 | if (!lv) |
1778 | copy_len = need_copy; | 2030 | return 0; |
1779 | logop_head->oh_len = cpu_to_be32(copy_len); | 2031 | break; |
1780 | if (partial_copy) | 2032 | } |
1781 | logop_head->oh_flags|= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS); | ||
1782 | partial_copy_len = partial_copy = 0; | ||
1783 | } else { /* partial write */ | ||
1784 | copy_len = iclog->ic_size - log_offset; | ||
1785 | logop_head->oh_len = cpu_to_be32(copy_len); | ||
1786 | logop_head->oh_flags |= XLOG_CONTINUE_TRANS; | ||
1787 | if (partial_copy) | ||
1788 | logop_head->oh_flags |= XLOG_WAS_CONT_TRANS; | ||
1789 | partial_copy_len += copy_len; | ||
1790 | partial_copy++; | ||
1791 | len += sizeof(xlog_op_header_t); /* from splitting of region */ | ||
1792 | /* account for new log op header */ | ||
1793 | ticket->t_curr_res -= sizeof(xlog_op_header_t); | ||
1794 | ticket->t_res_num_ophdrs++; | ||
1795 | } | ||
1796 | xlog_verify_dest_ptr(log, ptr); | ||
1797 | |||
1798 | /* copy region */ | ||
1799 | ASSERT(copy_len >= 0); | ||
1800 | memcpy((xfs_caddr_t)ptr, reg[index].i_addr + copy_off, copy_len); | ||
1801 | xlog_write_adv_cnt(ptr, len, log_offset, copy_len); | ||
1802 | |||
1803 | /* make copy_len total bytes copied, including headers */ | ||
1804 | copy_len += start_rec_copy + sizeof(xlog_op_header_t); | ||
1805 | record_cnt++; | ||
1806 | data_cnt += contwr ? copy_len : 0; | ||
1807 | if (partial_copy) { /* copied partial region */ | ||
1808 | /* already marked WANT_SYNC by xlog_state_get_iclog_space */ | ||
1809 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1810 | record_cnt = data_cnt = 0; | ||
1811 | if ((error = xlog_state_release_iclog(log, iclog))) | ||
1812 | return error; | ||
1813 | break; /* don't increment index */ | ||
1814 | } else { /* copied entire region */ | ||
1815 | index++; | ||
1816 | partial_copy_len = partial_copy = 0; | ||
1817 | |||
1818 | if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) { | ||
1819 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1820 | record_cnt = data_cnt = 0; | ||
1821 | spin_lock(&log->l_icloglock); | ||
1822 | xlog_state_want_sync(log, iclog); | ||
1823 | spin_unlock(&log->l_icloglock); | ||
1824 | if (commit_iclog) { | ||
1825 | ASSERT(flags & XLOG_COMMIT_TRANS); | ||
1826 | *commit_iclog = iclog; | ||
1827 | } else if ((error = xlog_state_release_iclog(log, iclog))) | ||
1828 | return error; | ||
1829 | if (index == nentries) | ||
1830 | return 0; /* we are done */ | ||
1831 | else | ||
1832 | break; | ||
1833 | } | 2033 | } |
1834 | } /* if (partial_copy) */ | 2034 | } |
1835 | } /* while (index < nentries) */ | 2035 | |
1836 | } /* for (index = 0; index < nentries; ) */ | 2036 | ASSERT(len == 0); |
1837 | ASSERT(len == 0); | 2037 | |
2038 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
2039 | if (!commit_iclog) | ||
2040 | return xlog_state_release_iclog(log, iclog); | ||
1838 | 2041 | ||
1839 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1840 | if (commit_iclog) { | ||
1841 | ASSERT(flags & XLOG_COMMIT_TRANS); | 2042 | ASSERT(flags & XLOG_COMMIT_TRANS); |
1842 | *commit_iclog = iclog; | 2043 | *commit_iclog = iclog; |
1843 | return 0; | 2044 | return 0; |
1844 | } | 2045 | } |
1845 | return xlog_state_release_iclog(log, iclog); | ||
1846 | } /* xlog_write */ | ||
1847 | 2046 | ||
1848 | 2047 | ||
1849 | /***************************************************************************** | 2048 | /***************************************************************************** |
@@ -2826,6 +3025,8 @@ _xfs_log_force( | |||
2826 | 3025 | ||
2827 | XFS_STATS_INC(xs_log_force); | 3026 | XFS_STATS_INC(xs_log_force); |
2828 | 3027 | ||
3028 | xlog_cil_push(log, 1); | ||
3029 | |||
2829 | spin_lock(&log->l_icloglock); | 3030 | spin_lock(&log->l_icloglock); |
2830 | 3031 | ||
2831 | iclog = log->l_iclog; | 3032 | iclog = log->l_iclog; |
@@ -2975,6 +3176,12 @@ _xfs_log_force_lsn( | |||
2975 | 3176 | ||
2976 | XFS_STATS_INC(xs_log_force); | 3177 | XFS_STATS_INC(xs_log_force); |
2977 | 3178 | ||
3179 | if (log->l_cilp) { | ||
3180 | lsn = xlog_cil_push_lsn(log, lsn); | ||
3181 | if (lsn == NULLCOMMITLSN) | ||
3182 | return 0; | ||
3183 | } | ||
3184 | |||
2978 | try_again: | 3185 | try_again: |
2979 | spin_lock(&log->l_icloglock); | 3186 | spin_lock(&log->l_icloglock); |
2980 | iclog = log->l_iclog; | 3187 | iclog = log->l_iclog; |
@@ -3139,20 +3346,30 @@ xfs_log_ticket_get( | |||
3139 | return ticket; | 3346 | return ticket; |
3140 | } | 3347 | } |
3141 | 3348 | ||
3349 | xlog_tid_t | ||
3350 | xfs_log_get_trans_ident( | ||
3351 | struct xfs_trans *tp) | ||
3352 | { | ||
3353 | return tp->t_ticket->t_tid; | ||
3354 | } | ||
3355 | |||
3142 | /* | 3356 | /* |
3143 | * Allocate and initialise a new log ticket. | 3357 | * Allocate and initialise a new log ticket. |
3144 | */ | 3358 | */ |
3145 | STATIC xlog_ticket_t * | 3359 | xlog_ticket_t * |
3146 | xlog_ticket_alloc(xlog_t *log, | 3360 | xlog_ticket_alloc( |
3147 | int unit_bytes, | 3361 | struct log *log, |
3148 | int cnt, | 3362 | int unit_bytes, |
3149 | char client, | 3363 | int cnt, |
3150 | uint xflags) | 3364 | char client, |
3365 | uint xflags, | ||
3366 | int alloc_flags) | ||
3151 | { | 3367 | { |
3152 | xlog_ticket_t *tic; | 3368 | struct xlog_ticket *tic; |
3153 | uint num_headers; | 3369 | uint num_headers; |
3370 | int iclog_space; | ||
3154 | 3371 | ||
3155 | tic = kmem_zone_zalloc(xfs_log_ticket_zone, KM_SLEEP|KM_MAYFAIL); | 3372 | tic = kmem_zone_zalloc(xfs_log_ticket_zone, alloc_flags); |
3156 | if (!tic) | 3373 | if (!tic) |
3157 | return NULL; | 3374 | return NULL; |
3158 | 3375 | ||
@@ -3194,16 +3411,40 @@ xlog_ticket_alloc(xlog_t *log, | |||
3194 | /* for start-rec */ | 3411 | /* for start-rec */ |
3195 | unit_bytes += sizeof(xlog_op_header_t); | 3412 | unit_bytes += sizeof(xlog_op_header_t); |
3196 | 3413 | ||
3197 | /* for LR headers */ | 3414 | /* |
3198 | num_headers = ((unit_bytes + log->l_iclog_size-1) >> log->l_iclog_size_log); | 3415 | * for LR headers - the space for data in an iclog is the size minus |
3416 | * the space used for the headers. If we use the iclog size, then we | ||
3417 | * undercalculate the number of headers required. | ||
3418 | * | ||
3419 | * Furthermore - the addition of op headers for split-recs might | ||
3420 | * increase the space required enough to require more log and op | ||
3421 | * headers, so take that into account too. | ||
3422 | * | ||
3423 | * IMPORTANT: This reservation makes the assumption that if this | ||
3424 | * transaction is the first in an iclog and hence has the LR headers | ||
3425 | * accounted to it, then the remaining space in the iclog is | ||
3426 | * exclusively for this transaction. i.e. if the transaction is larger | ||
3427 | * than the iclog, it will be the only thing in that iclog. | ||
3428 | * Fundamentally, this means we must pass the entire log vector to | ||
3429 | * xlog_write to guarantee this. | ||
3430 | */ | ||
3431 | iclog_space = log->l_iclog_size - log->l_iclog_hsize; | ||
3432 | num_headers = howmany(unit_bytes, iclog_space); | ||
3433 | |||
3434 | /* for split-recs - ophdrs added when data split over LRs */ | ||
3435 | unit_bytes += sizeof(xlog_op_header_t) * num_headers; | ||
3436 | |||
3437 | /* add extra header reservations if we overrun */ | ||
3438 | while (!num_headers || | ||
3439 | howmany(unit_bytes, iclog_space) > num_headers) { | ||
3440 | unit_bytes += sizeof(xlog_op_header_t); | ||
3441 | num_headers++; | ||
3442 | } | ||
3199 | unit_bytes += log->l_iclog_hsize * num_headers; | 3443 | unit_bytes += log->l_iclog_hsize * num_headers; |
3200 | 3444 | ||
3201 | /* for commit-rec LR header - note: padding will subsume the ophdr */ | 3445 | /* for commit-rec LR header - note: padding will subsume the ophdr */ |
3202 | unit_bytes += log->l_iclog_hsize; | 3446 | unit_bytes += log->l_iclog_hsize; |
3203 | 3447 | ||
3204 | /* for split-recs - ophdrs added when data split over LRs */ | ||
3205 | unit_bytes += sizeof(xlog_op_header_t) * num_headers; | ||
3206 | |||
3207 | /* for roundoff padding for transaction data and one for commit record */ | 3448 | /* for roundoff padding for transaction data and one for commit record */ |
3208 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb) && | 3449 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb) && |
3209 | log->l_mp->m_sb.sb_logsunit > 1) { | 3450 | log->l_mp->m_sb.sb_logsunit > 1) { |
@@ -3219,13 +3460,13 @@ xlog_ticket_alloc(xlog_t *log, | |||
3219 | tic->t_curr_res = unit_bytes; | 3460 | tic->t_curr_res = unit_bytes; |
3220 | tic->t_cnt = cnt; | 3461 | tic->t_cnt = cnt; |
3221 | tic->t_ocnt = cnt; | 3462 | tic->t_ocnt = cnt; |
3222 | tic->t_tid = (xlog_tid_t)((__psint_t)tic & 0xffffffff); | 3463 | tic->t_tid = random32(); |
3223 | tic->t_clientid = client; | 3464 | tic->t_clientid = client; |
3224 | tic->t_flags = XLOG_TIC_INITED; | 3465 | tic->t_flags = XLOG_TIC_INITED; |
3225 | tic->t_trans_type = 0; | 3466 | tic->t_trans_type = 0; |
3226 | if (xflags & XFS_LOG_PERM_RESERV) | 3467 | if (xflags & XFS_LOG_PERM_RESERV) |
3227 | tic->t_flags |= XLOG_TIC_PERM_RESERV; | 3468 | tic->t_flags |= XLOG_TIC_PERM_RESERV; |
3228 | sv_init(&(tic->t_wait), SV_DEFAULT, "logtick"); | 3469 | sv_init(&tic->t_wait, SV_DEFAULT, "logtick"); |
3229 | 3470 | ||
3230 | xlog_tic_reset_res(tic); | 3471 | xlog_tic_reset_res(tic); |
3231 | 3472 | ||
@@ -3246,20 +3487,22 @@ xlog_ticket_alloc(xlog_t *log, | |||
3246 | * part of the log in case we trash the log structure. | 3487 | * part of the log in case we trash the log structure. |
3247 | */ | 3488 | */ |
3248 | void | 3489 | void |
3249 | xlog_verify_dest_ptr(xlog_t *log, | 3490 | xlog_verify_dest_ptr( |
3250 | __psint_t ptr) | 3491 | struct log *log, |
3492 | char *ptr) | ||
3251 | { | 3493 | { |
3252 | int i; | 3494 | int i; |
3253 | int good_ptr = 0; | 3495 | int good_ptr = 0; |
3254 | 3496 | ||
3255 | for (i=0; i < log->l_iclog_bufs; i++) { | 3497 | for (i = 0; i < log->l_iclog_bufs; i++) { |
3256 | if (ptr >= (__psint_t)log->l_iclog_bak[i] && | 3498 | if (ptr >= log->l_iclog_bak[i] && |
3257 | ptr <= (__psint_t)log->l_iclog_bak[i]+log->l_iclog_size) | 3499 | ptr <= log->l_iclog_bak[i] + log->l_iclog_size) |
3258 | good_ptr++; | 3500 | good_ptr++; |
3259 | } | 3501 | } |
3260 | if (! good_ptr) | 3502 | |
3503 | if (!good_ptr) | ||
3261 | xlog_panic("xlog_verify_dest_ptr: invalid ptr"); | 3504 | xlog_panic("xlog_verify_dest_ptr: invalid ptr"); |
3262 | } /* xlog_verify_dest_ptr */ | 3505 | } |
3263 | 3506 | ||
3264 | STATIC void | 3507 | STATIC void |
3265 | xlog_verify_grant_head(xlog_t *log, int equals) | 3508 | xlog_verify_grant_head(xlog_t *log, int equals) |
@@ -3445,6 +3688,11 @@ xlog_state_ioerror( | |||
3445 | * c. nothing new gets queued up after (a) and (b) are done. | 3688 | * c. nothing new gets queued up after (a) and (b) are done. |
3446 | * d. if !logerror, flush the iclogs to disk, then seal them off | 3689 | * d. if !logerror, flush the iclogs to disk, then seal them off |
3447 | * for business. | 3690 | * for business. |
3691 | * | ||
3692 | * Note: for delayed logging the !logerror case needs to flush the regions | ||
3693 | * held in memory out to the iclogs before flushing them to disk. This needs | ||
3694 | * to be done before the log is marked as shutdown, otherwise the flush to the | ||
3695 | * iclogs will fail. | ||
3448 | */ | 3696 | */ |
3449 | int | 3697 | int |
3450 | xfs_log_force_umount( | 3698 | xfs_log_force_umount( |
@@ -3478,6 +3726,16 @@ xfs_log_force_umount( | |||
3478 | return 1; | 3726 | return 1; |
3479 | } | 3727 | } |
3480 | retval = 0; | 3728 | retval = 0; |
3729 | |||
3730 | /* | ||
3731 | * Flush the in memory commit item list before marking the log as | ||
3732 | * being shut down. We need to do it in this order to ensure all the | ||
3733 | * completed transactions are flushed to disk with the xfs_log_force() | ||
3734 | * call below. | ||
3735 | */ | ||
3736 | if (!logerror && (mp->m_flags & XFS_MOUNT_DELAYLOG)) | ||
3737 | xlog_cil_push(log, 1); | ||
3738 | |||
3481 | /* | 3739 | /* |
3482 | * We must hold both the GRANT lock and the LOG lock, | 3740 | * We must hold both the GRANT lock and the LOG lock, |
3483 | * before we mark the filesystem SHUTDOWN and wake | 3741 | * before we mark the filesystem SHUTDOWN and wake |