X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_yaffs2.c;h=688211e1ae6a48e3ee9e0bc1bb93cc8067ff7c2c;hp=34c0bde985cb5d972624d31b9e905b5aa489511d;hb=bf0323aab4b4a577fcb2dafc573b443aabcedc02;hpb=1570788072c1154eff93282e0bb8564de40bd8aa diff --git a/yaffs_yaffs2.c b/yaffs_yaffs2.c index 34c0bde..688211e 100644 --- a/yaffs_yaffs2.c +++ b/yaffs_yaffs2.c @@ -365,20 +365,47 @@ static int yaffs2_rd_checkpt_dev(struct yaffs_dev *dev) return ok ? 1 : 0; } + +static void yaffs2_checkpt_obj_bit_assign(struct yaffs_checkpt_obj *cp, + int bit_offset, + int bit_width, + u32 value) +{ + u32 and_mask; + + and_mask = ((1<bit_field &= ~and_mask; + cp->bit_field |= ((value << bit_offset) & and_mask); +} + +static u32 yaffs2_checkpt_obj_bit_get(struct yaffs_checkpt_obj *cp, + int bit_offset, + int bit_width) +{ + u32 and_mask; + + and_mask = ((1<bit_field >> bit_offset) & and_mask; +} + static void yaffs2_obj_checkpt_obj(struct yaffs_checkpt_obj *cp, struct yaffs_obj *obj) { cp->obj_id = obj->obj_id; cp->parent_id = (obj->parent) ? obj->parent->obj_id : 0; cp->hdr_chunk = obj->hdr_chunk; - cp->variant_type = obj->variant_type; - cp->deleted = obj->deleted; - cp->soft_del = obj->soft_del; - cp->unlinked = obj->unlinked; - cp->fake = obj->fake; - cp->rename_allowed = obj->rename_allowed; - cp->unlink_allowed = obj->unlink_allowed; - cp->serial = obj->serial; + + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_VARIANT_BITS, obj->variant_type); + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_DELETED_BITS, obj->deleted); + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_SOFT_DEL_BITS, obj->soft_del); + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_UNLINKED_BITS, obj->unlinked); + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_FAKE_BITS, obj->fake); + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_RENAME_ALLOWED_BITS, obj->rename_allowed); + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_UNLINK_ALLOWED_BITS, obj->unlink_allowed); + yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_SERIAL_BITS, obj->serial); + cp->n_data_chunks = obj->n_data_chunks; if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) @@ -391,11 +418,12 @@ static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj, struct yaffs_checkpt_obj *cp) { struct yaffs_obj *parent; + u32 cp_variant_type = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_VARIANT_BITS); - if (obj->variant_type != cp->variant_type) { + if (obj->variant_type != cp_variant_type) { yaffs_trace(YAFFS_TRACE_ERROR, "Checkpoint read object %d type %d chunk %d does not match existing object type %d", - cp->obj_id, cp->variant_type, cp->hdr_chunk, + cp->obj_id, cp_variant_type, cp->hdr_chunk, obj->variant_type); return 0; } @@ -414,7 +442,7 @@ static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj, yaffs_trace(YAFFS_TRACE_ALWAYS, "Checkpoint read object %d parent %d type %d chunk %d Parent type, %d, not directory", cp->obj_id, cp->parent_id, - cp->variant_type, cp->hdr_chunk, + cp_variant_type, cp->hdr_chunk, parent->variant_type); return 0; } @@ -422,21 +450,24 @@ static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj, } obj->hdr_chunk = cp->hdr_chunk; - obj->variant_type = cp->variant_type; - obj->deleted = cp->deleted; - obj->soft_del = cp->soft_del; - obj->unlinked = cp->unlinked; - obj->fake = cp->fake; - obj->rename_allowed = cp->rename_allowed; - obj->unlink_allowed = cp->unlink_allowed; - obj->serial = cp->serial; + + obj->variant_type = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_VARIANT_BITS); + obj->deleted = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_DELETED_BITS); + obj->soft_del = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_SOFT_DEL_BITS); + obj->unlinked = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_UNLINKED_BITS); + obj->fake = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_FAKE_BITS); + obj->rename_allowed = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_RENAME_ALLOWED_BITS); + obj->unlink_allowed = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_UNLINK_ALLOWED_BITS); + obj->serial = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_SERIAL_BITS); + 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; @@ -545,6 +576,7 @@ static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev) int i; int ok = 1; struct list_head *lh; + u32 cp_variant_type; /* Iterate through the objects in each hash entry, * dumping them to the checkpointing stream. @@ -556,11 +588,12 @@ static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev) if (!obj->defered_free) { yaffs2_obj_checkpt_obj(&cp, obj); cp.struct_type = sizeof(cp); - + cp_variant_type = yaffs2_checkpt_obj_bit_get( + &cp, CHECKPOINT_VARIANT_BITS); yaffs_trace(YAFFS_TRACE_CHECKPOINT, "Checkpoint write object %d parent %d type %d chunk %d obj addr %p", cp.obj_id, cp.parent_id, - cp.variant_type, cp.hdr_chunk, obj); + cp_variant_type, cp.hdr_chunk, obj); ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)); @@ -589,6 +622,7 @@ static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev) struct yaffs_checkpt_obj cp; int ok = 1; int done = 0; + u32 cp_variant_type; LIST_HEAD(hard_list); @@ -601,9 +635,11 @@ static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev) ok = 0; } + cp_variant_type = yaffs2_checkpt_obj_bit_get( + &cp, CHECKPOINT_VARIANT_BITS); yaffs_trace(YAFFS_TRACE_CHECKPOINT, "Checkpoint read object %d parent %d type %d chunk %d ", - cp.obj_id, cp.parent_id, cp.variant_type, + cp.obj_id, cp.parent_id, cp_variant_type, cp.hdr_chunk); if (ok && cp.obj_id == ~0) { @@ -611,7 +647,7 @@ static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev) } else if (ok) { obj = yaffs_find_or_create_by_number(dev, cp.obj_id, - cp.variant_type); + cp_variant_type); if (obj) { ok = yaffs2_checkpt_obj_to_obj(obj, &cp); if (!ok) @@ -836,7 +872,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; @@ -873,7 +909,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); @@ -942,7 +978,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, 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; @@ -957,9 +993,13 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, result = yaffs_summary_fetch(dev, &tags, chunk_in_block); tags.seq_number = bi->seq_number; } - - if (!summary_available || tags.obj_id == 0) + + 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... */ @@ -1019,6 +1059,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) { @@ -1029,8 +1070,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; @@ -1063,9 +1104,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; } @@ -1152,9 +1193,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; @@ -1188,12 +1229,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 || @@ -1228,7 +1271,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 { @@ -1236,7 +1279,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; @@ -1292,7 +1335,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 @@ -1300,7 +1343,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) @@ -1344,7 +1387,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; @@ -1434,7 +1476,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(); @@ -1462,13 +1504,12 @@ 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, blk); + summary_available = yaffs_summary_read(dev, dev->sum_tags, blk); /* For each chunk in each block that needs scanning.... */ found_chunks = 0; - if(summary_available) + if (summary_available) c = dev->chunks_per_summary - 1; else c = dev->param.chunks_per_block - 1;