Hello community,

here is the log from the commit of package ocfs2-tools for openSUSE:Factory 
checked in at 2012-09-27 10:26:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ocfs2-tools (Old)
 and      /work/SRC/openSUSE:Factory/.ocfs2-tools.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ocfs2-tools", Maintainer is "[email protected]"

Changes:
--------
--- /work/SRC/openSUSE:Factory/ocfs2-tools/ocfs2-tools.changes  2012-08-27 
16:31:49.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.ocfs2-tools.new/ocfs2-tools.changes     
2012-09-27 10:26:24.000000000 +0200
@@ -1,0 +2,6 @@
+Tue Sep 25 11:24:55 CDT 2012 - [email protected]
+
+- Fix infinite loop while checking for group desc chains
+  (bnc#781122)
+
+-------------------------------------------------------------------

New:
----
  0001-fswreck-Create-a-loop-in-group-chains.patch
  0002-Break-a-chain-loop-in-group-desc.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ocfs2-tools.spec ++++++
--- /var/tmp/diff_new_pack.qpZby7/_old  2012-09-27 10:26:26.000000000 +0200
+++ /var/tmp/diff_new_pack.qpZby7/_new  2012-09-27 10:26:26.000000000 +0200
@@ -52,6 +52,8 @@
 Patch205:       ocfs2-tools-kernel33.patch
 Patch206:       ocfs2-tools-resource.patch
 Patch207:       fix-indexed-dirs.patch
+Patch208:       0001-fswreck-Create-a-loop-in-group-chains.patch
+Patch209:       0002-Break-a-chain-loop-in-group-desc.patch
 Url:            http://oss.oracle.com/projects/ocfs2-tools/
 Requires:       /sbin/chkconfig
 Requires:       e2fsprogs
@@ -129,6 +131,8 @@
 %patch205 -p1
 %patch206 -p1
 %patch207 -p1
+%patch208 -p1
+%patch209 -p1
 
 %build
 export CFLAGS="${CFLAGS} ${RPM_OPT_FLAGS}"

++++++ 0001-fswreck-Create-a-loop-in-group-chains.patch ++++++
>From 57a0a528f35d2b540d4ed533b6274586056664ce Mon Sep 17 00:00:00 2001
From: Goldwyn Rodrigues <[email protected]>
Date: Thu, 20 Sep 2012 19:39:17 -0500
Subject: [PATCH 1/2] fswreck: Create a loop in group chains

---
 fswreck/corrupt.c           |    3 +++
 fswreck/group.c             |    6 ++++++
 fswreck/include/fsck_type.h |    1 +
 fswreck/main.c              |    2 ++
 4 files changed, 12 insertions(+)

Index: ocfs2-tools/fswreck/corrupt.c
===================================================================
--- ocfs2-tools.orig/fswreck/corrupt.c  2012-08-24 10:02:19.000000000 -0500
+++ ocfs2-tools/fswreck/corrupt.c       2012-09-25 11:12:35.000000000 -0500
@@ -331,6 +331,9 @@ void corrupt_group_desc(ocfs2_filesys *f
        case GROUP_FREE_BITS:
                func = mess_up_group_minor;
                break;
+       case GROUP_CHAIN_LOOP:
+               func = mess_up_group_minor;
+               break;
        case GROUP_GEN:
                func = mess_up_group_gen;
                break;
Index: ocfs2-tools/fswreck/group.c
===================================================================
--- ocfs2-tools.orig/fswreck/group.c    2012-08-24 10:02:19.000000000 -0500
+++ ocfs2-tools/fswreck/group.c 2012-09-25 11:12:35.000000000 -0500
@@ -176,6 +176,12 @@ static void damage_group_desc(ocfs2_file
                        bg->bg_chain, (bg->bg_chain + 10));
                bg->bg_chain += 10;
                break;
+       case GROUP_CHAIN_LOOP:
+               fprintf(stdout, "Corrput GROUP_LOOP: "
+                       "change group next from %"PRIu64" to %"PRIu64"\n",
+                       bg->bg_next_group, cr->c_blkno);
+               bg->bg_next_group = cpu_to_le64(cr->c_blkno);
+               break;
        case GROUP_FREE_BITS:
                fprintf(stdout, "Corrput GROUP_FREE_BITS: "
                        "change group free bits from %u to %u\n",
Index: ocfs2-tools/fswreck/include/fsck_type.h
===================================================================
--- ocfs2-tools.orig/fswreck/include/fsck_type.h        2012-08-24 
10:02:19.000000000 -0500
+++ ocfs2-tools/fswreck/include/fsck_type.h     2012-09-25 11:12:35.000000000 
-0500
@@ -57,6 +57,7 @@ enum fsck_type
        GROUP_BLKNO,
        GROUP_CHAIN,
        GROUP_FREE_BITS,
+       GROUP_CHAIN_LOOP,
        CHAIN_COUNT,
        CHAIN_NEXT_FREE,
        CHAIN_EMPTY,
Index: ocfs2-tools/fswreck/main.c
===================================================================
--- ocfs2-tools.orig/fswreck/main.c     2012-08-24 10:02:19.000000000 -0500
+++ ocfs2-tools/fswreck/main.c  2012-09-25 11:12:35.000000000 -0500
@@ -102,6 +102,8 @@ static struct prompt_code prompt_codes[N
                           "Corrupt chain group's blkno"),
        define_prompt_code(GROUP_CHAIN, corrupt_group_desc, "", 1,
                           "Corrupt chain group's chain where it was in"),
+       define_prompt_code(GROUP_CHAIN_LOOP, corrupt_group_desc, "", 1,
+                          "Corrupt group's chain to form a loop"),
        define_prompt_code(GROUP_FREE_BITS, corrupt_group_desc, "", 1,
                           "Corrupt chain group's free bits"),
        define_prompt_code(CHAIN_COUNT, corrupt_sys_file, "", 1,
++++++ 0002-Break-a-chain-loop-in-group-desc.patch ++++++
>From 16f191550058a768935cab2fe575c48e64eba334 Mon Sep 17 00:00:00 2001
From: Goldwyn Rodrigues <[email protected]>
Date: Thu, 20 Sep 2012 20:12:14 -0500
Subject: [PATCH 2/2] Break a chain loop in group desc

This patch detects and a loop by checking hops against the theoretical
limit of number of chains in a chain_rec. If a loop is found, it breaks
it by storing the block numbers and comparing with exiting block
numbers.
---
 fsck.ocfs2/fsck.ocfs2.checks.8.in |    9 ++++++
 fsck.ocfs2/pass0.c                |   61 ++++++++++++++++++++++++++++++++++---
 include/ocfs2-kernel/ocfs2_fs.h   |    2 +-
 3 files changed, 67 insertions(+), 5 deletions(-)

Index: ocfs2-tools/fsck.ocfs2/fsck.ocfs2.checks.8.in
===================================================================
--- ocfs2-tools.orig/fsck.ocfs2/fsck.ocfs2.checks.8.in  2012-09-25 
11:12:57.000000000 -0500
+++ ocfs2-tools/fsck.ocfs2/fsck.ocfs2.checks.8.in       2012-09-25 
11:13:03.000000000 -0500
@@ -202,6 +202,15 @@ valid in its bitmap.
 Answering yes decreases the number of recorded free bits so that it equals
 the total number of bits in the group descriptor's bitmap.
 
+.SS "GROUP_CHAIN_LOOP"
+A chain may loop if the next field of the group descriptor points to one of
+the previous group descriptors in the chain. This causes the ocfs2 code, both
+user space and kernel module to loop forever.
+
+Answering yes breaks the loop at an optimum location so that all the existing
+group descriptors are in the chain. However, it cannot re-connect stray group
+descriptors and must rely on the rest of the fsck code to fix it.
+
 .SS "CHAIN_COUNT"
 The chain list embedded in an inode is limited by the block size and the
 number of bytes consumed by the rest of the inode.  A chain list header was
Index: ocfs2-tools/fsck.ocfs2/pass0.c
===================================================================
--- ocfs2-tools.orig/fsck.ocfs2/pass0.c 2012-09-25 11:12:57.000000000 -0500
+++ ocfs2-tools/fsck.ocfs2/pass0.c      2012-09-25 11:13:03.000000000 -0500
@@ -666,6 +666,46 @@ out:
        return ret;
 }
 
+static errcode_t break_loop(o2fsck_state *ost, struct ocfs2_chain_rec *chain,
+               unsigned int max_depth)
+{
+       uint64_t *list;
+       int i;
+       unsigned int depth = 0;
+       uint64_t blkno = chain->c_blkno;
+       char *buf;
+       struct ocfs2_group_desc *gd;
+       errcode_t ret = ocfs2_malloc0(sizeof(uint64_t) * max_depth, &list);
+       if (ret)
+               goto out;
+       ret =  ocfs2_malloc_block(ost->ost_fs->fs_io, &buf);
+       if (ret)
+               goto out;
+       gd = (struct ocfs2_group_desc *)buf;
+
+       while (blkno && (depth<=max_depth)) {
+               list[depth++] = blkno;
+               ret = ocfs2_read_group_desc(ost->ost_fs, blkno, buf);
+               if (ret)
+                       goto out;
+               blkno = gd->bg_next_group;
+               for (i=0; i<depth; i++)
+                       if (list[i]==blkno) {
+                               gd->bg_next_group = 0;
+                               verbosef("Breaking gd loop %"PRIu64"\n", blkno);
+                               ret = ocfs2_write_group_desc(ost->ost_fs,
+                                               blkno, buf);
+                               goto out;
+                       }
+       }
+out:
+       if (list)
+               ocfs2_free(&list);
+       if (buf)
+               ocfs2_free(&buf);
+       return ret;
+}
+
 /* this takes a slightly ridiculous number of arguments :/ */
 static errcode_t check_chain(o2fsck_state *ost,
                             struct ocfs2_dinode *di,
@@ -675,7 +715,8 @@ static errcode_t check_chain(o2fsck_stat
                             char *buf2,
                             int *chain_changed,
                             ocfs2_bitmap *allowed,
-                            ocfs2_bitmap *forbidden)
+                            ocfs2_bitmap *forbidden,
+                            unsigned int max_depth)
 {
        struct ocfs2_group_desc *bg1 = (struct ocfs2_group_desc *)buf1;
        struct ocfs2_group_desc *bg2 = (struct ocfs2_group_desc *)buf2;
@@ -792,6 +833,14 @@ static errcode_t check_chain(o2fsck_stat
                /* the loop will now start by reading bg1->next_group */
                memcpy(buf1, buf2, ost->ost_fs->fs_blocksize);
                depth++;
+               if (depth > max_depth) {
+                        if (prompt(ost, PY, PR_GROUP_CHAIN_LOOP,
+                           "Loop detected in chain %d at block %"PRIu64
+                           ". Break the loop?",cs->cs_chain_no,
+                           (uint64_t) chain->c_blkno))
+                               ret = break_loop(ost, chain, max_depth);
+                       break;
+               }
        }
 
        /* we hit the premature end of a chain.. clear the last
@@ -854,6 +903,7 @@ static errcode_t verify_chain_alloc(o2fs
        int changed = 0, trust_next_free = 1;
        errcode_t ret = 0;
        uint64_t chain_bytes;
+       unsigned int num_gds, max_chain_len;
 
        if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
                   strlen(OCFS2_INODE_SIGNATURE))) {
@@ -883,9 +933,12 @@ static errcode_t verify_chain_alloc(o2fs
        /* XXX should we check suballoc_node? */
 
        cl = &di->id2.i_chain;
+       num_gds = (di->i_clusters + cl->cl_cpg)/cl->cl_cpg;
+       max_chain_len = (num_gds + cl->cl_count)/cl->cl_count;
 
-       verbosef("cl cpg %u bpc %u count %u next %u\n", 
-                cl->cl_cpg, cl->cl_bpc, cl->cl_count, cl->cl_next_free_rec);
+       verbosef("cl cpg %u bpc %u count %u next %u gds %u max_ch_len %u\n",
+                cl->cl_cpg, cl->cl_bpc, cl->cl_count, cl->cl_next_free_rec,
+                num_gds, max_chain_len);
 
        max_count = ocfs2_chain_recs_per_inode(ost->ost_fs->fs_blocksize);
 
@@ -948,7 +1001,7 @@ static errcode_t verify_chain_alloc(o2fs
                        .cs_cpg = cl->cl_cpg,
                };
                ret = check_chain(ost, di, &cs, cr, buf1, buf2, &changed,
-                                 allowed, forbidden);
+                                 allowed, forbidden, max_chain_len);
                /* XXX what?  not checking ret? */
 
                if (cr->c_blkno != 0) {
Index: ocfs2-tools/include/ocfs2-kernel/ocfs2_fs.h
===================================================================
--- ocfs2-tools.orig/include/ocfs2-kernel/ocfs2_fs.h    2012-09-25 
11:12:57.000000000 -0500
+++ ocfs2-tools/include/ocfs2-kernel/ocfs2_fs.h 2012-09-25 11:13:03.000000000 
-0500
@@ -1685,7 +1685,7 @@ static inline int ocfs2_sprintf_system_i
 }
 
 static inline void ocfs2_set_de_type(struct ocfs2_dir_entry *de,
-                                   umode_t mode)
+                                   unsigned short mode)
 {
        de->file_type = ocfs2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
 }
-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to