From: Bob Peterson <rpete...@redhat.com>

Before this patch, if an error was encountered while marking the
data blocks, the blocks would be removed from the linked list.
Now that we've got "undo" functions, we need to be able to undo
the designations of those blocks, which means we need to keep those
buffers on the linked list so they're found later. If we don't,
the undo data block function won't process them, and therefore they'll
be marked as "data" blocks in the bitmap, but no files will reference
the blocks (because the error causes the inode to be deleted).
With this patch, the metadata that points to the faulty data is kept
on the linked list, and after the error is found, the undo function
will therefore find it and mark its blocks as "free".

rhbz#902920
---
 gfs2/fsck/metawalk.c | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 4e18a7b..3aa1398 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1383,7 +1383,7 @@ static int hdr_size(struct gfs2_buffer_head *bh, int 
height)
 int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
 {
        osi_list_t metalist[GFS2_MAX_META_HEIGHT];
-       osi_list_t *list;
+       osi_list_t *list, *tmp;
        struct gfs2_buffer_head *bh;
        uint32_t height = ip->i_di.di_height;
        int  i, head_size;
@@ -1423,23 +1423,16 @@ int check_metatree(struct gfs2_inode *ip, struct 
metawalk_fxns *pass)
        if (ip->i_di.di_blocks > COMFORTABLE_BLKS)
                last_reported_fblock = -10000000;
 
-       while (error >= 0 && !osi_list_empty(list)) {
+       for (tmp = list->next; error >= 0 && tmp != list; tmp = tmp->next) {
                if (fsck_abort) {
                        free_metalist(ip, &metalist[0]);
                        return 0;
                }
-               bh = osi_list_entry(list->next, struct gfs2_buffer_head,
-                                   b_altlist);
-
+               bh = osi_list_entry(tmp, struct gfs2_buffer_head, b_altlist);
                head_size = hdr_size(bh, height);
-               if (!head_size) {
-                       if (bh == ip->i_bh)
-                               osi_list_del(&bh->b_altlist);
-                       else
-                               brelse(bh);
+               if (!head_size)
                        continue;
-               }
-
+               
                if (pass->check_data)
                        rc = check_data(ip, pass, bh, head_size,
                                        &blks_checked);
-- 
1.7.11.7

Reply via email to