aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Peterson <rpeterso@redhat.com>2007-06-18 15:50:20 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-07-09 03:23:47 -0400
commit2332c4435bb733b5cd4f612ee57532bd8fde4c1c (patch)
treedfa006c482a6e9c1a5e693478b424db0f5492fbe
parent2840501ac822c5bf712f67b4b02640e16e145a29 (diff)
[GFS2] assertion failure after writing to journaled file, umount
This patch passes all my nasty tests that were causing the code to fail under one circumstance or another. Here is a complete summary of all changes from today's git tree, in order of appearance: 1. There are now separate variables for metadata buffer accounting. 2. Variable sd_log_num_hdrs is no longer needed, since the header accounting is taken care of by the reserve/refund sequence. 3. Fixed a tiny grammatical problem in a comment. 4. Added a new function "calc_reserved" to calculate the reserved log space. This isn't entirely necessary, but it has two benefits: First, it simplifies the gfs2_log_refund function greatly. Second, it allows for easier debugging because I could sprinkle the code with calls to this function to make sure the accounting is proper (by adding asserts and printks) at strategic point of the code. 5. In log_pull_tail there apparently was a kludge to fix up the accounting based on a "pull" parameter. The buffer accounting is now done properly, so the kludge was removed. 6. File sync operations were making a call to gfs2_log_flush that writes another journal header. Since that header was unplanned for (reserved) by the reserve/refund sequence, the free space had to be decremented so that when log_pull_tail gets called, the free space is be adjusted properly. (Did I hear you call that a kludge? well, maybe, but a lot more justifiable than the one I removed). 7. In the gfs2_log_shutdown code, it optionally syncs the log by specifying the PULL parameter to log_write_header. I'm not sure this is necessary anymore. It just seems to me there could be cases where shutdown is called while there are outstanding log buffers. 8. In the (data)buf_lo_before_commit functions, I changed some offset values from being calculated on the fly to being constants. That simplified some code and we might as well let the compiler do the calculation once rather than redoing those cycles at run time. 9. This version has my rewritten databuf_lo_add function. This version is much more like its predecessor, buf_lo_add, which makes it easier to understand. Again, this might not be necessary, but it seems as if this one works as well as the previous one, maybe even better, so I decided to leave it in. 10. In databuf_lo_before_commit, a previous data corruption problem was caused by going off the end of the buffer. The proper solution is to have the proper limit in place, rather than stopping earlier. (Thus my previous attempt to fix it is wrong). If you don't wrap the buffer, you're stopping too early and that causes more log buffer accounting problems. 11. In lops.h there are two new (previously mentioned) constants for figuring out the data offset for the journal buffers. 12. There are also two new functions, buf_limit and databuf_limit to calculate how many entries will fit in the buffer. 13. In function gfs2_meta_wipe, it needs to distinguish between pinned metadata buffers and journaled data buffers for proper journal buffer accounting. It can't use the JDATA gfs2_inode flag because it's sometimes passed the "real" inode and sometimes the "metadata inode" and the inode flags will be random bits in a metadata gfs2_inode. It needs to base its decision on which was passed in. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/incore.h4
-rw-r--r--fs/gfs2/log.c100
-rw-r--r--fs/gfs2/lops.c53
-rw-r--r--fs/gfs2/lops.h23
-rw-r--r--fs/gfs2/meta_io.c8
5 files changed, 132 insertions, 56 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index c7c6ec0f17c7..170ba93829c0 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -354,7 +354,9 @@ struct gfs2_trans {
354 354
355 unsigned int tr_num_buf; 355 unsigned int tr_num_buf;
356 unsigned int tr_num_buf_new; 356 unsigned int tr_num_buf_new;
357 unsigned int tr_num_databuf_new;
357 unsigned int tr_num_buf_rm; 358 unsigned int tr_num_buf_rm;
359 unsigned int tr_num_databuf_rm;
358 struct list_head tr_list_buf; 360 struct list_head tr_list_buf;
359 361
360 unsigned int tr_num_revoke; 362 unsigned int tr_num_revoke;
@@ -599,6 +601,7 @@ struct gfs2_sbd {
599 601
600 unsigned int sd_log_blks_reserved; 602 unsigned int sd_log_blks_reserved;
601 unsigned int sd_log_commited_buf; 603 unsigned int sd_log_commited_buf;
604 unsigned int sd_log_commited_databuf;
602 unsigned int sd_log_commited_revoke; 605 unsigned int sd_log_commited_revoke;
603 606
604 unsigned int sd_log_num_gl; 607 unsigned int sd_log_num_gl;
@@ -607,7 +610,6 @@ struct gfs2_sbd {
607 unsigned int sd_log_num_rg; 610 unsigned int sd_log_num_rg;
608 unsigned int sd_log_num_databuf; 611 unsigned int sd_log_num_databuf;
609 unsigned int sd_log_num_jdata; 612 unsigned int sd_log_num_jdata;
610 unsigned int sd_log_num_hdrs;
611 613
612 struct list_head sd_log_le_gl; 614 struct list_head sd_log_le_gl;
613 struct list_head sd_log_le_buf; 615 struct list_head sd_log_le_buf;
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index fbdc0dc9923e..8fcfb784f906 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -276,7 +276,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
276 * @blks: The number of blocks to reserve 276 * @blks: The number of blocks to reserve
277 * 277 *
278 * Note that we never give out the last few blocks of the journal. Thats 278 * Note that we never give out the last few blocks of the journal. Thats
279 * due to the fact that there is are a small number of header blocks 279 * due to the fact that there is a small number of header blocks
280 * associated with each log flush. The exact number can't be known until 280 * associated with each log flush. The exact number can't be known until
281 * flush time, so we ensure that we have just enough free blocks at all 281 * flush time, so we ensure that we have just enough free blocks at all
282 * times to avoid running out during a log flush. 282 * times to avoid running out during a log flush.
@@ -371,6 +371,58 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer
371 return dist; 371 return dist;
372} 372}
373 373
374/**
375 * calc_reserved - Calculate the number of blocks to reserve when
376 * refunding a transaction's unused buffers.
377 * @sdp: The GFS2 superblock
378 *
379 * This is complex. We need to reserve room for all our currently used
380 * metadata buffers (e.g. normal file I/O rewriting file time stamps) and
381 * all our journaled data buffers for journaled files (e.g. files in the
382 * meta_fs like rindex, or files for which chattr +j was done.)
383 * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush
384 * will count it as free space (sd_log_blks_free) and corruption will follow.
385 *
386 * We can have metadata bufs and jdata bufs in the same journal. So each
387 * type gets its own log header, for which we need to reserve a block.
388 * In fact, each type has the potential for needing more than one header
389 * in cases where we have more buffers than will fit on a journal page.
390 * Metadata journal entries take up half the space of journaled buffer entries.
391 * Thus, metadata entries have buf_limit (502) and journaled buffers have
392 * databuf_limit (251) before they cause a wrap around.
393 *
394 * Also, we need to reserve blocks for revoke journal entries and one for an
395 * overall header for the lot.
396 *
397 * Returns: the number of blocks reserved
398 */
399static unsigned int calc_reserved(struct gfs2_sbd *sdp)
400{
401 unsigned int reserved = 0;
402 unsigned int mbuf_limit, metabufhdrs_needed;
403 unsigned int dbuf_limit, databufhdrs_needed;
404 unsigned int revokes = 0;
405
406 mbuf_limit = buf_limit(sdp);
407 metabufhdrs_needed = (sdp->sd_log_commited_buf +
408 (mbuf_limit - 1)) / mbuf_limit;
409 dbuf_limit = databuf_limit(sdp);
410 databufhdrs_needed = (sdp->sd_log_commited_databuf +
411 (dbuf_limit - 1)) / dbuf_limit;
412
413 if (sdp->sd_log_commited_revoke)
414 revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
415 sizeof(u64));
416
417 reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
418 sdp->sd_log_commited_databuf + databufhdrs_needed +
419 revokes;
420 /* One for the overall header */
421 if (reserved)
422 reserved++;
423 return reserved;
424}
425
374static unsigned int current_tail(struct gfs2_sbd *sdp) 426static unsigned int current_tail(struct gfs2_sbd *sdp)
375{ 427{
376 struct gfs2_ail *ai; 428 struct gfs2_ail *ai;
@@ -461,14 +513,14 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
461 return bh; 513 return bh;
462} 514}
463 515
464static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull) 516static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
465{ 517{
466 unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); 518 unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
467 519
468 ail2_empty(sdp, new_tail); 520 ail2_empty(sdp, new_tail);
469 521
470 gfs2_log_lock(sdp); 522 gfs2_log_lock(sdp);
471 sdp->sd_log_blks_free += dist - (pull ? 1 : 0); 523 sdp->sd_log_blks_free += dist;
472 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); 524 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
473 gfs2_log_unlock(sdp); 525 gfs2_log_unlock(sdp);
474 526
@@ -518,7 +570,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
518 brelse(bh); 570 brelse(bh);
519 571
520 if (sdp->sd_log_tail != tail) 572 if (sdp->sd_log_tail != tail)
521 log_pull_tail(sdp, tail, pull); 573 log_pull_tail(sdp, tail);
522 else 574 else
523 gfs2_assert_withdraw(sdp, !pull); 575 gfs2_assert_withdraw(sdp, !pull);
524 576
@@ -579,7 +631,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
579 INIT_LIST_HEAD(&ai->ai_ail1_list); 631 INIT_LIST_HEAD(&ai->ai_ail1_list);
580 INIT_LIST_HEAD(&ai->ai_ail2_list); 632 INIT_LIST_HEAD(&ai->ai_ail2_list);
581 633
582 gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf + sdp->sd_log_num_jdata == sdp->sd_log_commited_buf); 634 gfs2_assert_withdraw(sdp,
635 sdp->sd_log_num_buf + sdp->sd_log_num_jdata ==
636 sdp->sd_log_commited_buf +
637 sdp->sd_log_commited_databuf);
583 gfs2_assert_withdraw(sdp, 638 gfs2_assert_withdraw(sdp,
584 sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); 639 sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
585 640
@@ -590,16 +645,19 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
590 lops_before_commit(sdp); 645 lops_before_commit(sdp);
591 if (!list_empty(&sdp->sd_log_flush_list)) 646 if (!list_empty(&sdp->sd_log_flush_list))
592 log_flush_commit(sdp); 647 log_flush_commit(sdp);
593 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle) 648 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
649 gfs2_log_lock(sdp);
650 sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */
651 gfs2_log_unlock(sdp);
594 log_write_header(sdp, 0, PULL); 652 log_write_header(sdp, 0, PULL);
653 }
595 lops_after_commit(sdp, ai); 654 lops_after_commit(sdp, ai);
596 655
597 gfs2_log_lock(sdp); 656 gfs2_log_lock(sdp);
598 sdp->sd_log_head = sdp->sd_log_flush_head; 657 sdp->sd_log_head = sdp->sd_log_flush_head;
599 sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs;
600 sdp->sd_log_blks_reserved = 0; 658 sdp->sd_log_blks_reserved = 0;
601 sdp->sd_log_commited_buf = 0; 659 sdp->sd_log_commited_buf = 0;
602 sdp->sd_log_num_hdrs = 0; 660 sdp->sd_log_commited_databuf = 0;
603 sdp->sd_log_commited_revoke = 0; 661 sdp->sd_log_commited_revoke = 0;
604 662
605 if (!list_empty(&ai->ai_ail1_list)) { 663 if (!list_empty(&ai->ai_ail1_list)) {
@@ -616,32 +674,26 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
616 674
617static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 675static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
618{ 676{
619 unsigned int reserved = 0; 677 unsigned int reserved;
620 unsigned int old; 678 unsigned int old;
621 679
622 gfs2_log_lock(sdp); 680 gfs2_log_lock(sdp);
623 681
624 sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; 682 sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
625 gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0); 683 sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
684 tr->tr_num_databuf_rm;
685 gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
686 (((int)sdp->sd_log_commited_databuf) >= 0));
626 sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; 687 sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
627 gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); 688 gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
628 689 reserved = calc_reserved(sdp);
629 if (sdp->sd_log_commited_buf)
630 reserved += sdp->sd_log_commited_buf;
631 if (sdp->sd_log_commited_revoke)
632 reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
633 sizeof(u64));
634 if (reserved)
635 reserved++;
636
637 old = sdp->sd_log_blks_free; 690 old = sdp->sd_log_blks_free;
638 sdp->sd_log_blks_free += tr->tr_reserved - 691 sdp->sd_log_blks_free += tr->tr_reserved -
639 (reserved - sdp->sd_log_blks_reserved); 692 (reserved - sdp->sd_log_blks_reserved);
640 693
641 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old); 694 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
642 gfs2_assert_withdraw(sdp, 695 gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
643 sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks + 696 sdp->sd_jdesc->jd_blocks);
644 sdp->sd_log_num_hdrs);
645 697
646 sdp->sd_log_blks_reserved = reserved; 698 sdp->sd_log_blks_reserved = reserved;
647 699
@@ -687,13 +739,13 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
687 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); 739 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
688 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); 740 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
689 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); 741 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
690 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs);
691 gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); 742 gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
692 743
693 sdp->sd_log_flush_head = sdp->sd_log_head; 744 sdp->sd_log_flush_head = sdp->sd_log_head;
694 sdp->sd_log_flush_wrapped = 0; 745 sdp->sd_log_flush_wrapped = 0;
695 746
696 log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0); 747 log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
748 (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
697 749
698 gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks); 750 gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks);
699 gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); 751 gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index df6bceea379a..dd810ad68cf0 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -17,6 +17,7 @@
17 17
18#include "gfs2.h" 18#include "gfs2.h"
19#include "incore.h" 19#include "incore.h"
20#include "inode.h"
20#include "glock.h" 21#include "glock.h"
21#include "log.h" 22#include "log.h"
22#include "lops.h" 23#include "lops.h"
@@ -117,15 +118,13 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
117 struct gfs2_log_descriptor *ld; 118 struct gfs2_log_descriptor *ld;
118 struct gfs2_bufdata *bd1 = NULL, *bd2; 119 struct gfs2_bufdata *bd1 = NULL, *bd2;
119 unsigned int total = sdp->sd_log_num_buf; 120 unsigned int total = sdp->sd_log_num_buf;
120 unsigned int offset = sizeof(struct gfs2_log_descriptor); 121 unsigned int offset = BUF_OFFSET;
121 unsigned int limit; 122 unsigned int limit;
122 unsigned int num; 123 unsigned int num;
123 unsigned n; 124 unsigned n;
124 __be64 *ptr; 125 __be64 *ptr;
125 126
126 offset += sizeof(__be64) - 1; 127 limit = buf_limit(sdp);
127 offset &= ~(sizeof(__be64) - 1);
128 limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
129 /* for 4k blocks, limit = 503 */ 128 /* for 4k blocks, limit = 503 */
130 129
131 bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); 130 bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
@@ -134,7 +133,6 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
134 if (total > limit) 133 if (total > limit)
135 num = limit; 134 num = limit;
136 bh = gfs2_log_get_buf(sdp); 135 bh = gfs2_log_get_buf(sdp);
137 sdp->sd_log_num_hdrs++;
138 ld = (struct gfs2_log_descriptor *)bh->b_data; 136 ld = (struct gfs2_log_descriptor *)bh->b_data;
139 ptr = (__be64 *)(bh->b_data + offset); 137 ptr = (__be64 *)(bh->b_data + offset);
140 ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); 138 ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
@@ -469,27 +467,26 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
469 struct gfs2_inode *ip = GFS2_I(mapping->host); 467 struct gfs2_inode *ip = GFS2_I(mapping->host);
470 468
471 gfs2_log_lock(sdp); 469 gfs2_log_lock(sdp);
472 tr->tr_touched = 1; 470 if (!list_empty(&bd->bd_list_tr)) {
473 if (list_empty(&bd->bd_list_tr) &&
474 (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
475 tr->tr_num_buf++;
476 list_add(&bd->bd_list_tr, &tr->tr_list_buf);
477 gfs2_log_unlock(sdp);
478 if (!list_empty(&le->le_list))
479 return;
480 gfs2_pin(sdp, bd->bd_bh);
481 tr->tr_num_buf_new++;
482 } else {
483 gfs2_log_unlock(sdp); 471 gfs2_log_unlock(sdp);
472 return;
484 } 473 }
474 tr->tr_touched = 1;
475 tr->tr_num_buf++;
476 list_add(&bd->bd_list_tr, &tr->tr_list_buf);
477 gfs2_log_unlock(sdp);
478 if (!list_empty(&le->le_list))
479 return;
480
485 gfs2_trans_add_gl(bd->bd_gl); 481 gfs2_trans_add_gl(bd->bd_gl);
486 gfs2_log_lock(sdp); 482 if (gfs2_is_jdata(ip)) {
487 if (list_empty(&le->le_list)) { 483 sdp->sd_log_num_jdata++;
488 if (ip->i_di.di_flags & GFS2_DIF_JDATA) 484 gfs2_pin(sdp, bd->bd_bh);
489 sdp->sd_log_num_jdata++; 485 tr->tr_num_databuf_new++;
490 sdp->sd_log_num_databuf++;
491 list_add(&le->le_list, &sdp->sd_log_le_databuf);
492 } 486 }
487 sdp->sd_log_num_databuf++;
488 gfs2_log_lock(sdp);
489 list_add(&le->le_list, &sdp->sd_log_le_databuf);
493 gfs2_log_unlock(sdp); 490 gfs2_log_unlock(sdp);
494} 491}
495 492
@@ -522,7 +519,6 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
522 LIST_HEAD(started); 519 LIST_HEAD(started);
523 struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt; 520 struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
524 struct buffer_head *bh = NULL,*bh1 = NULL; 521 struct buffer_head *bh = NULL,*bh1 = NULL;
525 unsigned int offset = sizeof(struct gfs2_log_descriptor);
526 struct gfs2_log_descriptor *ld; 522 struct gfs2_log_descriptor *ld;
527 unsigned int limit; 523 unsigned int limit;
528 unsigned int total_dbuf = sdp->sd_log_num_databuf; 524 unsigned int total_dbuf = sdp->sd_log_num_databuf;
@@ -530,9 +526,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
530 unsigned int num, n; 526 unsigned int num, n;
531 __be64 *ptr = NULL; 527 __be64 *ptr = NULL;
532 528
533 offset += 2*sizeof(__be64) - 1; 529 limit = databuf_limit(sdp);
534 offset &= ~(2*sizeof(__be64) - 1);
535 limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
536 530
537 /* 531 /*
538 * Start writing ordered buffers, write journaled buffers 532 * Start writing ordered buffers, write journaled buffers
@@ -583,10 +577,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
583 gfs2_log_unlock(sdp); 577 gfs2_log_unlock(sdp);
584 if (!bh) { 578 if (!bh) {
585 bh = gfs2_log_get_buf(sdp); 579 bh = gfs2_log_get_buf(sdp);
586 sdp->sd_log_num_hdrs++;
587 ld = (struct gfs2_log_descriptor *) 580 ld = (struct gfs2_log_descriptor *)
588 bh->b_data; 581 bh->b_data;
589 ptr = (__be64 *)(bh->b_data + offset); 582 ptr = (__be64 *)(bh->b_data +
583 DATABUF_OFFSET);
590 ld->ld_header.mh_magic = 584 ld->ld_header.mh_magic =
591 cpu_to_be32(GFS2_MAGIC); 585 cpu_to_be32(GFS2_MAGIC);
592 ld->ld_header.mh_type = 586 ld->ld_header.mh_type =
@@ -607,8 +601,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
607 if (unlikely(magic != 0)) 601 if (unlikely(magic != 0))
608 set_buffer_escaped(bh1); 602 set_buffer_escaped(bh1);
609 gfs2_log_lock(sdp); 603 gfs2_log_lock(sdp);
610 n += 2; 604 if (++n >= num)
611 if (n >= num)
612 break; 605 break;
613 } else if (!bh1) { 606 } else if (!bh1) {
614 total_dbuf--; 607 total_dbuf--;
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 965bc65c7c64..41a00df75587 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -13,6 +13,13 @@
13#include <linux/list.h> 13#include <linux/list.h>
14#include "incore.h" 14#include "incore.h"
15 15
16#define BUF_OFFSET \
17 ((sizeof(struct gfs2_log_descriptor) + sizeof(__be64) - 1) & \
18 ~(sizeof(__be64) - 1))
19#define DATABUF_OFFSET \
20 ((sizeof(struct gfs2_log_descriptor) + (2 * sizeof(__be64) - 1)) & \
21 ~(2 * sizeof(__be64) - 1))
22
16extern const struct gfs2_log_operations gfs2_glock_lops; 23extern const struct gfs2_log_operations gfs2_glock_lops;
17extern const struct gfs2_log_operations gfs2_buf_lops; 24extern const struct gfs2_log_operations gfs2_buf_lops;
18extern const struct gfs2_log_operations gfs2_revoke_lops; 25extern const struct gfs2_log_operations gfs2_revoke_lops;
@@ -21,6 +28,22 @@ extern const struct gfs2_log_operations gfs2_databuf_lops;
21 28
22extern const struct gfs2_log_operations *gfs2_log_ops[]; 29extern const struct gfs2_log_operations *gfs2_log_ops[];
23 30
31static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
32{
33 unsigned int limit;
34
35 limit = (sdp->sd_sb.sb_bsize - BUF_OFFSET) / sizeof(__be64);
36 return limit;
37}
38
39static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
40{
41 unsigned int limit;
42
43 limit = (sdp->sd_sb.sb_bsize - DATABUF_OFFSET) / (2 * sizeof(__be64));
44 return limit;
45}
46
24static inline void lops_init_le(struct gfs2_log_element *le, 47static inline void lops_init_le(struct gfs2_log_element *le,
25 const struct gfs2_log_operations *lops) 48 const struct gfs2_log_operations *lops)
26{ 49{
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index e62d4f620c58..8da343b34ae7 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -387,12 +387,18 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
387 387
388 if (test_clear_buffer_pinned(bh)) { 388 if (test_clear_buffer_pinned(bh)) {
389 struct gfs2_trans *tr = current->journal_info; 389 struct gfs2_trans *tr = current->journal_info;
390 struct gfs2_inode *bh_ip =
391 GFS2_I(bh->b_page->mapping->host);
392
390 gfs2_log_lock(sdp); 393 gfs2_log_lock(sdp);
391 list_del_init(&bd->bd_le.le_list); 394 list_del_init(&bd->bd_le.le_list);
392 gfs2_assert_warn(sdp, sdp->sd_log_num_buf); 395 gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
393 sdp->sd_log_num_buf--; 396 sdp->sd_log_num_buf--;
394 gfs2_log_unlock(sdp); 397 gfs2_log_unlock(sdp);
395 tr->tr_num_buf_rm++; 398 if (bh_ip->i_inode.i_private != NULL)
399 tr->tr_num_databuf_rm++;
400 else
401 tr->tr_num_buf_rm++;
396 brelse(bh); 402 brelse(bh);
397 } 403 }
398 if (bd) { 404 if (bd) {