aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-02-19 21:31:31 -0500
committerBen Myers <bpm@sgi.com>2012-02-22 23:37:04 -0500
commit9006fb91cfdf22812923f0536c7531c429c1aeab (patch)
tree36b37fe3df405a57e8ede3d2a40ea6c307f40ae9 /fs/xfs/xfs_log.c
parent42ceedb3caffe67c4ec0dfbb78ce410832d429b9 (diff)
xfs: split and cleanup xfs_log_reserve
Split the log regrant case out of xfs_log_reserve into a separate function, and merge xlog_grant_log_space and xlog_regrant_write_log_space into their respective callers. Also replace the XFS_LOG_PERM_RESERV flag, which easily got misused before the previous cleanups with a simple boolean parameter. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r--fs/xfs/xfs_log.c265
1 files changed, 124 insertions, 141 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index c6a29a05c60a..98a9cb5ffd17 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -67,15 +67,10 @@ STATIC void xlog_state_switch_iclogs(xlog_t *log,
67 int eventual_size); 67 int eventual_size);
68STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog); 68STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog);
69 69
70/* local functions to manipulate grant head */
71STATIC int xlog_grant_log_space(xlog_t *log,
72 xlog_ticket_t *xtic);
73STATIC void xlog_grant_push_ail(struct log *log, 70STATIC void xlog_grant_push_ail(struct log *log,
74 int need_bytes); 71 int need_bytes);
75STATIC void xlog_regrant_reserve_log_space(xlog_t *log, 72STATIC void xlog_regrant_reserve_log_space(xlog_t *log,
76 xlog_ticket_t *ticket); 73 xlog_ticket_t *ticket);
77STATIC int xlog_regrant_write_log_space(xlog_t *log,
78 xlog_ticket_t *ticket);
79STATIC void xlog_ungrant_log_space(xlog_t *log, 74STATIC void xlog_ungrant_log_space(xlog_t *log,
80 xlog_ticket_t *ticket); 75 xlog_ticket_t *ticket);
81 76
@@ -324,6 +319,128 @@ xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type)
324} 319}
325 320
326/* 321/*
322 * Replenish the byte reservation required by moving the grant write head.
323 */
324int
325xfs_log_regrant(
326 struct xfs_mount *mp,
327 struct xlog_ticket *tic)
328{
329 struct log *log = mp->m_log;
330 int need_bytes;
331 int error = 0;
332
333 if (XLOG_FORCED_SHUTDOWN(log))
334 return XFS_ERROR(EIO);
335
336 XFS_STATS_INC(xs_try_logspace);
337
338 /*
339 * This is a new transaction on the ticket, so we need to change the
340 * transaction ID so that the next transaction has a different TID in
341 * the log. Just add one to the existing tid so that we can see chains
342 * of rolling transactions in the log easily.
343 */
344 tic->t_tid++;
345
346 xlog_grant_push_ail(log, tic->t_unit_res);
347
348 tic->t_curr_res = tic->t_unit_res;
349 xlog_tic_reset_res(tic);
350
351 if (tic->t_cnt > 0)
352 return 0;
353
354 trace_xfs_log_regrant(log, tic);
355
356 error = xlog_grant_head_check(log, &log->l_write_head, tic,
357 &need_bytes);
358 if (error)
359 goto out_error;
360
361 xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
362 trace_xfs_log_regrant_exit(log, tic);
363 xlog_verify_grant_tail(log);
364 return 0;
365
366out_error:
367 /*
368 * If we are failing, make sure the ticket doesn't have any current
369 * reservations. We don't want to add this back when the ticket/
370 * transaction gets cancelled.
371 */
372 tic->t_curr_res = 0;
373 tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
374 return error;
375}
376
377/*
378 * Reserve log space and return a ticket corresponding the reservation.
379 *
380 * Each reservation is going to reserve extra space for a log record header.
381 * When writes happen to the on-disk log, we don't subtract the length of the
382 * log record header from any reservation. By wasting space in each
383 * reservation, we prevent over allocation problems.
384 */
385int
386xfs_log_reserve(
387 struct xfs_mount *mp,
388 int unit_bytes,
389 int cnt,
390 struct xlog_ticket **ticp,
391 __uint8_t client,
392 bool permanent,
393 uint t_type)
394{
395 struct log *log = mp->m_log;
396 struct xlog_ticket *tic;
397 int need_bytes;
398 int error = 0;
399
400 ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
401
402 if (XLOG_FORCED_SHUTDOWN(log))
403 return XFS_ERROR(EIO);
404
405 XFS_STATS_INC(xs_try_logspace);
406
407 ASSERT(*ticp == NULL);
408 tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent,
409 KM_SLEEP | KM_MAYFAIL);
410 if (!tic)
411 return XFS_ERROR(ENOMEM);
412
413 tic->t_trans_type = t_type;
414 *ticp = tic;
415
416 xlog_grant_push_ail(log, tic->t_unit_res * tic->t_cnt);
417
418 trace_xfs_log_reserve(log, tic);
419
420 error = xlog_grant_head_check(log, &log->l_reserve_head, tic,
421 &need_bytes);
422 if (error)
423 goto out_error;
424
425 xlog_grant_add_space(log, &log->l_reserve_head.grant, need_bytes);
426 xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
427 trace_xfs_log_reserve_exit(log, tic);
428 xlog_verify_grant_tail(log);
429 return 0;
430
431out_error:
432 /*
433 * If we are failing, make sure the ticket doesn't have any current
434 * reservations. We don't want to add this back when the ticket/
435 * transaction gets cancelled.
436 */
437 tic->t_curr_res = 0;
438 tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
439 return error;
440}
441
442
443/*
327 * NOTES: 444 * NOTES:
328 * 445 *
329 * 1. currblock field gets updated at startup and after in-core logs 446 * 1. currblock field gets updated at startup and after in-core logs
@@ -433,88 +550,6 @@ xfs_log_release_iclog(
433} 550}
434 551
435/* 552/*
436 * 1. Reserve an amount of on-disk log space and return a ticket corresponding
437 * to the reservation.
438 * 2. Potentially, push buffers at tail of log to disk.
439 *
440 * Each reservation is going to reserve extra space for a log record header.
441 * When writes happen to the on-disk log, we don't subtract the length of the
442 * log record header from any reservation. By wasting space in each
443 * reservation, we prevent over allocation problems.
444 */
445int
446xfs_log_reserve(
447 struct xfs_mount *mp,
448 int unit_bytes,
449 int cnt,
450 struct xlog_ticket **ticket,
451 __uint8_t client,
452 uint flags,
453 uint t_type)
454{
455 struct log *log = mp->m_log;
456 struct xlog_ticket *internal_ticket;
457 int retval = 0;
458
459 ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
460
461 if (XLOG_FORCED_SHUTDOWN(log))
462 return XFS_ERROR(EIO);
463
464 XFS_STATS_INC(xs_try_logspace);
465
466
467 if (*ticket != NULL) {
468 ASSERT(flags & XFS_LOG_PERM_RESERV);
469 internal_ticket = *ticket;
470
471 /*
472 * this is a new transaction on the ticket, so we need to
473 * change the transaction ID so that the next transaction has a
474 * different TID in the log. Just add one to the existing tid
475 * so that we can see chains of rolling transactions in the log
476 * easily.
477 */
478 internal_ticket->t_tid++;
479
480 trace_xfs_log_reserve(log, internal_ticket);
481
482 xlog_grant_push_ail(log, internal_ticket->t_unit_res);
483 retval = xlog_regrant_write_log_space(log, internal_ticket);
484 } else {
485 /* may sleep if need to allocate more tickets */
486 internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt,
487 client, flags,
488 KM_SLEEP|KM_MAYFAIL);
489 if (!internal_ticket)
490 return XFS_ERROR(ENOMEM);
491 internal_ticket->t_trans_type = t_type;
492 *ticket = internal_ticket;
493
494 trace_xfs_log_reserve(log, internal_ticket);
495
496 xlog_grant_push_ail(log,
497 (internal_ticket->t_unit_res *
498 internal_ticket->t_cnt));
499 retval = xlog_grant_log_space(log, internal_ticket);
500 }
501
502 if (unlikely(retval)) {
503 /*
504 * If we are failing, make sure the ticket doesn't have any
505 * current reservations. We don't want to add this back
506 * when the ticket/ transaction gets cancelled.
507 */
508 internal_ticket->t_curr_res = 0;
509 /* ungrant will give back unit_res * t_cnt. */
510 internal_ticket->t_cnt = 0;
511 }
512
513 return retval;
514}
515
516
517/*
518 * Mount a log filesystem 553 * Mount a log filesystem
519 * 554 *
520 * mp - ubiquitous xfs mount point structure 555 * mp - ubiquitous xfs mount point structure
@@ -2565,58 +2600,6 @@ restart:
2565 return 0; 2600 return 0;
2566} /* xlog_state_get_iclog_space */ 2601} /* xlog_state_get_iclog_space */
2567 2602
2568STATIC int
2569xlog_grant_log_space(
2570 struct log *log,
2571 struct xlog_ticket *tic)
2572{
2573 int need_bytes;
2574 int error = 0;
2575
2576 trace_xfs_log_grant_enter(log, tic);
2577
2578 error = xlog_grant_head_check(log, &log->l_reserve_head, tic,
2579 &need_bytes);
2580 if (error)
2581 return error;
2582
2583 xlog_grant_add_space(log, &log->l_reserve_head.grant, need_bytes);
2584 xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
2585 trace_xfs_log_grant_exit(log, tic);
2586 xlog_verify_grant_tail(log);
2587 return 0;
2588}
2589
2590/*
2591 * Replenish the byte reservation required by moving the grant write head.
2592 */
2593STATIC int
2594xlog_regrant_write_log_space(
2595 struct log *log,
2596 struct xlog_ticket *tic)
2597{
2598 int need_bytes;
2599 int error = 0;
2600
2601 tic->t_curr_res = tic->t_unit_res;
2602 xlog_tic_reset_res(tic);
2603
2604 if (tic->t_cnt > 0)
2605 return 0;
2606
2607 trace_xfs_log_regrant_write_enter(log, tic);
2608
2609 error = xlog_grant_head_check(log, &log->l_write_head, tic,
2610 &need_bytes);
2611 if (error)
2612 return error;
2613
2614 xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
2615 trace_xfs_log_regrant_write_exit(log, tic);
2616 xlog_verify_grant_tail(log);
2617 return 0;
2618}
2619
2620/* The first cnt-1 times through here we don't need to 2603/* The first cnt-1 times through here we don't need to
2621 * move the grant write head because the permanent 2604 * move the grant write head because the permanent
2622 * reservation has reserved cnt times the unit amount. 2605 * reservation has reserved cnt times the unit amount.
@@ -3156,7 +3139,7 @@ xlog_ticket_alloc(
3156 int unit_bytes, 3139 int unit_bytes,
3157 int cnt, 3140 int cnt,
3158 char client, 3141 char client,
3159 uint xflags, 3142 bool permanent,
3160 int alloc_flags) 3143 int alloc_flags)
3161{ 3144{
3162 struct xlog_ticket *tic; 3145 struct xlog_ticket *tic;
@@ -3260,7 +3243,7 @@ xlog_ticket_alloc(
3260 tic->t_clientid = client; 3243 tic->t_clientid = client;
3261 tic->t_flags = XLOG_TIC_INITED; 3244 tic->t_flags = XLOG_TIC_INITED;
3262 tic->t_trans_type = 0; 3245 tic->t_trans_type = 0;
3263 if (xflags & XFS_LOG_PERM_RESERV) 3246 if (permanent)
3264 tic->t_flags |= XLOG_TIC_PERM_RESERV; 3247 tic->t_flags |= XLOG_TIC_PERM_RESERV;
3265 3248
3266 xlog_tic_reset_res(tic); 3249 xlog_tic_reset_res(tic);