[JFFS2] Fix ACL vs. mode handling.
[safe/jmp/linux-2.6] / fs / jffs2 / summary.c
index a60bbce..2a77d3f 100644 (file)
@@ -1,20 +1,17 @@
 /*
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
- * Copyright (C) 2004  Ferenc Havasi <havasi@inf.u-szeged.hu>,
- *                     Zoltan Sogor <weth@inf.u-szeged.hu>,
- *                     Patrik Kluba <pajko@halom.u-szeged.hu>,
- *                     University of Szeged, Hungary
- *               2005  KaiGai Kohei <kaigai@ak.jp.nec.com>
+ * Copyright © 2004  Ferenc Havasi <havasi@inf.u-szeged.hu>,
+ *                  Zoltan Sogor <weth@inf.u-szeged.hu>,
+ *                  Patrik Kluba <pajko@halom.u-szeged.hu>,
+ *                  University of Szeged, Hungary
+ *            2006  KaiGai Kohei <kaigai@ak.jp.nec.com>
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $
- *
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/pagemap.h>
 
 int jffs2_sum_init(struct jffs2_sb_info *c)
 {
-       c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
+       c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
 
        if (!c->summary) {
                JFFS2_WARNING("Can't allocate memory for summary information!\n");
                return -ENOMEM;
        }
 
-       memset(c->summary, 0, sizeof(struct jffs2_summary));
-
        c->summary->sum_buf = vmalloc(c->sector_size);
 
        if (!c->summary->sum_buf) {
@@ -43,7 +38,7 @@ int jffs2_sum_init(struct jffs2_sb_info *c)
                return -ENOMEM;
        }
 
-       dbg_summary("returned succesfully\n");
+       dbg_summary("returned successfully\n");
 
        return 0;
 }
@@ -252,6 +247,11 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
        union jffs2_node_union *node;
        struct jffs2_eraseblock *jeb;
 
+       if (c->summary->sum_size == JFFS2_SUMMARY_NOSUM_SIZE) {
+               dbg_summary("Summary is disabled for this jeb! Skipping summary info!\n");
+               return 0;
+       }
+
        node = invecs[0].iov_base;
        jeb = &c->blocks[ofs / c->sector_size];
        ofs -= jeb->offset;
@@ -310,8 +310,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
 #ifdef CONFIG_JFFS2_FS_XATTR
                case JFFS2_NODETYPE_XATTR: {
                        struct jffs2_sum_xattr_mem *temp;
-                       if (je32_to_cpu(node->x.version) == 0xffffffff)
-                               return 0;
                        temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
                        if (!temp)
                                goto no_mem;
@@ -327,10 +325,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
                }
                case JFFS2_NODETYPE_XREF: {
                        struct jffs2_sum_xref_mem *temp;
-
-                       if (je32_to_cpu(node->r.ino) == 0xffffffff
-                           && je32_to_cpu(node->r.xid) == 0xffffffff)
-                               return 0;
                        temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
                        if (!temp)
                                goto no_mem;
@@ -399,6 +393,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
        for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
                dbg_summary("processing summary index %d\n", i);
 
+               cond_resched();
+
                /* Make sure there's a spare ref for dirty space */
                err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
                if (err)
