summaryrefslogtreecommitdiff
path: root/fs/gfs2/log.c
diff options
context:
space:
mode:
authorRobert Peterson <rpeterso@redhat.com>2007-06-12 11:24:36 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2007-07-09 08:23:40 +0100
commit8fb68595d508fd30ec90939572484b263600376c (patch)
tree218a457675c111e2224fb57998d38e45d5786bd1 /fs/gfs2/log.c
parentfad59c1390045b5adb7c7249ec4e77e0f868aca5 (diff)
downloadlinux-8fb68595d508fd30ec90939572484b263600376c.tar.gz
[GFS2] Journaled file write/unstuff bug
This patch is for bugzilla bug 283162, which uncovered a number of bugs pertaining to writing to files that have the journaled bit on. These bugs happen most often when writing to the meta_fs because the files are always journaled. So operations like gfs2_grow were particularly vulnerable, although many of the problems could be recreated with normal files after setting the journaled bit on. The problems fixed are: -GFS2 wasn't ever writing unstuffed journaled data blocks to their in-place location on disk. Now it does. -If you unmounted too quickly after doing IO to a journaled file, GFS2 was crashing because you would discard a buffer whose bufdata was still on the active items list. GFS2 now deals with this gracefully. -GFS2 was losing track of the bufdata for journaled data blocks, and it wasn't getting freed, causing an error when you tried to unmount the module. GFS2 now frees all the bufdata structures. -There was a memory corruption occurring because GFS2 wrote twice as many log entries for journaled buffers. -It was occasionally trying to write journal headers in buffers that weren't currently mapped. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r--fs/gfs2/log.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 1fb846fc545e..fbdc0dc9923e 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -83,6 +83,11 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
gfs2_assert(sdp, bd->bd_ail == ai);
+ if (!bh){
+ list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+ continue;
+ }
+
if (!buffer_busy(bh)) {
if (!buffer_uptodate(bh)) {
gfs2_log_unlock(sdp);
@@ -125,6 +130,11 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl
bd_ail_st_list) {
bh = bd->bd_bh;
+ if (!bh){
+ list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+ continue;
+ }
+
gfs2_assert(sdp, bd->bd_ail == ai);
if (buffer_busy(bh)) {
@@ -227,7 +237,10 @@ static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
list_del(&bd->bd_ail_st_list);
list_del(&bd->bd_ail_gl_list);
atomic_dec(&bd->bd_gl->gl_ail_count);
- brelse(bd->bd_bh);
+ if (bd->bd_bh)
+ brelse(bd->bd_bh);
+ else
+ kmem_cache_free(gfs2_bufdata_cachep, bd);
}
}