X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_yaffs2.c;h=f2f98a4c08770e8d3542de0f24a4f40fa6c51072;hp=6d3b5160855053aa0e01e31400be3c99edbeab8c;hb=33308768bd24abe4e1f59c5025a3dd824119ae1d;hpb=6648cbf52d6695755941ff8607fd7a0cda542e05 diff --git a/yaffs_yaffs2.c b/yaffs_yaffs2.c index 6d3b516..f2f98a4 100644 --- a/yaffs_yaffs2.c +++ b/yaffs_yaffs2.c @@ -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. @@ -431,11 +432,12 @@ static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj, obj->serial = cp->serial; obj->n_data_chunks = cp->n_data_chunks; - if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) + if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) { obj->variant.file_variant.file_size = cp->size_or_equiv_obj; - else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) + obj->variant.file_variant.stored_size = cp->size_or_equiv_obj; + } else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) { obj->variant.hardlink_variant.equiv_id = cp->size_or_equiv_obj; - + } if (obj->hdr_chunk > 0) obj->lazy_loaded = 1; return 1; @@ -573,7 +575,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) @@ -835,7 +837,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; @@ -868,11 +870,11 @@ 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 */ - 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); @@ -893,7 +895,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,13 +936,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 +954,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 +1024,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 +1035,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; @@ -1055,9 +1069,9 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, endpos = chunk_base + tags.n_bytes; if (!in->valid && - in->variant.file_variant.scanned_size < endpos) { + in->variant.file_variant.stored_size < endpos) { in->variant.file_variant. - scanned_size = endpos; + stored_size = endpos; in->variant.file_variant. file_size = endpos; } @@ -1144,9 +1158,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; @@ -1180,12 +1194,14 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, } if (!in->valid && in->variant_type != - (oh ? oh->type : tags.extra_obj_type)) + (oh ? oh->type : tags.extra_obj_type)) { yaffs_trace(YAFFS_TRACE_ERROR, - "yaffs tragedy: Bad object type, %d != %d, for object %d at chunk %d during scan", + "yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan", oh ? oh->type : tags.extra_obj_type, in->variant_type, tags.obj_id, chunk); + in = yaffs_retype_obj(in, oh ? oh->type : tags.extra_obj_type); + } if (!in->valid && (tags.obj_id == YAFFS_OBJECTID_ROOT || @@ -1220,7 +1236,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 +1244,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; @@ -1284,7 +1300,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, break; case YAFFS_OBJECT_TYPE_FILE: file_var = &in->variant.file_variant; - if (file_var->scanned_size < file_size) { + if (file_var->stored_size < file_size) { /* This covers the case where the file * size is greater than the data held. * This will happen if the file is @@ -1292,7 +1308,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, * current data extents. */ file_var->file_size = file_size; - file_var->scanned_size = file_size; + file_var->stored_size = file_size; } if (file_var->shrink_size > file_size) @@ -1336,7 +1352,6 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) int n_to_scan = 0; enum yaffs_block_state state; int c; - int deleted; LIST_HEAD(hard_list); struct yaffs_block_info *bi; u32 seq_number; @@ -1346,6 +1361,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 +1387,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; @@ -1425,7 +1441,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) bi++; } - yaffs_trace(YAFFS_TRACE_SCAN, "%d blocks to be sorted...", n_to_scan); + yaffs_trace(YAFFS_TRACE_ALWAYS, "%d blocks to be sorted...", n_to_scan); cond_resched(); @@ -1453,20 +1469,28 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) /* get the block to scan in the correct order */ blk = block_index[block_iter].block; 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 +1522,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;