diff options
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r-- | fs/xfs/xfs_log.c | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index f76c6d7cea21..3750f04ede0b 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -562,9 +562,8 @@ xfs_log_mount( | |||
562 | } | 562 | } |
563 | 563 | ||
564 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); | 564 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); |
565 | if (!mp->m_log) { | 565 | if (IS_ERR(mp->m_log)) { |
566 | cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!"); | 566 | error = -PTR_ERR(mp->m_log); |
567 | error = ENOMEM; | ||
568 | goto out; | 567 | goto out; |
569 | } | 568 | } |
570 | 569 | ||
@@ -1180,10 +1179,13 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1180 | xfs_buf_t *bp; | 1179 | xfs_buf_t *bp; |
1181 | int i; | 1180 | int i; |
1182 | int iclogsize; | 1181 | int iclogsize; |
1182 | int error = ENOMEM; | ||
1183 | 1183 | ||
1184 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); | 1184 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); |
1185 | if (!log) | 1185 | if (!log) { |
1186 | return NULL; | 1186 | xlog_warn("XFS: Log allocation failed: No memory!"); |
1187 | goto out; | ||
1188 | } | ||
1187 | 1189 | ||
1188 | log->l_mp = mp; | 1190 | log->l_mp = mp; |
1189 | log->l_targ = log_target; | 1191 | log->l_targ = log_target; |
@@ -1201,19 +1203,35 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1201 | log->l_grant_reserve_cycle = 1; | 1203 | log->l_grant_reserve_cycle = 1; |
1202 | log->l_grant_write_cycle = 1; | 1204 | log->l_grant_write_cycle = 1; |
1203 | 1205 | ||
1206 | error = EFSCORRUPTED; | ||
1204 | if (xfs_sb_version_hassector(&mp->m_sb)) { | 1207 | if (xfs_sb_version_hassector(&mp->m_sb)) { |
1205 | log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; | 1208 | log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; |
1206 | ASSERT(log->l_sectbb_log <= mp->m_sectbb_log); | 1209 | if (log->l_sectbb_log < 0 || |
1210 | log->l_sectbb_log > mp->m_sectbb_log) { | ||
1211 | xlog_warn("XFS: Log sector size (0x%x) out of range.", | ||
1212 | log->l_sectbb_log); | ||
1213 | goto out_free_log; | ||
1214 | } | ||
1215 | |||
1207 | /* for larger sector sizes, must have v2 or external log */ | 1216 | /* for larger sector sizes, must have v2 or external log */ |
1208 | ASSERT(log->l_sectbb_log == 0 || | 1217 | if (log->l_sectbb_log != 0 && |
1209 | log->l_logBBstart == 0 || | 1218 | (log->l_logBBstart != 0 && |
1210 | xfs_sb_version_haslogv2(&mp->m_sb)); | 1219 | !xfs_sb_version_haslogv2(&mp->m_sb))) { |
1211 | ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT); | 1220 | xlog_warn("XFS: log sector size (0x%x) invalid " |
1221 | "for configuration.", log->l_sectbb_log); | ||
1222 | goto out_free_log; | ||
1223 | } | ||
1224 | if (mp->m_sb.sb_logsectlog < BBSHIFT) { | ||
1225 | xlog_warn("XFS: Log sector log (0x%x) too small.", | ||
1226 | mp->m_sb.sb_logsectlog); | ||
1227 | goto out_free_log; | ||
1228 | } | ||
1212 | } | 1229 | } |
1213 | log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; | 1230 | log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; |
1214 | 1231 | ||
1215 | xlog_get_iclog_buffer_size(mp, log); | 1232 | xlog_get_iclog_buffer_size(mp, log); |
1216 | 1233 | ||
1234 | error = ENOMEM; | ||
1217 | bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); | 1235 | bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); |
1218 | if (!bp) | 1236 | if (!bp) |
1219 | goto out_free_log; | 1237 | goto out_free_log; |
@@ -1313,7 +1331,8 @@ out_free_iclog: | |||
1313 | xfs_buf_free(log->l_xbuf); | 1331 | xfs_buf_free(log->l_xbuf); |
1314 | out_free_log: | 1332 | out_free_log: |
1315 | kmem_free(log); | 1333 | kmem_free(log); |
1316 | return NULL; | 1334 | out: |
1335 | return ERR_PTR(-error); | ||
1317 | } /* xlog_alloc_log */ | 1336 | } /* xlog_alloc_log */ |
1318 | 1337 | ||
1319 | 1338 | ||
@@ -2541,18 +2560,19 @@ redo: | |||
2541 | xlog_ins_ticketq(&log->l_reserve_headq, tic); | 2560 | xlog_ins_ticketq(&log->l_reserve_headq, tic); |
2542 | xlog_trace_loggrant(log, tic, | 2561 | xlog_trace_loggrant(log, tic, |
2543 | "xlog_grant_log_space: sleep 2"); | 2562 | "xlog_grant_log_space: sleep 2"); |
2563 | spin_unlock(&log->l_grant_lock); | ||
2564 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2565 | spin_lock(&log->l_grant_lock); | ||
2566 | |||
2544 | XFS_STATS_INC(xs_sleep_logspace); | 2567 | XFS_STATS_INC(xs_sleep_logspace); |
2545 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); | 2568 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); |
2546 | 2569 | ||
2547 | if (XLOG_FORCED_SHUTDOWN(log)) { | 2570 | spin_lock(&log->l_grant_lock); |
2548 | spin_lock(&log->l_grant_lock); | 2571 | if (XLOG_FORCED_SHUTDOWN(log)) |
2549 | goto error_return; | 2572 | goto error_return; |
2550 | } | ||
2551 | 2573 | ||
2552 | xlog_trace_loggrant(log, tic, | 2574 | xlog_trace_loggrant(log, tic, |
2553 | "xlog_grant_log_space: wake 2"); | 2575 | "xlog_grant_log_space: wake 2"); |
2554 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2555 | spin_lock(&log->l_grant_lock); | ||
2556 | goto redo; | 2576 | goto redo; |
2557 | } else if (tic->t_flags & XLOG_TIC_IN_Q) | 2577 | } else if (tic->t_flags & XLOG_TIC_IN_Q) |
2558 | xlog_del_ticketq(&log->l_reserve_headq, tic); | 2578 | xlog_del_ticketq(&log->l_reserve_headq, tic); |
@@ -2631,7 +2651,7 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
2631 | * for more free space, otherwise try to get some space for | 2651 | * for more free space, otherwise try to get some space for |
2632 | * this transaction. | 2652 | * this transaction. |
2633 | */ | 2653 | */ |
2634 | 2654 | need_bytes = tic->t_unit_res; | |
2635 | if ((ntic = log->l_write_headq)) { | 2655 | if ((ntic = log->l_write_headq)) { |
2636 | free_bytes = xlog_space_left(log, log->l_grant_write_cycle, | 2656 | free_bytes = xlog_space_left(log, log->l_grant_write_cycle, |
2637 | log->l_grant_write_bytes); | 2657 | log->l_grant_write_bytes); |
@@ -2651,26 +2671,25 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
2651 | 2671 | ||
2652 | xlog_trace_loggrant(log, tic, | 2672 | xlog_trace_loggrant(log, tic, |
2653 | "xlog_regrant_write_log_space: sleep 1"); | 2673 | "xlog_regrant_write_log_space: sleep 1"); |
2674 | spin_unlock(&log->l_grant_lock); | ||
2675 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2676 | spin_lock(&log->l_grant_lock); | ||
2677 | |||
2654 | XFS_STATS_INC(xs_sleep_logspace); | 2678 | XFS_STATS_INC(xs_sleep_logspace); |
2655 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, | 2679 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, |
2656 | &log->l_grant_lock, s); | 2680 | &log->l_grant_lock, s); |
2657 | 2681 | ||
2658 | /* If we're shutting down, this tic is already | 2682 | /* If we're shutting down, this tic is already |
2659 | * off the queue */ | 2683 | * off the queue */ |
2660 | if (XLOG_FORCED_SHUTDOWN(log)) { | 2684 | spin_lock(&log->l_grant_lock); |
2661 | spin_lock(&log->l_grant_lock); | 2685 | if (XLOG_FORCED_SHUTDOWN(log)) |
2662 | goto error_return; | 2686 | goto error_return; |
2663 | } | ||
2664 | 2687 | ||
2665 | xlog_trace_loggrant(log, tic, | 2688 | xlog_trace_loggrant(log, tic, |
2666 | "xlog_regrant_write_log_space: wake 1"); | 2689 | "xlog_regrant_write_log_space: wake 1"); |
2667 | xlog_grant_push_ail(log->l_mp, tic->t_unit_res); | ||
2668 | spin_lock(&log->l_grant_lock); | ||
2669 | } | 2690 | } |
2670 | } | 2691 | } |
2671 | 2692 | ||
2672 | need_bytes = tic->t_unit_res; | ||
2673 | |||
2674 | redo: | 2693 | redo: |
2675 | if (XLOG_FORCED_SHUTDOWN(log)) | 2694 | if (XLOG_FORCED_SHUTDOWN(log)) |
2676 | goto error_return; | 2695 | goto error_return; |
@@ -2680,19 +2699,20 @@ redo: | |||
2680 | if (free_bytes < need_bytes) { | 2699 | if (free_bytes < need_bytes) { |
2681 | if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) | 2700 | if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) |
2682 | xlog_ins_ticketq(&log->l_write_headq, tic); | 2701 | xlog_ins_ticketq(&log->l_write_headq, tic); |
2702 | spin_unlock(&log->l_grant_lock); | ||
2703 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2704 | spin_lock(&log->l_grant_lock); | ||
2705 | |||
2683 | XFS_STATS_INC(xs_sleep_logspace); | 2706 | XFS_STATS_INC(xs_sleep_logspace); |
2684 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); | 2707 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); |
2685 | 2708 | ||
2686 | /* If we're shutting down, this tic is already off the queue */ | 2709 | /* If we're shutting down, this tic is already off the queue */ |
2687 | if (XLOG_FORCED_SHUTDOWN(log)) { | 2710 | spin_lock(&log->l_grant_lock); |
2688 | spin_lock(&log->l_grant_lock); | 2711 | if (XLOG_FORCED_SHUTDOWN(log)) |
2689 | goto error_return; | 2712 | goto error_return; |
2690 | } | ||
2691 | 2713 | ||
2692 | xlog_trace_loggrant(log, tic, | 2714 | xlog_trace_loggrant(log, tic, |
2693 | "xlog_regrant_write_log_space: wake 2"); | 2715 | "xlog_regrant_write_log_space: wake 2"); |
2694 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2695 | spin_lock(&log->l_grant_lock); | ||
2696 | goto redo; | 2716 | goto redo; |
2697 | } else if (tic->t_flags & XLOG_TIC_IN_Q) | 2717 | } else if (tic->t_flags & XLOG_TIC_IN_Q) |
2698 | xlog_del_ticketq(&log->l_write_headq, tic); | 2718 | xlog_del_ticketq(&log->l_write_headq, tic); |