aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/lops.c
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 /fs/gfs2/lops.c
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>
Diffstat (limited to 'fs/gfs2/lops.c')
-rw-r--r--fs/gfs2/lops.c53
1 files changed, 23 insertions, 30 deletions
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--;