aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r--fs/gfs2/log.c119
1 files changed, 72 insertions, 47 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 7df702473252..161ab6f2058e 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
4 * 4 *
5 * This copyrighted material is made available to anyone wishing to use, 5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions 6 * modify, copy, or redistribute it subject to the terms and conditions
@@ -16,6 +16,8 @@
16#include <linux/crc32.h> 16#include <linux/crc32.h>
17#include <linux/lm_interface.h> 17#include <linux/lm_interface.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/kthread.h>
20#include <linux/freezer.h>
19 21
20#include "gfs2.h" 22#include "gfs2.h"
21#include "incore.h" 23#include "incore.h"
@@ -68,14 +70,12 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
68 * 70 *
69 */ 71 */
70 72
71void gfs2_remove_from_ail(struct address_space *mapping, struct gfs2_bufdata *bd) 73void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
72{ 74{
73 bd->bd_ail = NULL; 75 bd->bd_ail = NULL;
74 list_del_init(&bd->bd_ail_st_list); 76 list_del_init(&bd->bd_ail_st_list);
75 list_del_init(&bd->bd_ail_gl_list); 77 list_del_init(&bd->bd_ail_gl_list);
76 atomic_dec(&bd->bd_gl->gl_ail_count); 78 atomic_dec(&bd->bd_gl->gl_ail_count);
77 if (mapping)
78 gfs2_meta_cache_flush(GFS2_I(mapping->host));
79 brelse(bd->bd_bh); 79 brelse(bd->bd_bh);
80} 80}
81 81
@@ -92,8 +92,6 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
92 struct buffer_head *bh; 92 struct buffer_head *bh;
93 int retry; 93 int retry;
94 94
95 BUG_ON(!spin_is_locked(&sdp->sd_log_lock));
96
97 do { 95 do {
98 retry = 0; 96 retry = 0;
99 97
@@ -210,7 +208,7 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
210 gfs2_log_unlock(sdp); 208 gfs2_log_unlock(sdp);
211} 209}
212 210
213int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags) 211static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags)
214{ 212{
215 struct gfs2_ail *ai, *s; 213 struct gfs2_ail *ai, *s;
216 int ret; 214 int ret;
@@ -248,7 +246,7 @@ static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
248 bd = list_entry(head->prev, struct gfs2_bufdata, 246 bd = list_entry(head->prev, struct gfs2_bufdata,
249 bd_ail_st_list); 247 bd_ail_st_list);
250 gfs2_assert(sdp, bd->bd_ail == ai); 248 gfs2_assert(sdp, bd->bd_ail == ai);
251 gfs2_remove_from_ail(bd->bd_bh->b_page->mapping, bd); 249 gfs2_remove_from_ail(bd);
252 } 250 }
253} 251}
254 252
@@ -303,7 +301,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
303 301
304 mutex_lock(&sdp->sd_log_reserve_mutex); 302 mutex_lock(&sdp->sd_log_reserve_mutex);
305 gfs2_log_lock(sdp); 303 gfs2_log_lock(sdp);
306 while(sdp->sd_log_blks_free <= (blks + reserved_blks)) { 304 while(atomic_read(&sdp->sd_log_blks_free) <= (blks + reserved_blks)) {
307 gfs2_log_unlock(sdp); 305 gfs2_log_unlock(sdp);
308 gfs2_ail1_empty(sdp, 0); 306 gfs2_ail1_empty(sdp, 0);
309 gfs2_log_flush(sdp, NULL); 307 gfs2_log_flush(sdp, NULL);
@@ -312,7 +310,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
312 gfs2_ail1_start(sdp, 0); 310 gfs2_ail1_start(sdp, 0);
313 gfs2_log_lock(sdp); 311 gfs2_log_lock(sdp);
314 } 312 }
315 sdp->sd_log_blks_free -= blks; 313 atomic_sub(blks, &sdp->sd_log_blks_free);
316 gfs2_log_unlock(sdp); 314 gfs2_log_unlock(sdp);
317 mutex_unlock(&sdp->sd_log_reserve_mutex); 315 mutex_unlock(&sdp->sd_log_reserve_mutex);
318 316
@@ -332,27 +330,23 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
332{ 330{
333 331
334 gfs2_log_lock(sdp); 332 gfs2_log_lock(sdp);
335 sdp->sd_log_blks_free += blks; 333 atomic_add(blks, &sdp->sd_log_blks_free);
336 gfs2_assert_withdraw(sdp, 334 gfs2_assert_withdraw(sdp,
337 sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); 335 atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks);
338 gfs2_log_unlock(sdp); 336 gfs2_log_unlock(sdp);
339 up_read(&sdp->sd_log_flush_lock); 337 up_read(&sdp->sd_log_flush_lock);
340} 338}
341 339
342static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) 340static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
343{ 341{
344 struct inode *inode = sdp->sd_jdesc->jd_inode; 342 struct gfs2_journal_extent *je;
345 int error; 343
346 struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; 344 list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) {
347 345 if (lbn >= je->lblock && lbn < je->lblock + je->blocks)
348 bh_map.b_size = 1 << inode->i_blkbits; 346 return je->dblock + lbn - je->lblock;
349 error = gfs2_block_map(inode, lbn, 0, &bh_map); 347 }
350 if (error || !bh_map.b_blocknr) 348
351 printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, 349 return -1;
352 (unsigned long long)bh_map.b_blocknr, lbn);
353 gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr);
354
355 return bh_map.b_blocknr;
356} 350}
357 351
358/** 352/**
@@ -561,8 +555,8 @@ static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
561 ail2_empty(sdp, new_tail); 555 ail2_empty(sdp, new_tail);
562 556
563 gfs2_log_lock(sdp); 557 gfs2_log_lock(sdp);
564 sdp->sd_log_blks_free += dist; 558 atomic_add(dist, &sdp->sd_log_blks_free);
565 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); 559 gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks);
566 gfs2_log_unlock(sdp); 560 gfs2_log_unlock(sdp);
567 561
568 sdp->sd_log_tail = new_tail; 562 sdp->sd_log_tail = new_tail;
@@ -652,7 +646,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
652 get_bh(bh); 646 get_bh(bh);
653 gfs2_log_unlock(sdp); 647 gfs2_log_unlock(sdp);
654 lock_buffer(bh); 648 lock_buffer(bh);
655 if (test_clear_buffer_dirty(bh)) { 649 if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) {
656 bh->b_end_io = end_buffer_write_sync; 650 bh->b_end_io = end_buffer_write_sync;
657 submit_bh(WRITE, bh); 651 submit_bh(WRITE, bh);
658 } else { 652 } else {
@@ -694,20 +688,16 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
694 * 688 *
695 */ 689 */
696 690
697void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) 691void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
698{ 692{
699 struct gfs2_ail *ai; 693 struct gfs2_ail *ai;
700 694
701 down_write(&sdp->sd_log_flush_lock); 695 down_write(&sdp->sd_log_flush_lock);
702 696
703 if (gl) { 697 /* Log might have been flushed while we waited for the flush lock */
704 gfs2_log_lock(sdp); 698 if (gl && !test_bit(GLF_LFLUSH, &gl->gl_flags)) {
705 if (list_empty(&gl->gl_le.le_list)) { 699 up_write(&sdp->sd_log_flush_lock);
706 gfs2_log_unlock(sdp); 700 return;
707 up_write(&sdp->sd_log_flush_lock);
708 return;
709 }
710 gfs2_log_unlock(sdp);
711 } 701 }
712 702
713 ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL); 703 ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
@@ -739,7 +729,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
739 log_flush_commit(sdp); 729 log_flush_commit(sdp);
740 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ 730 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
741 gfs2_log_lock(sdp); 731 gfs2_log_lock(sdp);
742 sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */ 732 atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
743 gfs2_log_unlock(sdp); 733 gfs2_log_unlock(sdp);
744 log_write_header(sdp, 0, PULL); 734 log_write_header(sdp, 0, PULL);
745 } 735 }
@@ -767,7 +757,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
767static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 757static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
768{ 758{
769 unsigned int reserved; 759 unsigned int reserved;
770 unsigned int old; 760 unsigned int unused;
771 761
772 gfs2_log_lock(sdp); 762 gfs2_log_lock(sdp);
773 763
@@ -779,14 +769,11 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
779 sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; 769 sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
780 gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); 770 gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
781 reserved = calc_reserved(sdp); 771 reserved = calc_reserved(sdp);
782 old = sdp->sd_log_blks_free; 772 unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
783 sdp->sd_log_blks_free += tr->tr_reserved - 773 gfs2_assert_withdraw(sdp, unused >= 0);
784 (reserved - sdp->sd_log_blks_reserved); 774 atomic_add(unused, &sdp->sd_log_blks_free);
785 775 gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
786 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
787 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
788 sdp->sd_jdesc->jd_blocks); 776 sdp->sd_jdesc->jd_blocks);
789
790 sdp->sd_log_blks_reserved = reserved; 777 sdp->sd_log_blks_reserved = reserved;
791 778
792 gfs2_log_unlock(sdp); 779 gfs2_log_unlock(sdp);
@@ -825,7 +812,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
825 down_write(&sdp->sd_log_flush_lock); 812 down_write(&sdp->sd_log_flush_lock);
826 813
827 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); 814 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
828 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl);
829 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); 815 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
830 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); 816 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
831 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); 817 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
@@ -838,7 +824,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
838 log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 824 log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
839 (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL); 825 (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
840 826
841 gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks); 827 gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
842 gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); 828 gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
843 gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list)); 829 gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
844 830
@@ -866,3 +852,42 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
866 } 852 }
867} 853}
868 854
855
856/**
857 * gfs2_logd - Update log tail as Active Items get flushed to in-place blocks
858 * @sdp: Pointer to GFS2 superblock
859 *
860 * Also, periodically check to make sure that we're using the most recent
861 * journal index.
862 */
863
864int gfs2_logd(void *data)
865{
866 struct gfs2_sbd *sdp = data;
867 unsigned long t;
868 int need_flush;
869
870 while (!kthread_should_stop()) {
871 /* Advance the log tail */
872
873 t = sdp->sd_log_flush_time +
874 gfs2_tune_get(sdp, gt_log_flush_secs) * HZ;
875
876 gfs2_ail1_empty(sdp, DIO_ALL);
877 gfs2_log_lock(sdp);
878 need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks);
879 gfs2_log_unlock(sdp);
880 if (need_flush || time_after_eq(jiffies, t)) {
881 gfs2_log_flush(sdp, NULL);
882 sdp->sd_log_flush_time = jiffies;
883 }
884
885 t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
886 if (freezing(current))
887 refrigerator();
888 schedule_timeout_interruptible(t);
889 }
890
891 return 0;
892}
893