Merge branches 'pm-core' and 'pm-sleep'
[linux-2.6-microblaze.git] / fs / ubifs / debug.c
index ebff43f..1bbb9fe 100644 (file)
@@ -291,9 +291,9 @@ void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
        kfree(pdent);
 }
 
-void ubifs_dump_node(const struct ubifs_info *c, const void *node)
+void ubifs_dump_node(const struct ubifs_info *c, const void *node, int node_len)
 {
-       int i, n;
+       int i, n, type, safe_len, max_node_len, min_node_len;
        union ubifs_key key;
        const struct ubifs_ch *ch = node;
        char key_buf[DBG_KEY_BUF_LEN];
@@ -306,10 +306,40 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
                return;
        }
 
+       /* Skip dumping unknown type node */
+       type = ch->node_type;
+       if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
+               pr_err("node type %d was not recognized\n", type);
+               return;
+       }
+
        spin_lock(&dbg_lock);
        dump_ch(node);
 
-       switch (ch->node_type) {
+       if (c->ranges[type].max_len == 0) {
+               max_node_len = min_node_len = c->ranges[type].len;
+       } else {
+               max_node_len = c->ranges[type].max_len;
+               min_node_len = c->ranges[type].min_len;
+       }
+       safe_len = le32_to_cpu(ch->len);
+       safe_len = safe_len > 0 ? safe_len : 0;
+       safe_len = min3(safe_len, max_node_len, node_len);
+       if (safe_len < min_node_len) {
+               pr_err("node len(%d) is too short for %s, left %d bytes:\n",
+                      safe_len, dbg_ntype(type),
+                      safe_len > UBIFS_CH_SZ ?
+                      safe_len - (int)UBIFS_CH_SZ : 0);
+               if (safe_len > UBIFS_CH_SZ)
+                       print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 32, 1,
+                                      (void *)node + UBIFS_CH_SZ,
+                                      safe_len - UBIFS_CH_SZ, 0);
+               goto out_unlock;
+       }
+       if (safe_len != le32_to_cpu(ch->len))
+               pr_err("\ttruncated node length      %d\n", safe_len);
+
+       switch (type) {
        case UBIFS_PAD_NODE:
        {
                const struct ubifs_pad_node *pad = node;
@@ -453,7 +483,8 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
                pr_err("\tnlen           %d\n", nlen);
                pr_err("\tname           ");
 
-               if (nlen > UBIFS_MAX_NLEN)
+               if (nlen > UBIFS_MAX_NLEN ||
+                   nlen > safe_len - UBIFS_DENT_NODE_SZ)
                        pr_err("(bad name length, not printing, bad or corrupted node)");
                else {
                        for (i = 0; i < nlen && dent->name[i]; i++)
@@ -467,7 +498,6 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
        case UBIFS_DATA_NODE:
        {
                const struct ubifs_data_node *dn = node;
-               int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
 
                key_read(c, &dn->key, &key);
                pr_err("\tkey            %s\n",
@@ -475,10 +505,13 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
                pr_err("\tsize           %u\n", le32_to_cpu(dn->size));
                pr_err("\tcompr_typ      %d\n",
                       (int)le16_to_cpu(dn->compr_type));
-               pr_err("\tdata size      %d\n", dlen);
-               pr_err("\tdata:\n");
+               pr_err("\tdata size      %u\n",
+                      le32_to_cpu(ch->len) - (unsigned int)UBIFS_DATA_NODE_SZ);
+               pr_err("\tdata (length = %d):\n",
+                      safe_len - (int)UBIFS_DATA_NODE_SZ);
                print_hex_dump(KERN_ERR, "\t", DUMP_PREFIX_OFFSET, 32, 1,
-                              (void *)&dn->data, dlen, 0);
+                              (void *)&dn->data,
+                              safe_len - (int)UBIFS_DATA_NODE_SZ, 0);
                break;
        }
        case UBIFS_TRUN_NODE:
@@ -495,13 +528,16 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
        case UBIFS_IDX_NODE:
        {
                const struct ubifs_idx_node *idx = node;
+               int max_child_cnt = (safe_len - UBIFS_IDX_NODE_SZ) /
+                                   (ubifs_idx_node_sz(c, 1) -
+                                   UBIFS_IDX_NODE_SZ);
 
-               n = le16_to_cpu(idx->child_cnt);
-               pr_err("\tchild_cnt      %d\n", n);
+               n = min_t(int, le16_to_cpu(idx->child_cnt), max_child_cnt);
+               pr_err("\tchild_cnt      %d\n", (int)le16_to_cpu(idx->child_cnt));
                pr_err("\tlevel          %d\n", (int)le16_to_cpu(idx->level));
                pr_err("\tBranches:\n");
 
-               for (i = 0; i < n && i < c->fanout - 1; i++) {
+               for (i = 0; i < n && i < c->fanout; i++) {
                        const struct ubifs_branch *br;
 
                        br = ubifs_idx_branch(c, idx, i);
@@ -525,7 +561,7 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
                                le64_to_cpu(orph->cmt_no) & LLONG_MAX);
                pr_err("\tlast node flag %llu\n",
                       (unsigned long long)(le64_to_cpu(orph->cmt_no)) >> 63);
-               n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3;
+               n = (safe_len - UBIFS_ORPH_NODE_SZ) >> 3;
                pr_err("\t%d orphan inode numbers:\n", n);
                for (i = 0; i < n; i++)
                        pr_err("\t  ino %llu\n",
@@ -537,9 +573,10 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
                break;
        }
        default:
-               pr_err("node type %d was not recognized\n",
-                      (int)ch->node_type);
+               pr_err("node type %d was not recognized\n", type);
        }
+
+out_unlock:
        spin_unlock(&dbg_lock);
 }
 
@@ -764,7 +801,7 @@ void ubifs_dump_lpt_info(struct ubifs_info *c)
        pr_err("\tnnode_sz:      %d\n", c->nnode_sz);
        pr_err("\tltab_sz:       %d\n", c->ltab_sz);
        pr_err("\tlsave_sz:      %d\n", c->lsave_sz);
-       pr_err("\tbig_lpt:       %d\n", c->big_lpt);
+       pr_err("\tbig_lpt:       %u\n", c->big_lpt);
        pr_err("\tlpt_hght:      %d\n", c->lpt_hght);
        pr_err("\tpnode_cnt:     %d\n", c->pnode_cnt);
        pr_err("\tnnode_cnt:     %d\n", c->nnode_cnt);
@@ -791,22 +828,6 @@ void ubifs_dump_lpt_info(struct ubifs_info *c)
        spin_unlock(&dbg_lock);
 }
 
-void ubifs_dump_sleb(const struct ubifs_info *c,
-                    const struct ubifs_scan_leb *sleb, int offs)
-{
-       struct ubifs_scan_node *snod;
-
-       pr_err("(pid %d) start dumping scanned data from LEB %d:%d\n",
-              current->pid, sleb->lnum, offs);
-
-       list_for_each_entry(snod, &sleb->nodes, list) {
-               cond_resched();
-               pr_err("Dumping node at LEB %d:%d len %d\n",
-                      sleb->lnum, snod->offs, snod->len);
-               ubifs_dump_node(c, snod->node);
-       }
-}
-
 void ubifs_dump_leb(const struct ubifs_info *c, int lnum)
 {
        struct ubifs_scan_leb *sleb;
@@ -834,7 +855,7 @@ void ubifs_dump_leb(const struct ubifs_info *c, int lnum)
                cond_resched();
                pr_err("Dumping node at LEB %d:%d len %d\n", lnum,
                       snod->offs, snod->len);
-               ubifs_dump_node(c, snod->node);
+               ubifs_dump_node(c, snod->node, c->leb_size - snod->offs);
        }
 
        pr_err("(pid %d) finish dumping LEB %d\n", current->pid, lnum);
@@ -1012,7 +1033,7 @@ void dbg_save_space_info(struct ubifs_info *c)
  *
  * This function compares current flash space information with the information
  * which was saved when the 'dbg_save_space_info()' function was called.
- * Returns zero if the information has not changed, and %-EINVAL it it has
+ * Returns zero if the information has not changed, and %-EINVAL if it has
  * changed.
  */
 int dbg_check_space_info(struct ubifs_info *c)
@@ -1212,7 +1233,7 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                ubifs_err(c, "but it should have key %s according to tnc",
                          dbg_snprintf_key(c, &zbr1->key, key_buf,
                                           DBG_KEY_BUF_LEN));
-               ubifs_dump_node(c, dent1);
+               ubifs_dump_node(c, dent1, UBIFS_MAX_DENT_NODE_SZ);
                goto out_free;
        }
 
@@ -1224,7 +1245,7 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                ubifs_err(c, "but it should have key %s according to tnc",
                          dbg_snprintf_key(c, &zbr2->key, key_buf,
                                           DBG_KEY_BUF_LEN));
-               ubifs_dump_node(c, dent2);
+               ubifs_dump_node(c, dent2, UBIFS_MAX_DENT_NODE_SZ);
                goto out_free;
        }
 
