aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/xfs/xfs_log.c265
-rw-r--r--fs/xfs/xfs_log.h12
-rw-r--r--fs/xfs/xfs_log_priv.h2
-rw-r--r--fs/xfs/xfs_trace.h11
-rw-r--r--fs/xfs/xfs_trans.c31
5 files changed, 151 insertions, 170 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);
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index fe32c6927877..2c622bedb302 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -53,15 +53,6 @@ static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
53#define XFS_LOG_REL_PERM_RESERV 0x1 53#define XFS_LOG_REL_PERM_RESERV 0x1
54 54
55/* 55/*
56 * Flags to xfs_log_reserve()
57 *
58 * XFS_LOG_PERM_RESERV: Permanent reservation. When writes are
59 * performed against this type of reservation, the reservation
60 * is not decreased. Long running transactions should use this.
61 */
62#define XFS_LOG_PERM_RESERV 0x2
63
64/*
65 * Flags to xfs_log_force() 56 * Flags to xfs_log_force()
66 * 57 *
67 * XFS_LOG_SYNC: Synchronous force in-core log to disk 58 * XFS_LOG_SYNC: Synchronous force in-core log to disk
@@ -172,8 +163,9 @@ int xfs_log_reserve(struct xfs_mount *mp,
172 int count, 163 int count,
173 struct xlog_ticket **ticket, 164 struct xlog_ticket **ticket,
174 __uint8_t clientid, 165 __uint8_t clientid,
175 uint flags, 166 bool permanent,
176 uint t_type); 167 uint t_type);
168int xfs_log_regrant(struct xfs_mount *mp, struct xlog_ticket *tic);
177int xfs_log_unmount_write(struct xfs_mount *mp); 169int xfs_log_unmount_write(struct xfs_mount *mp);
178void xfs_log_unmount(struct xfs_mount *mp); 170void xfs_log_unmount(struct xfs_mount *mp);
179int xfs_log_force_umount(struct xfs_mount *mp, int logerror); 171int xfs_log_force_umount(struct xfs_mount *mp, int logerror);
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index eba4ec925a45..2152900b79d4 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -552,7 +552,7 @@ extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
552 552
553extern kmem_zone_t *xfs_log_ticket_zone; 553extern kmem_zone_t *xfs_log_ticket_zone;
554struct xlog_ticket *xlog_ticket_alloc(struct log *log, int unit_bytes, 554struct xlog_ticket *xlog_ticket_alloc(struct log *log, int unit_bytes,
555 int count, char client, uint xflags, 555 int count, char client, bool permanent,
556 int alloc_flags); 556 int alloc_flags);
557 557
558 558
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 482bebf8c7ef..3b369c1277f0 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -826,17 +826,14 @@ DEFINE_EVENT(xfs_loggrant_class, name, \
826 TP_ARGS(log, tic)) 826 TP_ARGS(log, tic))
827DEFINE_LOGGRANT_EVENT(xfs_log_done_nonperm); 827DEFINE_LOGGRANT_EVENT(xfs_log_done_nonperm);
828DEFINE_LOGGRANT_EVENT(xfs_log_done_perm); 828DEFINE_LOGGRANT_EVENT(xfs_log_done_perm);
829DEFINE_LOGGRANT_EVENT(xfs_log_reserve);
830DEFINE_LOGGRANT_EVENT(xfs_log_umount_write); 829DEFINE_LOGGRANT_EVENT(xfs_log_umount_write);
831DEFINE_LOGGRANT_EVENT(xfs_log_grant_enter);
832DEFINE_LOGGRANT_EVENT(xfs_log_grant_exit);
833DEFINE_LOGGRANT_EVENT(xfs_log_grant_error);
834DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep); 830DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep);
835DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake); 831DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake);
836DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up); 832DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up);
837DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter); 833DEFINE_LOGGRANT_EVENT(xfs_log_reserve);
838DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit); 834DEFINE_LOGGRANT_EVENT(xfs_log_reserve_exit);
839DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error); 835DEFINE_LOGGRANT_EVENT(xfs_log_regrant);
836DEFINE_LOGGRANT_EVENT(xfs_log_regrant_exit);
840DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter); 837DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter);
841DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit); 838DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit);
842DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_sub); 839DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_sub);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 7adcdf15ae0c..103b00c90004 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -681,7 +681,6 @@ xfs_trans_reserve(
681 uint flags, 681 uint flags,
682 uint logcount) 682 uint logcount)
683{ 683{
684 int log_flags;
685 int error = 0; 684 int error = 0;
686 int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; 685 int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
687 686
@@ -707,24 +706,32 @@ xfs_trans_reserve(
707 * Reserve the log space needed for this transaction. 706 * Reserve the log space needed for this transaction.
708 */ 707 */
709 if (logspace > 0) { 708 if (logspace > 0) {
710 ASSERT((tp->t_log_res == 0) || (tp->t_log_res == logspace)); 709 bool permanent = false;
711 ASSERT((tp->t_log_count == 0) || 710
712 (tp->t_log_count == logcount)); 711 ASSERT(tp->t_log_res == 0 || tp->t_log_res == logspace);
712 ASSERT(tp->t_log_count == 0 || tp->t_log_count == logcount);
713
713 if (flags & XFS_TRANS_PERM_LOG_RES) { 714 if (flags & XFS_TRANS_PERM_LOG_RES) {
714 log_flags = XFS_LOG_PERM_RESERV;
715 tp->t_flags |= XFS_TRANS_PERM_LOG_RES; 715 tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
716 permanent = true;
716 } else { 717 } else {
717 ASSERT(tp->t_ticket == NULL); 718 ASSERT(tp->t_ticket == NULL);
718 ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); 719 ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
719 log_flags = 0;
720 } 720 }
721 721
722 error = xfs_log_reserve(tp->t_mountp, logspace, logcount, 722 if (tp->t_ticket != NULL) {
723 &tp->t_ticket, 723 ASSERT(flags & XFS_TRANS_PERM_LOG_RES);
724 XFS_TRANSACTION, log_flags, tp->t_type); 724 error = xfs_log_regrant(tp->t_mountp, tp->t_ticket);
725 if (error) { 725 } else {
726 goto undo_blocks; 726 error = xfs_log_reserve(tp->t_mountp, logspace,
727 logcount, &tp->t_ticket,
728 XFS_TRANSACTION, permanent,
729 tp->t_type);
727 } 730 }
731
732 if (error)
733 goto undo_blocks;
734
728 tp->t_log_res = logspace; 735 tp->t_log_res = logspace;
729 tp->t_log_count = logcount; 736 tp->t_log_count = logcount;
730 } 737 }
@@ -752,6 +759,8 @@ xfs_trans_reserve(
752 */ 759 */
753undo_log: 760undo_log:
754 if (logspace > 0) { 761 if (logspace > 0) {
762 int log_flags;
763
755 if (flags & XFS_TRANS_PERM_LOG_RES) { 764 if (flags & XFS_TRANS_PERM_LOG_RES) {
756 log_flags = XFS_LOG_REL_PERM_RESERV; 765 log_flags = XFS_LOG_REL_PERM_RESERV;
757 } else { 766 } else {