diff options
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r-- | fs/xfs/xfs_log.c | 81 |
1 files changed, 44 insertions, 37 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 3608a0f0a5f6..f4726f702a9e 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -100,12 +100,11 @@ STATIC void xlog_ungrant_log_space(xlog_t *log, | |||
100 | 100 | ||
101 | 101 | ||
102 | /* local ticket functions */ | 102 | /* local ticket functions */ |
103 | STATIC xlog_ticket_t *xlog_ticket_get(xlog_t *log, | 103 | STATIC xlog_ticket_t *xlog_ticket_alloc(xlog_t *log, |
104 | int unit_bytes, | 104 | int unit_bytes, |
105 | int count, | 105 | int count, |
106 | char clientid, | 106 | char clientid, |
107 | uint flags); | 107 | uint flags); |
108 | STATIC void xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket); | ||
109 | 108 | ||
110 | #if defined(DEBUG) | 109 | #if defined(DEBUG) |
111 | STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr); | 110 | STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr); |
@@ -360,7 +359,7 @@ xfs_log_done(xfs_mount_t *mp, | |||
360 | */ | 359 | */ |
361 | xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)"); | 360 | xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)"); |
362 | xlog_ungrant_log_space(log, ticket); | 361 | xlog_ungrant_log_space(log, ticket); |
363 | xlog_ticket_put(log, ticket); | 362 | xfs_log_ticket_put(ticket); |
364 | } else { | 363 | } else { |
365 | xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)"); | 364 | xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)"); |
366 | xlog_regrant_reserve_log_space(log, ticket); | 365 | xlog_regrant_reserve_log_space(log, ticket); |
@@ -514,7 +513,7 @@ xfs_log_reserve(xfs_mount_t *mp, | |||
514 | retval = xlog_regrant_write_log_space(log, internal_ticket); | 513 | retval = xlog_regrant_write_log_space(log, internal_ticket); |
515 | } else { | 514 | } else { |
516 | /* may sleep if need to allocate more tickets */ | 515 | /* may sleep if need to allocate more tickets */ |
517 | internal_ticket = xlog_ticket_get(log, unit_bytes, cnt, | 516 | internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt, |
518 | client, flags); | 517 | client, flags); |
519 | if (!internal_ticket) | 518 | if (!internal_ticket) |
520 | return XFS_ERROR(ENOMEM); | 519 | return XFS_ERROR(ENOMEM); |
@@ -572,12 +571,12 @@ xfs_log_mount( | |||
572 | /* | 571 | /* |
573 | * Initialize the AIL now we have a log. | 572 | * Initialize the AIL now we have a log. |
574 | */ | 573 | */ |
575 | spin_lock_init(&mp->m_ail_lock); | ||
576 | error = xfs_trans_ail_init(mp); | 574 | error = xfs_trans_ail_init(mp); |
577 | if (error) { | 575 | if (error) { |
578 | cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); | 576 | cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); |
579 | goto error; | 577 | goto error; |
580 | } | 578 | } |
579 | mp->m_log->l_ailp = mp->m_ail; | ||
581 | 580 | ||
582 | /* | 581 | /* |
583 | * skip log recovery on a norecovery mount. pretend it all | 582 | * skip log recovery on a norecovery mount. pretend it all |
@@ -730,8 +729,8 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
730 | spin_lock(&log->l_icloglock); | 729 | spin_lock(&log->l_icloglock); |
731 | iclog = log->l_iclog; | 730 | iclog = log->l_iclog; |
732 | atomic_inc(&iclog->ic_refcnt); | 731 | atomic_inc(&iclog->ic_refcnt); |
733 | spin_unlock(&log->l_icloglock); | ||
734 | xlog_state_want_sync(log, iclog); | 732 | xlog_state_want_sync(log, iclog); |
733 | spin_unlock(&log->l_icloglock); | ||
735 | error = xlog_state_release_iclog(log, iclog); | 734 | error = xlog_state_release_iclog(log, iclog); |
736 | 735 | ||
737 | spin_lock(&log->l_icloglock); | 736 | spin_lock(&log->l_icloglock); |
@@ -749,7 +748,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
749 | if (tic) { | 748 | if (tic) { |
750 | xlog_trace_loggrant(log, tic, "unmount rec"); | 749 | xlog_trace_loggrant(log, tic, "unmount rec"); |
751 | xlog_ungrant_log_space(log, tic); | 750 | xlog_ungrant_log_space(log, tic); |
752 | xlog_ticket_put(log, tic); | 751 | xfs_log_ticket_put(tic); |
753 | } | 752 | } |
754 | } else { | 753 | } else { |
755 | /* | 754 | /* |
@@ -768,9 +767,9 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
768 | spin_lock(&log->l_icloglock); | 767 | spin_lock(&log->l_icloglock); |
769 | iclog = log->l_iclog; | 768 | iclog = log->l_iclog; |
770 | atomic_inc(&iclog->ic_refcnt); | 769 | atomic_inc(&iclog->ic_refcnt); |
771 | spin_unlock(&log->l_icloglock); | ||
772 | 770 | ||
773 | xlog_state_want_sync(log, iclog); | 771 | xlog_state_want_sync(log, iclog); |
772 | spin_unlock(&log->l_icloglock); | ||
774 | error = xlog_state_release_iclog(log, iclog); | 773 | error = xlog_state_release_iclog(log, iclog); |
775 | 774 | ||
776 | spin_lock(&log->l_icloglock); | 775 | spin_lock(&log->l_icloglock); |
@@ -906,7 +905,7 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
906 | int | 905 | int |
907 | xfs_log_need_covered(xfs_mount_t *mp) | 906 | xfs_log_need_covered(xfs_mount_t *mp) |
908 | { | 907 | { |
909 | int needed = 0, gen; | 908 | int needed = 0; |
910 | xlog_t *log = mp->m_log; | 909 | xlog_t *log = mp->m_log; |
911 | 910 | ||
912 | if (!xfs_fs_writable(mp)) | 911 | if (!xfs_fs_writable(mp)) |
@@ -915,7 +914,7 @@ xfs_log_need_covered(xfs_mount_t *mp) | |||
915 | spin_lock(&log->l_icloglock); | 914 | spin_lock(&log->l_icloglock); |
916 | if (((log->l_covered_state == XLOG_STATE_COVER_NEED) || | 915 | if (((log->l_covered_state == XLOG_STATE_COVER_NEED) || |
917 | (log->l_covered_state == XLOG_STATE_COVER_NEED2)) | 916 | (log->l_covered_state == XLOG_STATE_COVER_NEED2)) |
918 | && !xfs_trans_first_ail(mp, &gen) | 917 | && !xfs_trans_ail_tail(log->l_ailp) |
919 | && xlog_iclogs_empty(log)) { | 918 | && xlog_iclogs_empty(log)) { |
920 | if (log->l_covered_state == XLOG_STATE_COVER_NEED) | 919 | if (log->l_covered_state == XLOG_STATE_COVER_NEED) |
921 | log->l_covered_state = XLOG_STATE_COVER_DONE; | 920 | log->l_covered_state = XLOG_STATE_COVER_DONE; |
@@ -952,7 +951,7 @@ xlog_assign_tail_lsn(xfs_mount_t *mp) | |||
952 | xfs_lsn_t tail_lsn; | 951 | xfs_lsn_t tail_lsn; |
953 | xlog_t *log = mp->m_log; | 952 | xlog_t *log = mp->m_log; |
954 | 953 | ||
955 | tail_lsn = xfs_trans_tail_ail(mp); | 954 | tail_lsn = xfs_trans_ail_tail(mp->m_ail); |
956 | spin_lock(&log->l_grant_lock); | 955 | spin_lock(&log->l_grant_lock); |
957 | if (tail_lsn != 0) { | 956 | if (tail_lsn != 0) { |
958 | log->l_tail_lsn = tail_lsn; | 957 | log->l_tail_lsn = tail_lsn; |
@@ -1030,12 +1029,6 @@ xlog_iodone(xfs_buf_t *bp) | |||
1030 | ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long) 2); | 1029 | ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long) 2); |
1031 | XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); | 1030 | XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); |
1032 | aborted = 0; | 1031 | aborted = 0; |
1033 | |||
1034 | /* | ||
1035 | * Some versions of cpp barf on the recursive definition of | ||
1036 | * ic_log -> hic_fields.ic_log and expand ic_log twice when | ||
1037 | * it is passed through two macros. Workaround broken cpp. | ||
1038 | */ | ||
1039 | l = iclog->ic_log; | 1032 | l = iclog->ic_log; |
1040 | 1033 | ||
1041 | /* | 1034 | /* |
@@ -1302,7 +1295,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1302 | XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb); | 1295 | XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb); |
1303 | XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); | 1296 | XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); |
1304 | iclog->ic_bp = bp; | 1297 | iclog->ic_bp = bp; |
1305 | iclog->hic_data = bp->b_addr; | 1298 | iclog->ic_data = bp->b_addr; |
1306 | #ifdef DEBUG | 1299 | #ifdef DEBUG |
1307 | log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header); | 1300 | log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header); |
1308 | #endif | 1301 | #endif |
@@ -1322,7 +1315,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1322 | atomic_set(&iclog->ic_refcnt, 0); | 1315 | atomic_set(&iclog->ic_refcnt, 0); |
1323 | spin_lock_init(&iclog->ic_callback_lock); | 1316 | spin_lock_init(&iclog->ic_callback_lock); |
1324 | iclog->ic_callback_tail = &(iclog->ic_callback); | 1317 | iclog->ic_callback_tail = &(iclog->ic_callback); |
1325 | iclog->ic_datap = (char *)iclog->hic_data + log->l_iclog_hsize; | 1318 | iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize; |
1326 | 1319 | ||
1327 | ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp)); | 1320 | ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp)); |
1328 | ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0); | 1321 | ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0); |
@@ -1446,7 +1439,7 @@ xlog_grant_push_ail(xfs_mount_t *mp, | |||
1446 | */ | 1439 | */ |
1447 | if (threshold_lsn && | 1440 | if (threshold_lsn && |
1448 | !XLOG_FORCED_SHUTDOWN(log)) | 1441 | !XLOG_FORCED_SHUTDOWN(log)) |
1449 | xfs_trans_push_ail(mp, threshold_lsn); | 1442 | xfs_trans_ail_push(log->l_ailp, threshold_lsn); |
1450 | } /* xlog_grant_push_ail */ | 1443 | } /* xlog_grant_push_ail */ |
1451 | 1444 | ||
1452 | 1445 | ||
@@ -1991,7 +1984,9 @@ xlog_write(xfs_mount_t * mp, | |||
1991 | if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) { | 1984 | if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) { |
1992 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | 1985 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); |
1993 | record_cnt = data_cnt = 0; | 1986 | record_cnt = data_cnt = 0; |
1987 | spin_lock(&log->l_icloglock); | ||
1994 | xlog_state_want_sync(log, iclog); | 1988 | xlog_state_want_sync(log, iclog); |
1989 | spin_unlock(&log->l_icloglock); | ||
1995 | if (commit_iclog) { | 1990 | if (commit_iclog) { |
1996 | ASSERT(flags & XLOG_COMMIT_TRANS); | 1991 | ASSERT(flags & XLOG_COMMIT_TRANS); |
1997 | *commit_iclog = iclog; | 1992 | *commit_iclog = iclog; |
@@ -3200,7 +3195,7 @@ try_again: | |||
3200 | STATIC void | 3195 | STATIC void |
3201 | xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) | 3196 | xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) |
3202 | { | 3197 | { |
3203 | spin_lock(&log->l_icloglock); | 3198 | ASSERT(spin_is_locked(&log->l_icloglock)); |
3204 | 3199 | ||
3205 | if (iclog->ic_state == XLOG_STATE_ACTIVE) { | 3200 | if (iclog->ic_state == XLOG_STATE_ACTIVE) { |
3206 | xlog_state_switch_iclogs(log, iclog, 0); | 3201 | xlog_state_switch_iclogs(log, iclog, 0); |
@@ -3208,10 +3203,7 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) | |||
3208 | ASSERT(iclog->ic_state & | 3203 | ASSERT(iclog->ic_state & |
3209 | (XLOG_STATE_WANT_SYNC|XLOG_STATE_IOERROR)); | 3204 | (XLOG_STATE_WANT_SYNC|XLOG_STATE_IOERROR)); |
3210 | } | 3205 | } |
3211 | 3206 | } | |
3212 | spin_unlock(&log->l_icloglock); | ||
3213 | } /* xlog_state_want_sync */ | ||
3214 | |||
3215 | 3207 | ||
3216 | 3208 | ||
3217 | /***************************************************************************** | 3209 | /***************************************************************************** |
@@ -3222,22 +3214,33 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) | |||
3222 | */ | 3214 | */ |
3223 | 3215 | ||
3224 | /* | 3216 | /* |
3225 | * Free a used ticket. | 3217 | * Free a used ticket when it's refcount falls to zero. |
3226 | */ | 3218 | */ |
3227 | STATIC void | 3219 | void |
3228 | xlog_ticket_put(xlog_t *log, | 3220 | xfs_log_ticket_put( |
3229 | xlog_ticket_t *ticket) | 3221 | xlog_ticket_t *ticket) |
3230 | { | 3222 | { |
3231 | sv_destroy(&ticket->t_wait); | 3223 | ASSERT(atomic_read(&ticket->t_ref) > 0); |
3232 | kmem_zone_free(xfs_log_ticket_zone, ticket); | 3224 | if (atomic_dec_and_test(&ticket->t_ref)) { |
3233 | } /* xlog_ticket_put */ | 3225 | sv_destroy(&ticket->t_wait); |
3226 | kmem_zone_free(xfs_log_ticket_zone, ticket); | ||
3227 | } | ||
3228 | } | ||
3234 | 3229 | ||
3230 | xlog_ticket_t * | ||
3231 | xfs_log_ticket_get( | ||
3232 | xlog_ticket_t *ticket) | ||
3233 | { | ||
3234 | ASSERT(atomic_read(&ticket->t_ref) > 0); | ||
3235 | atomic_inc(&ticket->t_ref); | ||
3236 | return ticket; | ||
3237 | } | ||
3235 | 3238 | ||
3236 | /* | 3239 | /* |
3237 | * Allocate and initialise a new log ticket. | 3240 | * Allocate and initialise a new log ticket. |
3238 | */ | 3241 | */ |
3239 | STATIC xlog_ticket_t * | 3242 | STATIC xlog_ticket_t * |
3240 | xlog_ticket_get(xlog_t *log, | 3243 | xlog_ticket_alloc(xlog_t *log, |
3241 | int unit_bytes, | 3244 | int unit_bytes, |
3242 | int cnt, | 3245 | int cnt, |
3243 | char client, | 3246 | char client, |
@@ -3308,6 +3311,7 @@ xlog_ticket_get(xlog_t *log, | |||
3308 | unit_bytes += 2*BBSIZE; | 3311 | unit_bytes += 2*BBSIZE; |
3309 | } | 3312 | } |
3310 | 3313 | ||
3314 | atomic_set(&tic->t_ref, 1); | ||
3311 | tic->t_unit_res = unit_bytes; | 3315 | tic->t_unit_res = unit_bytes; |
3312 | tic->t_curr_res = unit_bytes; | 3316 | tic->t_curr_res = unit_bytes; |
3313 | tic->t_cnt = cnt; | 3317 | tic->t_cnt = cnt; |
@@ -3323,7 +3327,7 @@ xlog_ticket_get(xlog_t *log, | |||
3323 | xlog_tic_reset_res(tic); | 3327 | xlog_tic_reset_res(tic); |
3324 | 3328 | ||
3325 | return tic; | 3329 | return tic; |
3326 | } /* xlog_ticket_get */ | 3330 | } |
3327 | 3331 | ||
3328 | 3332 | ||
3329 | /****************************************************************************** | 3333 | /****************************************************************************** |
@@ -3452,7 +3456,7 @@ xlog_verify_iclog(xlog_t *log, | |||
3452 | ptr = iclog->ic_datap; | 3456 | ptr = iclog->ic_datap; |
3453 | base_ptr = ptr; | 3457 | base_ptr = ptr; |
3454 | ophead = (xlog_op_header_t *)ptr; | 3458 | ophead = (xlog_op_header_t *)ptr; |
3455 | xhdr = (xlog_in_core_2_t *)&iclog->ic_header; | 3459 | xhdr = iclog->ic_data; |
3456 | for (i = 0; i < len; i++) { | 3460 | for (i = 0; i < len; i++) { |
3457 | ophead = (xlog_op_header_t *)ptr; | 3461 | ophead = (xlog_op_header_t *)ptr; |
3458 | 3462 | ||
@@ -3558,7 +3562,8 @@ xfs_log_force_umount( | |||
3558 | if (!log || | 3562 | if (!log || |
3559 | log->l_flags & XLOG_ACTIVE_RECOVERY) { | 3563 | log->l_flags & XLOG_ACTIVE_RECOVERY) { |
3560 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; | 3564 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; |
3561 | XFS_BUF_DONE(mp->m_sb_bp); | 3565 | if (mp->m_sb_bp) |
3566 | XFS_BUF_DONE(mp->m_sb_bp); | ||
3562 | return 0; | 3567 | return 0; |
3563 | } | 3568 | } |
3564 | 3569 | ||
@@ -3579,7 +3584,9 @@ xfs_log_force_umount( | |||
3579 | spin_lock(&log->l_icloglock); | 3584 | spin_lock(&log->l_icloglock); |
3580 | spin_lock(&log->l_grant_lock); | 3585 | spin_lock(&log->l_grant_lock); |
3581 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; | 3586 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; |
3582 | XFS_BUF_DONE(mp->m_sb_bp); | 3587 | if (mp->m_sb_bp) |
3588 | XFS_BUF_DONE(mp->m_sb_bp); | ||
3589 | |||
3583 | /* | 3590 | /* |
3584 | * This flag is sort of redundant because of the mount flag, but | 3591 | * This flag is sort of redundant because of the mount flag, but |
3585 | * it's good to maintain the separation between the log and the rest | 3592 | * it's good to maintain the separation between the log and the rest |