@@ -1243,9 +1264,9 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                          dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
 
        ubifs_msg(c, "first node at %d:%d\n", zbr1->lnum, zbr1->offs);
-       ubifs_dump_node(c, dent1);
+       ubifs_dump_node(c, dent1, UBIFS_MAX_DENT_NODE_SZ);
        ubifs_msg(c, "second node at %d:%d\n", zbr2->lnum, zbr2->offs);
-       ubifs_dump_node(c, dent2);
+       ubifs_dump_node(c, dent2, UBIFS_MAX_DENT_NODE_SZ);
 
 out_free:
        kfree(dent2);
@@ -2110,7 +2131,7 @@ out:
 
 out_dump:
        ubifs_msg(c, "dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
-       ubifs_dump_node(c, node);
+       ubifs_dump_node(c, node, zbr->len);
 out_free:
        kfree(node);
        return err;
@@ -2243,7 +2264,7 @@ out_dump:
 
        ubifs_msg(c, "dump of the inode %lu sitting in LEB %d:%d",
                  (unsigned long)fscki->inum, zbr->lnum, zbr->offs);
-       ubifs_dump_node(c, ino);
+       ubifs_dump_node(c, ino, zbr->len);
        kfree(ino);
        return -EINVAL;
 }
@@ -2314,12 +2335,12 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
 
                if (sa->type != UBIFS_DATA_NODE) {
                        ubifs_err(c, "bad node type %d", sa->type);
-                       ubifs_dump_node(c, sa->node);
+                       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
                        return -EINVAL;
                }
                if (sb->type != UBIFS_DATA_NODE) {
                        ubifs_err(c, "bad node type %d", sb->type);
-                       ubifs_dump_node(c, sb->node);
+                       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
                        return -EINVAL;
                }
 
@@ -2350,8 +2371,8 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
        return 0;
 
 error_dump:
-       ubifs_dump_node(c, sa->node);
-       ubifs_dump_node(c, sb->node);
+       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
+       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
        return -EINVAL;
 }
 
@@ -2382,13 +2403,13 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
                if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
                    sa->type != UBIFS_XENT_NODE) {
                        ubifs_err(c, "bad node type %d", sa->type);
-                       ubifs_dump_node(c, sa->node);
+                       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
                        return -EINVAL;
                }
                if (sb->type != UBIFS_INO_NODE && sb->type != UBIFS_DENT_NODE &&
                    sb->type != UBIFS_XENT_NODE) {
                        ubifs_err(c, "bad node type %d", sb->type);
-                       ubifs_dump_node(c, sb->node);
+                       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
                        return -EINVAL;
                }
 
@@ -2438,11 +2459,10 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
 
 error_dump:
        ubifs_msg(c, "dumping first node");
-       ubifs_dump_node(c, sa->node);
+       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
        ubifs_msg(c, "dumping second node");
-       ubifs_dump_node(c, sb->node);
+       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
        return -EINVAL;
-       return 0;
 }
 
 static inline int chance(unsigned int n, unsigned int out_of)