@@ -413,7 +409,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
 
                                dbg_summary("Inode at 0x%08x-0x%08x\n",
                                            jeb->offset + je32_to_cpu(spi->offset),
-                                           jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen));
+                                           jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen));
 
                                ic = jffs2_scan_make_ino_cache(c, ino);
                                if (!ic) {
@@ -435,7 +431,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                struct jffs2_sum_dirent_flash *spd;
                                spd = sp;
 
-                               dbg_summary("Dirent at 0x%08x\n",
+                               dbg_summary("Dirent at 0x%08x-0x%08x\n",
                                            jeb->offset + je32_to_cpu(spd->offset),
                                            jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
 
@@ -453,7 +449,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                        return -ENOMEM;
                                }
 
-                               fd->raw = sum_link_node_ref(c, jeb,  je32_to_cpu(spd->offset) | REF_PRISTINE,
+                               fd->raw = sum_link_node_ref(c, jeb,  je32_to_cpu(spd->offset) | REF_UNCHECKED,
                                                            PAD(je32_to_cpu(spd->totlen)), ic);
 
                                fd->next = NULL;
@@ -483,22 +479,20 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
 
                                xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
                                                                je32_to_cpu(spx->version));
-                               if (IS_ERR(xd)) {
-                                       if (PTR_ERR(xd) == -EEXIST) {
-                                               /* a newer version of xd exists */
-                                               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
-                                                       return err;
-                                               sp += JFFS2_SUMMARY_XATTR_SIZE;
-                                               break;
-                                       }
-                                       JFFS2_NOTICE("allocation of xattr_datum failed\n");
+                               if (IS_ERR(xd))
                                        return PTR_ERR(xd);
+                               if (xd->version > je32_to_cpu(spx->version)) {
+                                       /* node is not the newest one */
+                                       struct jffs2_raw_node_ref *raw
+                                               = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
+                                                                   PAD(je32_to_cpu(spx->totlen)), NULL);
+                                       raw->next_in_ino = xd->node->next_in_ino;
+                                       xd->node->next_in_ino = raw;
+                               } else {
+                                       xd->version = je32_to_cpu(spx->version);
+                                       sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
+                                                         PAD(je32_to_cpu(spx->totlen)), (void *)xd);
                                }
-
-                               xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
-                                                            PAD(je32_to_cpu(spx->totlen)), NULL);
-                               /* FIXME */ xd->node->next_in_ino = (void *)xd;
-
                                *pseudo_random += je32_to_cpu(spx->xid);
                                sp += JFFS2_SUMMARY_XATTR_SIZE;
 
@@ -511,21 +505,19 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                spr = (struct jffs2_sum_xref_flash *)sp;
                                dbg_summary("xref at %#08x-%#08x\n",
                                            jeb->offset + je32_to_cpu(spr->offset),
-                                           jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref)));
+                                           jeb->offset + je32_to_cpu(spr->offset) + 
+                                           (uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
 
                                ref = jffs2_alloc_xattr_ref();
                                if (!ref) {
                                        JFFS2_NOTICE("allocation of xattr_datum failed\n");
                                        return -ENOMEM;
                                }
-                               ref->ino = 0xfffffffe;
-                               ref->xid = 0xfffffffd;
                                ref->next = c->xref_temp;
                                c->xref_temp = ref;
 
-                               ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
-                                                             PAD(sizeof(struct jffs2_raw_xref)), NULL);
-                               /* FIXME */ ref->node->next_in_ino = (void *)ref;
+                               sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
+                                                 PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
 
                                *pseudo_random += ref->node->flash_offset;
                                sp += JFFS2_SUMMARY_XREF_SIZE;
@@ -563,7 +555,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
        struct jffs2_unknown_node crcnode;
        int ret, ofs;
        uint32_t crc;
-       int err;
 
        ofs = c->sector_size - sumsize;
 
@@ -605,16 +596,20 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
 
                dbg_summary("Summary : CLEANMARKER node \n");
 
+               ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+               if (ret)
+                       return ret;
+
                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);
-                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
-                               return err;
+                       if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
+                               return ret;
                } else if (jeb->first_node) {
                        dbg_summary("CLEANMARKER node not first node in block "
                                        "(0x%08x)\n", jeb->offset);
-                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
-                               return err;
+                       if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
+                               return ret;
                } else {
                        jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
                                            je32_to_cpu(summary->cln_mkr), NULL);
@@ -787,10 +782,12 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
                JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
                              infosize, sum_ofs, ret, retlen);
 
-               /* Waste remaining space */
-               spin_lock(&c->erase_completion_lock);
-               jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
-               spin_unlock(&c->erase_completion_lock);
+               if (retlen) {
+                       /* Waste remaining space */
+                       spin_lock(&c->erase_completion_lock);
+                       jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
+                       spin_unlock(&c->erase_completion_lock);
+               }
 
                c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
 
@@ -836,6 +833,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
                jffs2_sum_disable_collecting(c->summary);
 
                JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
+               spin_lock(&c->erase_completion_lock);
                return 0;
        }