]> err.no Git - linux-2.6/blobdiff - fs/jffs2/summary.c
[JFFS2] Correct handling of JFFS2_FEATURE_RWCOMPAT_COPY nodes.
[linux-2.6] / fs / jffs2 / summary.c
index 439b9f6d5837428410f003da55b71be279f9e08a..53a84b468cfe223a38f669a1e4168d600ecc43ed 100644 (file)
@@ -399,7 +399,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                raw = jffs2_alloc_raw_node_ref();
                                if (!raw) {
                                        JFFS2_NOTICE("allocation of node reference failed\n");
-                                       kfree(summary);
                                        return -ENOMEM;
                                }
 
@@ -407,24 +406,17 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                if (!ic) {
                                        JFFS2_NOTICE("scan_make_ino_cache failed\n");
                                        jffs2_free_raw_node_ref(raw);
-                                       kfree(summary);
                                        return -ENOMEM;
                                }
 
                                raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED;
-                               raw->__totlen = PAD(je32_to_cpu(spi->totlen));
-                               raw->next_phys = NULL;
-                               raw->next_in_ino = ic->nodes;
 
+                               raw->next_in_ino = ic->nodes;
                                ic->nodes = raw;
-                               if (!jeb->first_node)
-                                       jeb->first_node = raw;
-                               if (jeb->last_node)
-                                       jeb->last_node->next_phys = raw;
-                               jeb->last_node = raw;
-                               *pseudo_random += je32_to_cpu(spi->version);
 
-                               UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen)));
+                               jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)));
+
+                               *pseudo_random += je32_to_cpu(spi->version);
 
                                sp += JFFS2_SUMMARY_INODE_SIZE;
 
@@ -439,10 +431,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                                        jeb->offset + je32_to_cpu(spd->offset));
 
                                fd = jffs2_alloc_full_dirent(spd->nsize+1);
-                               if (!fd) {
-                                       kfree(summary);
+                               if (!fd)
                                        return -ENOMEM;
-                               }
 
                                memcpy(&fd->name, spd->name, spd->nsize);
                                fd->name[spd->nsize] = 0;
@@ -451,7 +441,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                if (!raw) {
                                        jffs2_free_full_dirent(fd);
                                        JFFS2_NOTICE("allocation of node reference failed\n");
-                                       kfree(summary);
                                        return -ENOMEM;
                                }
 
@@ -459,20 +448,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                if (!ic) {
                                        jffs2_free_full_dirent(fd);
                                        jffs2_free_raw_node_ref(raw);
-                                       kfree(summary);
                                        return -ENOMEM;
                                }
 
-                               raw->__totlen = PAD(je32_to_cpu(spd->totlen));
                                raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE;
-                               raw->next_phys = NULL;
                                raw->next_in_ino = ic->nodes;
                                ic->nodes = raw;
-                               if (!jeb->first_node)
-                                       jeb->first_node = raw;
-                               if (jeb->last_node)
-                                       jeb->last_node->next_phys = raw;
-                               jeb->last_node = raw;
+
+                               jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)));
 
                                fd->raw = raw;
                                fd->next = NULL;
@@ -480,7 +463,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                fd->ino = je32_to_cpu(spd->ino);
                                fd->nhash = full_name_hash(fd->name, spd->nsize);
                                fd->type = spd->type;
-                               USED_SPACE(PAD(je32_to_cpu(spd->totlen)));
+
                                jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
                                *pseudo_random += je32_to_cpu(spd->version);
@@ -522,17 +505,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                xd->node = raw;
 
                                raw->flash_offset = ofs | REF_UNCHECKED;
-                               raw->__totlen = PAD(je32_to_cpu(spx->totlen));
-                               raw->next_phys = NULL;
                                raw->next_in_ino = (void *)xd;
-                               if (!jeb->first_node)
-                                       jeb->first_node = raw;
-                               if (jeb->last_node)
-                                       jeb->last_node->next_phys = raw;
-                               jeb->last_node = raw;
+
+                               jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)));
 
                                *pseudo_random += je32_to_cpu(spx->xid);
-                               UNCHECKED_SPACE(je32_to_cpu(spx->totlen));
                                sp += JFFS2_SUMMARY_XATTR_SIZE;
 
                                break;
@@ -565,17 +542,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                ref->next = c->xref_temp;
                                c->xref_temp = ref;
 
-                               raw->__totlen = PAD(sizeof(struct jffs2_raw_xref));
                                raw->flash_offset = ofs | REF_UNCHECKED;
