yaffs: Discard partially written summary data
[yaffs2.git] / yaffs_yaffs2.c
index 6d3b5160855053aa0e01e31400be3c99edbeab8c..5761e960e646c816c0628a2c7b64470bb55c04f1 100644 (file)
@@ -20,6 +20,7 @@
 #include "yaffs_getblockinfo.h"
 #include "yaffs_verify.h"
 #include "yaffs_attribs.h"
+#include "yaffs_summary.h"
 
 /*
  * Checkpoints are really no benefit on very small partitions.
@@ -573,7 +574,7 @@ static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev)
        }
 
        /* Dump end of list */
-       memset(&cp, 0xFF, sizeof(struct yaffs_checkpt_obj));
+       memset(&cp, 0xff, sizeof(struct yaffs_checkpt_obj));
        cp.struct_type = sizeof(cp);
 
        if (ok)
@@ -868,7 +869,7 @@ int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size)
                small_hole = 0;
 
        if (small_hole)
-               local_buffer = yaffs_get_temp_buffer(dev, __LINE__);
+               local_buffer = yaffs_get_temp_buffer(dev);
 
        if (local_buffer) {
                /* fill hole with zero bytes */
@@ -893,7 +894,7 @@ int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size)
                        }
                }
 
-               yaffs_release_temp_buffer(dev, local_buffer, __LINE__);
+               yaffs_release_temp_buffer(dev, local_buffer);
 
                /* If out of space then reverse any chunks we've added */
                if (!small_increase_ok)
@@ -934,7 +935,8 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                int blk, int chunk_in_block,
                int *found_chunks,
                u8 *chunk_data,
-               struct list_head *hard_list)
+               struct list_head *hard_list,
+               int summary_available)
 {
        struct yaffs_obj_hdr *oh;
        struct yaffs_obj *in;
@@ -951,7 +953,17 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
        struct yaffs_hardlink_var *hl_var;
        struct yaffs_symlink_var *sl_var;
 
-       result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
+       if (summary_available) {
+               result = yaffs_summary_fetch(dev, &tags, chunk_in_block);
+               tags.seq_number = bi->seq_number;
+       }
+
+       if (!summary_available || tags.obj_id == 0) {
+               result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
+               dev->tags_used++;
+       } else {
+               dev->summary_used++;
+       }
 
        /* Let's have a good look at this chunk... */
 
@@ -1011,6 +1023,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                        dev->n_free_chunks++;
        } else if (tags.obj_id > YAFFS_MAX_OBJECT_ID ||
                   tags.chunk_id > YAFFS_MAX_CHUNK_ID ||
+                  tags.obj_id == YAFFS_OBJECTID_SUMMARY ||
                   (tags.chunk_id > 0 &&
                     tags.n_bytes > dev->data_bytes_per_chunk) ||
                   tags.seq_number != bi->seq_number) {
@@ -1346,6 +1359,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
        int alloc_failed = 0;
        struct yaffs_block_index *block_index = NULL;
        int alt_block_index = 0;
+       int summary_available;
 
        yaffs_trace(YAFFS_TRACE_SCAN,
                "yaffs2_scan_backwards starts  intstartblk %d intendblk %d...",
@@ -1371,7 +1385,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
 
        dev->blocks_in_checkpt = 0;
 
-       chunk_data = yaffs_get_temp_buffer(dev, __LINE__);
+       chunk_data = yaffs_get_temp_buffer(dev);
 
        /* Scan all the blocks to determine their state */
        bi = dev->block_info;
@@ -1455,18 +1469,27 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
                bi = yaffs_get_block_info(dev, blk);
                deleted = 0;
 
+               summary_available = yaffs_summary_read(dev, dev->sum_tags, blk);
+
                /* For each chunk in each block that needs scanning.... */
                found_chunks = 0;
-               for (c = dev->param.chunks_per_block - 1;
+               if(summary_available)
+                       c = dev->chunks_per_summary - 1;
+               else
+                       c = dev->param.chunks_per_block - 1;
+
+               for (/* c is already initialised */;
                     !alloc_failed && c >= 0 &&
                     (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
-                     bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
+                     bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING);
+                     c--) {
                        /* Scan backwards...
                         * Read the tags and decide what to do
                         */
                        if (yaffs2_scan_chunk(dev, bi, blk, c,
                                        &found_chunks, chunk_data,
-                                       &hard_list) == YAFFS_FAIL)
+                                       &hard_list, summary_available) ==
+                                       YAFFS_FAIL)
                                alloc_failed = 1;
                }
 
@@ -1498,7 +1521,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
         */
        yaffs_link_fixup(dev, &hard_list);
 
-       yaffs_release_temp_buffer(dev, chunk_data, __LINE__);
+       yaffs_release_temp_buffer(dev, chunk_data);
 
        if (alloc_failed)
                return YAFFS_FAIL;