-
- mark_flash = 1;
-
- yaffs_init_tags(&tags);
-
- yaffs_rd_chunk_tags_nand(dev, old_chunk,
- buffer, &tags);
-
- object = yaffs_find_by_number(dev, tags.obj_id);
-
- yaffs_trace(YAFFS_TRACE_GC_DETAIL,
- "Collecting chunk in block %d, %d %d %d ",
- dev->gc_chunk, tags.obj_id,
- tags.chunk_id, tags.n_bytes);
-
- if (object && !yaffs_skip_verification(dev)) {
- if (tags.chunk_id == 0)
- matching_chunk =
- object->hdr_chunk;
- else if (object->soft_del)
- matching_chunk = old_chunk; /* Defeat the test */
- else
- matching_chunk =
- yaffs_find_chunk_in_file
- (object, tags.chunk_id,
- NULL);
-
- if (old_chunk != matching_chunk)
- yaffs_trace(YAFFS_TRACE_ERROR,
- "gc: page in gc mismatch: %d %d %d %d",
- old_chunk,
- matching_chunk,
- tags.obj_id,
- tags.chunk_id);
-
- }
-
- if (!object) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "page %d in gc has no object: %d %d %d ",
- old_chunk,
- tags.obj_id, tags.chunk_id,
- tags.n_bytes);
- }
-
- if (object &&
- object->deleted &&
- object->soft_del && tags.chunk_id != 0) {
- /* Data chunk in a soft deleted file, throw it away
- * It's a soft deleted data chunk,
- * No need to copy this, just forget about it and
- * fix up the object.
- */
-
- /* Free chunks already includes softdeleted chunks.
- * How ever this chunk is going to soon be really deleted
- * which will increment free chunks.
- * We have to decrement free chunks so this works out properly.
- */
- dev->n_free_chunks--;
- bi->soft_del_pages--;
-
- object->n_data_chunks--;
-
- if (object->n_data_chunks <= 0) {
- /* remeber to clean up the object */
- dev->gc_cleanup_list[dev->
- n_clean_ups]
- = tags.obj_id;
- dev->n_clean_ups++;
- }
- mark_flash = 0;
- } else if (0) {
- /* Todo object && object->deleted && object->n_data_chunks == 0 */
- /* Deleted object header with no data chunks.
- * Can be discarded and the file deleted.
- */
- object->hdr_chunk = 0;
- yaffs_free_tnode(object->my_dev,
- object->
- variant.file_variant.
- top);
- object->variant.file_variant.top = NULL;
- yaffs_generic_obj_del(object);
-
- } else if (object) {
- /* It's either a data chunk in a live file or
- * an ObjectHeader, so we're interested in it.
- * NB Need to keep the ObjectHeaders of deleted files
- * until the whole file has been deleted off
- */
- tags.serial_number++;
-
- dev->n_gc_copies++;
-
- if (tags.chunk_id == 0) {
- /* It is an object Id,
- * We need to nuke the shrinkheader flags first
- * Also need to clean up shadowing.
- * We no longer want the shrink_header flag since its work is done
- * and if it is left in place it will mess up scanning.
- */
-
- struct yaffs_obj_hdr *oh;
- oh = (struct yaffs_obj_hdr *)
- buffer;
-
- oh->is_shrink = 0;
- tags.extra_is_shrink = 0;
-
- oh->shadows_obj = 0;
- oh->inband_shadowed_obj_id = 0;
- tags.extra_shadows = 0;
-
- /* Update file size */
- if (object->variant_type ==
- YAFFS_OBJECT_TYPE_FILE) {
- oh->file_size =
- object->variant.
- file_variant.
- file_size;
- tags.extra_length =
- oh->file_size;
- }
-
- yaffs_verify_oh(object, oh,
- &tags, 1);
- new_chunk =
- yaffs_write_new_chunk(dev,
- (u8 *)
- oh,
- &tags,
- 1);
- } else {
- new_chunk =
- yaffs_write_new_chunk(dev,
- buffer,
- &tags,
- 1);
- }
-
- if (new_chunk < 0) {
- ret_val = YAFFS_FAIL;
- } else {
-
- /* Ok, now fix up the Tnodes etc. */
-
- if (tags.chunk_id == 0) {
- /* It's a header */
- object->hdr_chunk =
- new_chunk;
- object->serial =
- tags.serial_number;
- } else {
- /* It's a data chunk */
- int ok;
- ok = yaffs_put_chunk_in_file(object, tags.chunk_id, new_chunk, 0);
- }
- }
- }
-
- if (ret_val == YAFFS_OK)
- yaffs_chunk_del(dev, old_chunk,
- mark_flash, __LINE__);
-