Add large file support changes to yaffs_vfs_single.c
[yaffs2.git] / yaffs_yaffs2.c
index f4a7a7f2066c7cc1b7c82593de9eb296c53200e8..aa32055989a42a14496d48b1647d0c921cea9f5f 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.
@@ -835,7 +836,7 @@ int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size)
         * of hole marker.
         */
        loff_t old_file_size;
-       int increase;
+       loff_t increase;
        int small_hole;
        int result = YAFFS_OK;
        struct yaffs_dev *dev = NULL;
@@ -872,7 +873,7 @@ int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size)
 
        if (local_buffer) {
                /* fill hole with zero bytes */
-               int pos = old_file_size;
+               loff_t pos = old_file_size;
                int this_write;
                int written;
                memset(local_buffer, 0, dev->data_bytes_per_chunk);
@@ -934,13 +935,14 @@ 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;
        struct yaffs_obj *parent;
        int equiv_id;
-       int file_size;
+       loff_t file_size;
        int is_shrink;
        int is_unlinked;
        struct yaffs_ext_tags tags;
@@ -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) {
@@ -1021,8 +1034,8 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                dev->n_free_chunks++;
        } else if (tags.chunk_id > 0) {
                /* chunk_id > 0 so it is a data chunk... */
-               unsigned int endpos;
-               u32 chunk_base = (tags.chunk_id - 1) *
+               loff_t endpos;
+               loff_t chunk_base = (tags.chunk_id - 1) *
                                        dev->data_bytes_per_chunk;
 
                *found_chunks = 1;
@@ -1144,9 +1157,9 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                                 (tags.extra_available &&
                                  tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
                                )) {
-                               u32 this_size = (oh) ?
-                                       oh->file_size :
-                                       tags.extra_length;
+                               loff_t this_size = (oh) ?
+                                       yaffs_oh_to_size(oh) :
+                                       tags.extra_file_size;
                                u32 parent_obj_id = (oh) ?
                                        oh->parent_obj_id :
                                        tags.extra_parent_id;
@@ -1220,7 +1233,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                                parent = yaffs_find_or_create_by_number(dev,
                                                oh->parent_obj_id,
                                                YAFFS_OBJECT_TYPE_DIRECTORY);
-                               file_size = oh->file_size;
+                               file_size = yaffs_oh_to_size(oh);
                                is_shrink = oh->is_shrink;
                                equiv_id = oh->equiv_id;
                        } else {
@@ -1228,7 +1241,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                                parent = yaffs_find_or_create_by_number(dev,
                                                tags.extra_parent_id,
                                                YAFFS_OBJECT_TYPE_DIRECTORY);
-                               file_size = tags.extra_length;
+                               file_size = tags.extra_file_size;
                                is_shrink = tags.extra_is_shrink;
                                equiv_id = tags.extra_equiv_id;
                                in->lazy_loaded = 1;
@@ -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...",
@@ -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;
                }