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_width)-1) << bit_offset;
+
+ cp->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_width)-1);
+
+ return (cp->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)
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;
}
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;
}
}
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;
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.
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));
struct yaffs_checkpt_obj cp;
int ok = 1;
int done = 0;
+ u32 cp_variant_type;
LIST_HEAD(hard_list);
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) {
} 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)
* 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;
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);
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;
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... */
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) {
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;
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;
}
(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;
}
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 ||
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 {
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;
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
* 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)
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;
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();
/* 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;