-                               raw->next_phys = NULL;
                                raw->next_in_ino = (void *)ref;
-                               if (!jeb->first_node)
-                                       jeb->first_node = raw;
-                               if (jeb->last_node)
-                                       jeb->last_node->next_phys = raw;
-                               jeb->last_node = raw;
 
-                               UNCHECKED_SPACE(PAD(sizeof(struct jffs2_raw_xref)));
+                               jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)));
+
                                *pseudo_random += ofs;
                                sp += JFFS2_SUMMARY_XREF_SIZE;
 
@@ -585,45 +556,28 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                        default : {
 printk("nodetype = %#04x\n",je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype));
                                JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
-                               kfree(summary);
                                return -EIO;
                        }
                }
        }
 
-       kfree(summary);
        return 0;
 }
 
 /* Process the summary node - called from jffs2_scan_eraseblock() */
-
 int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-                               uint32_t ofs, uint32_t *pseudo_random)
+                          struct jffs2_raw_summary *summary, uint32_t sumsize,
+                          uint32_t *pseudo_random)
 {
        struct jffs2_unknown_node crcnode;
        struct jffs2_raw_node_ref *cache_ref;
-       struct jffs2_raw_summary *summary;
-       int ret, sumsize;
+       int ret, ofs;
        uint32_t crc;
 
-       sumsize = c->sector_size - ofs;
-       ofs += jeb->offset;
+       ofs = jeb->offset + c->sector_size - sumsize;
 
        dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
-                               jeb->offset, ofs, sumsize);
-
-       summary = kmalloc(sumsize, GFP_KERNEL);
-
-       if (!summary) {
-               return -ENOMEM;
-       }
-
-       ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
-
-       if (ret) {
-               kfree(summary);
-               return ret;
-       }
+                   jeb->offset, ofs, sumsize);
 
        /* OK, now check for node validity and CRC */
        crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -663,27 +617,23 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
                if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
                        dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
                                je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
-                       UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
+                       DIRTY_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
                } else if (jeb->first_node) {
                        dbg_summary("CLEANMARKER node not first node in block "
                                        "(0x%08x)\n", jeb->offset);
-                       UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
+                       DIRTY_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
                } else {
                        struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
 
                        if (!marker_ref) {
                                JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
-                               kfree(summary);
                                return -ENOMEM;
                        }
 
-                       marker_ref->next_in_ino = NULL;
-                       marker_ref->next_phys = NULL;
                        marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-                       marker_ref->__totlen = je32_to_cpu(summary->cln_mkr);
-                       jeb->first_node = jeb->last_node = marker_ref;
+                       marker_ref->next_in_ino = NULL;
 
-                       USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) );
+                       jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr));
                }
        }
 
@@ -706,15 +656,8 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
        cache_ref->next_in_ino = NULL;
        cache_ref->next_phys = NULL;
        cache_ref->flash_offset = ofs | REF_NORMAL;
-       cache_ref->__totlen = sumsize;
 
-       if (!jeb->first_node)
-               jeb->first_node = cache_ref;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = cache_ref;
-       jeb->last_node = cache_ref;
-
-       USED_SPACE(sumsize);
+       jffs2_link_node_ref(c, jeb, cache_ref, sumsize);
 
        jeb->wasted_size += jeb->free_size;
        c->wasted_size += jeb->free_size;
@@ -817,7 +760,14 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
                        }
 #endif
                        default : {
-                               BUG();  /* unknown node in summary information */
+                               if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
+                                   == JFFS2_FEATURE_RWCOMPAT_COPY) {
+                                       dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
+                                                   je16_to_cpu(temp->u.nodetype));
+                                       jffs2_sum_disable_collecting(c->summary);
+                               } else {
+                                       BUG();  /* unknown node in summary information */
+                               }
                        }
                }
 
@@ -857,7 +807,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
                        infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
 
                c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
-               WASTED_SPACE(infosize);
+               DIRTY_SPACE(infosize);
 
                return 1;
        }
@@ -912,17 +862,9 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
        }
 
        summary_ref->next_in_ino = NULL;
-       summary_ref->next_phys = NULL;
        summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
-       summary_ref->__totlen = infosize;
-
-       if (!jeb->first_node)
-               jeb->first_node = summary_ref;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = summary_ref;
-       jeb->last_node = summary_ref;
 
-       USED_SPACE(infosize);
+       jffs2_link_node_ref(c, jeb, summary_ref, infosize);
 
        return 0;
 }