2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2011 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include "yaffs_guts.h"
15 #include "yaffs_trace.h"
16 #include "yaffs_yaffs2.h"
17 #include "yaffs_checkptrw.h"
18 #include "yaffs_bitmap.h"
19 #include "yaffs_nand.h"
20 #include "yaffs_getblockinfo.h"
21 #include "yaffs_verify.h"
22 #include "yaffs_attribs.h"
23 #include "yaffs_summary.h"
26 * Checkpoints are really no benefit on very small partitions.
28 * To save space on small partitions don't bother with checkpoints unless
29 * the partition is at least this big.
31 #define YAFFS_CHECKPOINT_MIN_BLOCKS 60
32 #define YAFFS_SMALL_HOLE_THRESHOLD 4
35 * Oldest Dirty Sequence Number handling.
38 /* yaffs_calc_oldest_dirty_seq()
39 * yaffs2_find_oldest_dirty_seq()
40 * Calculate the oldest dirty sequence number if we don't know it.
42 void yaffs_calc_oldest_dirty_seq(struct yaffs_dev
*dev
)
46 unsigned block_no
= 0;
47 struct yaffs_block_info
*b
;
49 if (!dev
->param
.is_yaffs2
)
52 /* Find the oldest dirty sequence number. */
53 seq
= dev
->seq_number
+ 1;
55 for (i
= dev
->internal_start_block
; i
<= dev
->internal_end_block
; i
++) {
56 if (b
->block_state
== YAFFS_BLOCK_STATE_FULL
&&
57 (b
->pages_in_use
- b
->soft_del_pages
) <
58 dev
->param
.chunks_per_block
&&
59 b
->seq_number
< seq
) {
67 dev
->oldest_dirty_seq
= seq
;
68 dev
->oldest_dirty_block
= block_no
;
72 void yaffs2_find_oldest_dirty_seq(struct yaffs_dev
*dev
)
74 if (!dev
->param
.is_yaffs2
)
77 if (!dev
->oldest_dirty_seq
)
78 yaffs_calc_oldest_dirty_seq(dev
);
82 * yaffs_clear_oldest_dirty_seq()
83 * Called when a block is erased or marked bad. (ie. when its seq_number
84 * becomes invalid). If the value matches the oldest then we clear
85 * dev->oldest_dirty_seq to force its recomputation.
87 void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev
*dev
,
88 struct yaffs_block_info
*bi
)
91 if (!dev
->param
.is_yaffs2
)
94 if (!bi
|| bi
->seq_number
== dev
->oldest_dirty_seq
) {
95 dev
->oldest_dirty_seq
= 0;
96 dev
->oldest_dirty_block
= 0;
101 * yaffs2_update_oldest_dirty_seq()
102 * Update the oldest dirty sequence number whenever we dirty a block.
103 * Only do this if the oldest_dirty_seq is actually being tracked.
105 void yaffs2_update_oldest_dirty_seq(struct yaffs_dev
*dev
, unsigned block_no
,
106 struct yaffs_block_info
*bi
)
108 if (!dev
->param
.is_yaffs2
)
111 if (dev
->oldest_dirty_seq
) {
112 if (dev
->oldest_dirty_seq
> bi
->seq_number
) {
113 dev
->oldest_dirty_seq
= bi
->seq_number
;
114 dev
->oldest_dirty_block
= block_no
;
119 int yaffs_block_ok_for_gc(struct yaffs_dev
*dev
, struct yaffs_block_info
*bi
)
122 if (!dev
->param
.is_yaffs2
)
123 return 1; /* disqualification only applies to yaffs2. */
125 if (!bi
->has_shrink_hdr
)
126 return 1; /* can gc */
128 yaffs2_find_oldest_dirty_seq(dev
);
130 /* Can't do gc of this block if there are any blocks older than this
131 * one that have discarded pages.
133 return (bi
->seq_number
<= dev
->oldest_dirty_seq
);
137 * yaffs2_find_refresh_block()
138 * periodically finds the oldest full block by sequence number for refreshing.
141 u32
yaffs2_find_refresh_block(struct yaffs_dev
*dev
)
146 struct yaffs_block_info
*bi
;
148 if (!dev
->param
.is_yaffs2
)
152 * If refresh period < 10 then refreshing is disabled.
154 if (dev
->param
.refresh_period
< 10)
160 if (dev
->refresh_skip
> dev
->param
.refresh_period
)
161 dev
->refresh_skip
= dev
->param
.refresh_period
;
163 if (dev
->refresh_skip
> 0)
167 * Refresh skip is now zero.
168 * We'll do a refresh this time around....
169 * Update the refresh skip and find the oldest block.
171 dev
->refresh_skip
= dev
->param
.refresh_period
;
172 dev
->refresh_count
++;
173 bi
= dev
->block_info
;
174 for (b
= dev
->internal_start_block
; b
<= dev
->internal_end_block
; b
++) {
176 if (bi
->block_state
== YAFFS_BLOCK_STATE_FULL
) {
178 if (oldest
< 1 || bi
->seq_number
< oldest_seq
) {
180 oldest_seq
= bi
->seq_number
;
187 yaffs_trace(YAFFS_TRACE_GC
,
188 "GC refresh count %d selected block %d with seq_number %d",
189 dev
->refresh_count
, oldest
, oldest_seq
);
195 int yaffs2_checkpt_required(struct yaffs_dev
*dev
)
199 if (!dev
->param
.is_yaffs2
)
202 nblocks
= dev
->internal_end_block
- dev
->internal_start_block
+ 1;
204 return !dev
->param
.skip_checkpt_wr
&&
205 !dev
->read_only
&& (nblocks
>= YAFFS_CHECKPOINT_MIN_BLOCKS
);
208 int yaffs_calc_checkpt_blocks_required(struct yaffs_dev
*dev
)
215 if (!dev
->param
.is_yaffs2
)
218 if (!dev
->checkpoint_blocks_required
&& yaffs2_checkpt_required(dev
)) {
219 /* Not a valid value so recalculate */
220 dev_blocks
= dev
->param
.end_block
- dev
->param
.start_block
+ 1;
221 n_bytes
+= sizeof(struct yaffs_checkpt_validity
);
222 n_bytes
+= sizeof(struct yaffs_checkpt_dev
);
223 n_bytes
+= dev_blocks
* sizeof(struct yaffs_block_info
);
224 n_bytes
+= dev_blocks
* dev
->chunk_bit_stride
;
226 (sizeof(struct yaffs_checkpt_obj
) + sizeof(u32
)) *
228 n_bytes
+= (dev
->tnode_size
+ sizeof(u32
)) * dev
->n_tnodes
;
229 n_bytes
+= sizeof(struct yaffs_checkpt_validity
);
230 n_bytes
+= sizeof(u32
); /* checksum */
232 /* Round up and add 2 blocks to allow for some bad blocks,
237 (dev
->data_bytes_per_chunk
*
238 dev
->param
.chunks_per_block
)) + 3;
240 dev
->checkpoint_blocks_required
= n_blocks
;
243 retval
= dev
->checkpoint_blocks_required
- dev
->blocks_in_checkpt
;
249 /*--------------------- Checkpointing --------------------*/
251 static int yaffs2_wr_checkpt_validity_marker(struct yaffs_dev
*dev
, int head
)
253 struct yaffs_checkpt_validity cp
;
255 memset(&cp
, 0, sizeof(cp
));
257 cp
.struct_type
= sizeof(cp
);
258 cp
.magic
= YAFFS_MAGIC
;
259 cp
.version
= YAFFS_CHECKPOINT_VERSION
;
260 cp
.head
= (head
) ? 1 : 0;
262 return (yaffs2_checkpt_wr(dev
, &cp
, sizeof(cp
)) == sizeof(cp
)) ? 1 : 0;
265 static int yaffs2_rd_checkpt_validity_marker(struct yaffs_dev
*dev
, int head
)
267 struct yaffs_checkpt_validity cp
;
270 ok
= (yaffs2_checkpt_rd(dev
, &cp
, sizeof(cp
)) == sizeof(cp
));
273 ok
= (cp
.struct_type
== sizeof(cp
)) &&
274 (cp
.magic
== YAFFS_MAGIC
) &&
275 (cp
.version
== YAFFS_CHECKPOINT_VERSION
) &&
276 (cp
.head
== ((head
) ? 1 : 0));
280 static void yaffs2_dev_to_checkpt_dev(struct yaffs_checkpt_dev
*cp
,
281 struct yaffs_dev
*dev
)
283 cp
->n_erased_blocks
= dev
->n_erased_blocks
;
284 cp
->alloc_block
= dev
->alloc_block
;
285 cp
->alloc_page
= dev
->alloc_page
;
286 cp
->n_free_chunks
= dev
->n_free_chunks
;
288 cp
->n_deleted_files
= dev
->n_deleted_files
;
289 cp
->n_unlinked_files
= dev
->n_unlinked_files
;
290 cp
->n_bg_deletions
= dev
->n_bg_deletions
;
291 cp
->seq_number
= dev
->seq_number
;
295 static void yaffs_checkpt_dev_to_dev(struct yaffs_dev
*dev
,
296 struct yaffs_checkpt_dev
*cp
)
298 dev
->n_erased_blocks
= cp
->n_erased_blocks
;
299 dev
->alloc_block
= cp
->alloc_block
;
300 dev
->alloc_page
= cp
->alloc_page
;
301 dev
->n_free_chunks
= cp
->n_free_chunks
;
303 dev
->n_deleted_files
= cp
->n_deleted_files
;
304 dev
->n_unlinked_files
= cp
->n_unlinked_files
;
305 dev
->n_bg_deletions
= cp
->n_bg_deletions
;
306 dev
->seq_number
= cp
->seq_number
;
309 static int yaffs2_wr_checkpt_dev(struct yaffs_dev
*dev
)
311 struct yaffs_checkpt_dev cp
;
313 u32 n_blocks
= dev
->internal_end_block
- dev
->internal_start_block
+ 1;
316 /* Write device runtime values */
317 yaffs2_dev_to_checkpt_dev(&cp
, dev
);
318 cp
.struct_type
= sizeof(cp
);
320 ok
= (yaffs2_checkpt_wr(dev
, &cp
, sizeof(cp
)) == sizeof(cp
));
324 /* Write block info */
325 n_bytes
= n_blocks
* sizeof(struct yaffs_block_info
);
326 ok
= (yaffs2_checkpt_wr(dev
, dev
->block_info
, n_bytes
) == n_bytes
);
330 /* Write chunk bits */
331 n_bytes
= n_blocks
* dev
->chunk_bit_stride
;
332 ok
= (yaffs2_checkpt_wr(dev
, dev
->chunk_bits
, n_bytes
) == n_bytes
);
337 static int yaffs2_rd_checkpt_dev(struct yaffs_dev
*dev
)
339 struct yaffs_checkpt_dev cp
;
342 (dev
->internal_end_block
- dev
->internal_start_block
+ 1);
345 ok
= (yaffs2_checkpt_rd(dev
, &cp
, sizeof(cp
)) == sizeof(cp
));
349 if (cp
.struct_type
!= sizeof(cp
))
352 yaffs_checkpt_dev_to_dev(dev
, &cp
);
354 n_bytes
= n_blocks
* sizeof(struct yaffs_block_info
);
356 ok
= (yaffs2_checkpt_rd(dev
, dev
->block_info
, n_bytes
) == n_bytes
);
361 n_bytes
= n_blocks
* dev
->chunk_bit_stride
;
363 ok
= (yaffs2_checkpt_rd(dev
, dev
->chunk_bits
, n_bytes
) == n_bytes
);
368 static void yaffs2_obj_checkpt_obj(struct yaffs_checkpt_obj
*cp
,
369 struct yaffs_obj
*obj
)
371 cp
->obj_id
= obj
->obj_id
;
372 cp
->parent_id
= (obj
->parent
) ? obj
->parent
->obj_id
: 0;
373 cp
->hdr_chunk
= obj
->hdr_chunk
;
374 cp
->variant_type
= obj
->variant_type
;
375 cp
->deleted
= obj
->deleted
;
376 cp
->soft_del
= obj
->soft_del
;
377 cp
->unlinked
= obj
->unlinked
;
378 cp
->fake
= obj
->fake
;
379 cp
->rename_allowed
= obj
->rename_allowed
;
380 cp
->unlink_allowed
= obj
->unlink_allowed
;
381 cp
->serial
= obj
->serial
;
382 cp
->n_data_chunks
= obj
->n_data_chunks
;
384 if (obj
->variant_type
== YAFFS_OBJECT_TYPE_FILE
)
385 cp
->size_or_equiv_obj
= obj
->variant
.file_variant
.file_size
;
386 else if (obj
->variant_type
== YAFFS_OBJECT_TYPE_HARDLINK
)
387 cp
->size_or_equiv_obj
= obj
->variant
.hardlink_variant
.equiv_id
;
390 static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj
*obj
,
391 struct yaffs_checkpt_obj
*cp
)
393 struct yaffs_obj
*parent
;
395 if (obj
->variant_type
!= cp
->variant_type
) {
396 yaffs_trace(YAFFS_TRACE_ERROR
,
397 "Checkpoint read object %d type %d chunk %d does not match existing object type %d",
398 cp
->obj_id
, cp
->variant_type
, cp
->hdr_chunk
,
403 obj
->obj_id
= cp
->obj_id
;
406 parent
= yaffs_find_or_create_by_number(obj
->my_dev
,
408 YAFFS_OBJECT_TYPE_DIRECTORY
);
413 if (parent
->variant_type
!= YAFFS_OBJECT_TYPE_DIRECTORY
) {
414 yaffs_trace(YAFFS_TRACE_ALWAYS
,
415 "Checkpoint read object %d parent %d type %d chunk %d Parent type, %d, not directory",
416 cp
->obj_id
, cp
->parent_id
,
417 cp
->variant_type
, cp
->hdr_chunk
,
418 parent
->variant_type
);
421 yaffs_add_obj_to_dir(parent
, obj
);
424 obj
->hdr_chunk
= cp
->hdr_chunk
;
425 obj
->variant_type
= cp
->variant_type
;
426 obj
->deleted
= cp
->deleted
;
427 obj
->soft_del
= cp
->soft_del
;
428 obj
->unlinked
= cp
->unlinked
;
429 obj
->fake
= cp
->fake
;
430 obj
->rename_allowed
= cp
->rename_allowed
;
431 obj
->unlink_allowed
= cp
->unlink_allowed
;
432 obj
->serial
= cp
->serial
;
433 obj
->n_data_chunks
= cp
->n_data_chunks
;
435 if (obj
->variant_type
== YAFFS_OBJECT_TYPE_FILE
)
436 obj
->variant
.file_variant
.file_size
= cp
->size_or_equiv_obj
;
437 else if (obj
->variant_type
== YAFFS_OBJECT_TYPE_HARDLINK
)
438 obj
->variant
.hardlink_variant
.equiv_id
= cp
->size_or_equiv_obj
;
440 if (obj
->hdr_chunk
> 0)
441 obj
->lazy_loaded
= 1;
445 static int yaffs2_checkpt_tnode_worker(struct yaffs_obj
*in
,
446 struct yaffs_tnode
*tn
, u32 level
,
450 struct yaffs_dev
*dev
= in
->my_dev
;
458 for (i
= 0; i
< YAFFS_NTNODES_INTERNAL
&& ok
; i
++) {
459 if (!tn
->internal
[i
])
461 ok
= yaffs2_checkpt_tnode_worker(in
,
465 YAFFS_TNODES_INTERNAL_BITS
) + i
);
471 base_offset
= chunk_offset
<< YAFFS_TNODES_LEVEL0_BITS
;
472 ok
= (yaffs2_checkpt_wr(dev
, &base_offset
, sizeof(base_offset
)) ==
473 sizeof(base_offset
));
475 ok
= (yaffs2_checkpt_wr(dev
, tn
, dev
->tnode_size
) ==
481 static int yaffs2_wr_checkpt_tnodes(struct yaffs_obj
*obj
)
486 if (obj
->variant_type
!= YAFFS_OBJECT_TYPE_FILE
)
489 ok
= yaffs2_checkpt_tnode_worker(obj
,
490 obj
->variant
.file_variant
.top
,
491 obj
->variant
.file_variant
.
494 ok
= (yaffs2_checkpt_wr(obj
->my_dev
, &end_marker
,
495 sizeof(end_marker
)) == sizeof(end_marker
));
500 static int yaffs2_rd_checkpt_tnodes(struct yaffs_obj
*obj
)
504 struct yaffs_dev
*dev
= obj
->my_dev
;
505 struct yaffs_file_var
*file_stuct_ptr
= &obj
->variant
.file_variant
;
506 struct yaffs_tnode
*tn
;
509 ok
= (yaffs2_checkpt_rd(dev
, &base_chunk
, sizeof(base_chunk
)) ==
512 while (ok
&& (~base_chunk
)) {
514 /* Read level 0 tnode */
516 tn
= yaffs_get_tnode(dev
);
518 ok
= (yaffs2_checkpt_rd(dev
, tn
, dev
->tnode_size
) ==
524 ok
= yaffs_add_find_tnode_0(dev
,
526 base_chunk
, tn
) ? 1 : 0;
529 ok
= (yaffs2_checkpt_rd
531 sizeof(base_chunk
)) == sizeof(base_chunk
));
534 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
535 "Checkpoint read tnodes %d records, last %d. ok %d",
536 nread
, base_chunk
, ok
);
541 static int yaffs2_wr_checkpt_objs(struct yaffs_dev
*dev
)
543 struct yaffs_obj
*obj
;
544 struct yaffs_checkpt_obj cp
;
547 struct list_head
*lh
;
549 /* Iterate through the objects in each hash entry,
550 * dumping them to the checkpointing stream.
553 for (i
= 0; ok
&& i
< YAFFS_NOBJECT_BUCKETS
; i
++) {
554 list_for_each(lh
, &dev
->obj_bucket
[i
].list
) {
555 obj
= list_entry(lh
, struct yaffs_obj
, hash_link
);
556 if (!obj
->defered_free
) {
557 yaffs2_obj_checkpt_obj(&cp
, obj
);
558 cp
.struct_type
= sizeof(cp
);
560 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
561 "Checkpoint write object %d parent %d type %d chunk %d obj addr %p",
562 cp
.obj_id
, cp
.parent_id
,
563 cp
.variant_type
, cp
.hdr_chunk
, obj
);
565 ok
= (yaffs2_checkpt_wr(dev
, &cp
,
566 sizeof(cp
)) == sizeof(cp
));
570 YAFFS_OBJECT_TYPE_FILE
)
571 ok
= yaffs2_wr_checkpt_tnodes(obj
);
576 /* Dump end of list */
577 memset(&cp
, 0xff, sizeof(struct yaffs_checkpt_obj
));
578 cp
.struct_type
= sizeof(cp
);
581 ok
= (yaffs2_checkpt_wr(dev
, &cp
, sizeof(cp
)) == sizeof(cp
));
586 static int yaffs2_rd_checkpt_objs(struct yaffs_dev
*dev
)
588 struct yaffs_obj
*obj
;
589 struct yaffs_checkpt_obj cp
;
592 LIST_HEAD(hard_list
);
595 while (ok
&& !done
) {
596 ok
= (yaffs2_checkpt_rd(dev
, &cp
, sizeof(cp
)) == sizeof(cp
));
597 if (cp
.struct_type
!= sizeof(cp
)) {
598 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
599 "struct size %d instead of %d ok %d",
600 cp
.struct_type
, (int)sizeof(cp
), ok
);
604 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
605 "Checkpoint read object %d parent %d type %d chunk %d ",
606 cp
.obj_id
, cp
.parent_id
, cp
.variant_type
,
609 if (ok
&& cp
.obj_id
== ~0) {
613 yaffs_find_or_create_by_number(dev
, cp
.obj_id
,
616 ok
= yaffs2_checkpt_obj_to_obj(obj
, &cp
);
619 if (obj
->variant_type
==
620 YAFFS_OBJECT_TYPE_FILE
) {
621 ok
= yaffs2_rd_checkpt_tnodes(obj
);
622 } else if (obj
->variant_type
==
623 YAFFS_OBJECT_TYPE_HARDLINK
) {
624 list_add(&obj
->hard_links
, &hard_list
);
633 yaffs_link_fixup(dev
, &hard_list
);
638 static int yaffs2_wr_checkpt_sum(struct yaffs_dev
*dev
)
643 yaffs2_get_checkpt_sum(dev
, &checkpt_sum
);
645 ok
= (yaffs2_checkpt_wr(dev
, &checkpt_sum
, sizeof(checkpt_sum
)) ==
646 sizeof(checkpt_sum
));
654 static int yaffs2_rd_checkpt_sum(struct yaffs_dev
*dev
)
660 yaffs2_get_checkpt_sum(dev
, &checkpt_sum0
);
662 ok
= (yaffs2_checkpt_rd(dev
, &checkpt_sum1
, sizeof(checkpt_sum1
)) ==
663 sizeof(checkpt_sum1
));
668 if (checkpt_sum0
!= checkpt_sum1
)
674 static int yaffs2_wr_checkpt_data(struct yaffs_dev
*dev
)
678 if (!yaffs2_checkpt_required(dev
)) {
679 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
680 "skipping checkpoint write");
685 ok
= yaffs2_checkpt_open(dev
, 1);
688 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
689 "write checkpoint validity");
690 ok
= yaffs2_wr_checkpt_validity_marker(dev
, 1);
693 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
694 "write checkpoint device");
695 ok
= yaffs2_wr_checkpt_dev(dev
);
698 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
699 "write checkpoint objects");
700 ok
= yaffs2_wr_checkpt_objs(dev
);
703 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
704 "write checkpoint validity");
705 ok
= yaffs2_wr_checkpt_validity_marker(dev
, 0);
709 ok
= yaffs2_wr_checkpt_sum(dev
);
711 if (!yaffs_checkpt_close(dev
))
715 dev
->is_checkpointed
= 1;
717 dev
->is_checkpointed
= 0;
719 return dev
->is_checkpointed
;
722 static int yaffs2_rd_checkpt_data(struct yaffs_dev
*dev
)
726 if (!dev
->param
.is_yaffs2
)
729 if (ok
&& dev
->param
.skip_checkpt_rd
) {
730 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
731 "skipping checkpoint read");
736 ok
= yaffs2_checkpt_open(dev
, 0); /* open for read */
739 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
740 "read checkpoint validity");
741 ok
= yaffs2_rd_checkpt_validity_marker(dev
, 1);
744 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
745 "read checkpoint device");
746 ok
= yaffs2_rd_checkpt_dev(dev
);
749 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
750 "read checkpoint objects");
751 ok
= yaffs2_rd_checkpt_objs(dev
);
754 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
755 "read checkpoint validity");
756 ok
= yaffs2_rd_checkpt_validity_marker(dev
, 0);
760 ok
= yaffs2_rd_checkpt_sum(dev
);
761 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
762 "read checkpoint checksum %d", ok
);
765 if (!yaffs_checkpt_close(dev
))
769 dev
->is_checkpointed
= 1;
771 dev
->is_checkpointed
= 0;
776 void yaffs2_checkpt_invalidate(struct yaffs_dev
*dev
)
778 if (dev
->is_checkpointed
|| dev
->blocks_in_checkpt
> 0) {
779 dev
->is_checkpointed
= 0;
780 yaffs2_checkpt_invalidate_stream(dev
);
782 if (dev
->param
.sb_dirty_fn
)
783 dev
->param
.sb_dirty_fn(dev
);
786 int yaffs_checkpoint_save(struct yaffs_dev
*dev
)
788 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
789 "save entry: is_checkpointed %d",
790 dev
->is_checkpointed
);
792 yaffs_verify_objects(dev
);
793 yaffs_verify_blocks(dev
);
794 yaffs_verify_free_chunks(dev
);
796 if (!dev
->is_checkpointed
) {
797 yaffs2_checkpt_invalidate(dev
);
798 yaffs2_wr_checkpt_data(dev
);
801 yaffs_trace(YAFFS_TRACE_CHECKPOINT
| YAFFS_TRACE_MOUNT
,
802 "save exit: is_checkpointed %d",
803 dev
->is_checkpointed
);
805 return dev
->is_checkpointed
;
808 int yaffs2_checkpt_restore(struct yaffs_dev
*dev
)
812 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
813 "restore entry: is_checkpointed %d",
814 dev
->is_checkpointed
);
816 retval
= yaffs2_rd_checkpt_data(dev
);
818 if (dev
->is_checkpointed
) {
819 yaffs_verify_objects(dev
);
820 yaffs_verify_blocks(dev
);
821 yaffs_verify_free_chunks(dev
);
824 yaffs_trace(YAFFS_TRACE_CHECKPOINT
,
825 "restore exit: is_checkpointed %d",
826 dev
->is_checkpointed
);
831 int yaffs2_handle_hole(struct yaffs_obj
*obj
, loff_t new_size
)
833 /* if new_size > old_file_size.
834 * We're going to be writing a hole.
835 * If the hole is small then write zeros otherwise write a start
838 loff_t old_file_size
;
841 int result
= YAFFS_OK
;
842 struct yaffs_dev
*dev
= NULL
;
843 u8
*local_buffer
= NULL
;
844 int small_increase_ok
= 0;
849 if (obj
->variant_type
!= YAFFS_OBJECT_TYPE_FILE
)
854 /* Bail out if not yaffs2 mode */
855 if (!dev
->param
.is_yaffs2
)
858 old_file_size
= obj
->variant
.file_variant
.file_size
;
860 if (new_size
<= old_file_size
)
863 increase
= new_size
- old_file_size
;
865 if (increase
< YAFFS_SMALL_HOLE_THRESHOLD
* dev
->data_bytes_per_chunk
&&
866 yaffs_check_alloc_available(dev
, YAFFS_SMALL_HOLE_THRESHOLD
+ 1))
872 local_buffer
= yaffs_get_temp_buffer(dev
);
875 /* fill hole with zero bytes */
876 loff_t pos
= old_file_size
;
879 memset(local_buffer
, 0, dev
->data_bytes_per_chunk
);
880 small_increase_ok
= 1;
882 while (increase
> 0 && small_increase_ok
) {
883 this_write
= increase
;
884 if (this_write
> dev
->data_bytes_per_chunk
)
885 this_write
= dev
->data_bytes_per_chunk
;
887 yaffs_do_file_wr(obj
, local_buffer
, pos
, this_write
,
889 if (written
== this_write
) {
891 increase
-= this_write
;
893 small_increase_ok
= 0;
897 yaffs_release_temp_buffer(dev
, local_buffer
);
899 /* If out of space then reverse any chunks we've added */
900 if (!small_increase_ok
)
901 yaffs_resize_file_down(obj
, old_file_size
);
904 if (!small_increase_ok
&&
906 obj
->parent
->obj_id
!= YAFFS_OBJECTID_UNLINKED
&&
907 obj
->parent
->obj_id
!= YAFFS_OBJECTID_DELETED
) {
908 /* Write a hole start header with the old file size */
909 yaffs_update_oh(obj
, NULL
, 0, 1, 0, NULL
);
915 struct yaffs_block_index
{
920 static int yaffs2_ybicmp(const void *a
, const void *b
)
922 int aseq
= ((struct yaffs_block_index
*)a
)->seq
;
923 int bseq
= ((struct yaffs_block_index
*)b
)->seq
;
924 int ablock
= ((struct yaffs_block_index
*)a
)->block
;
925 int bblock
= ((struct yaffs_block_index
*)b
)->block
;
928 return ablock
- bblock
;
933 static inline int yaffs2_scan_chunk(struct yaffs_dev
*dev
,
934 struct yaffs_block_info
*bi
,
935 int blk
, int chunk_in_block
,
938 struct list_head
*hard_list
,
939 int summary_available
)
941 struct yaffs_obj_hdr
*oh
;
942 struct yaffs_obj
*in
;
943 struct yaffs_obj
*parent
;
948 struct yaffs_ext_tags tags
;
950 int alloc_failed
= 0;
951 int chunk
= blk
* dev
->param
.chunks_per_block
+ chunk_in_block
;
952 struct yaffs_file_var
*file_var
;
953 struct yaffs_hardlink_var
*hl_var
;
954 struct yaffs_symlink_var
*sl_var
;
956 if (summary_available
) {
957 result
= yaffs_summary_fetch(dev
, &tags
, chunk_in_block
);
958 tags
.seq_number
= bi
->seq_number
;
961 if (!summary_available
|| tags
.obj_id
== 0) {
962 result
= yaffs_rd_chunk_tags_nand(dev
, chunk
, NULL
, &tags
);
968 /* Let's have a good look at this chunk... */
970 if (!tags
.chunk_used
) {
971 /* An unassigned chunk in the block.
972 * If there are used chunks after this one, then
973 * it is a chunk that was skipped due to failing
974 * the erased check. Just skip it so that it can
976 * But, more typically, We get here when this is
977 * an unallocated chunk and his means that
978 * either the block is empty or this is the one
979 * being allocated from
983 /* This is a chunk that was skipped due
984 * to failing the erased check */
985 } else if (chunk_in_block
== 0) {
986 /* We're looking at the first chunk in
987 * the block so the block is unused */
988 bi
->block_state
= YAFFS_BLOCK_STATE_EMPTY
;
989 dev
->n_erased_blocks
++;
991 if (bi
->block_state
== YAFFS_BLOCK_STATE_NEEDS_SCAN
||
992 bi
->block_state
== YAFFS_BLOCK_STATE_ALLOCATING
) {
993 if (dev
->seq_number
== bi
->seq_number
) {
994 /* Allocating from this block*/
995 yaffs_trace(YAFFS_TRACE_SCAN
,
996 " Allocating from %d %d",
997 blk
, chunk_in_block
);
1000 YAFFS_BLOCK_STATE_ALLOCATING
;
1001 dev
->alloc_block
= blk
;
1002 dev
->alloc_page
= chunk_in_block
;
1003 dev
->alloc_block_finder
= blk
;
1005 /* This is a partially written block
1006 * that is not the current
1009 yaffs_trace(YAFFS_TRACE_SCAN
,
1010 "Partially written block %d detected. gc will fix this.",
1016 dev
->n_free_chunks
++;
1018 } else if (tags
.ecc_result
==
1019 YAFFS_ECC_RESULT_UNFIXED
) {
1020 yaffs_trace(YAFFS_TRACE_SCAN
,
1021 " Unfixed ECC in chunk(%d:%d), chunk ignored",
1022 blk
, chunk_in_block
);
1023 dev
->n_free_chunks
++;
1024 } else if (tags
.obj_id
> YAFFS_MAX_OBJECT_ID
||
1025 tags
.chunk_id
> YAFFS_MAX_CHUNK_ID
||
1026 tags
.obj_id
== YAFFS_OBJECTID_SUMMARY
||
1027 (tags
.chunk_id
> 0 &&
1028 tags
.n_bytes
> dev
->data_bytes_per_chunk
) ||
1029 tags
.seq_number
!= bi
->seq_number
) {
1030 yaffs_trace(YAFFS_TRACE_SCAN
,
1031 "Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored",
1032 blk
, chunk_in_block
, tags
.obj_id
,
1033 tags
.chunk_id
, tags
.n_bytes
);
1034 dev
->n_free_chunks
++;
1035 } else if (tags
.chunk_id
> 0) {
1036 /* chunk_id > 0 so it is a data chunk... */
1038 loff_t chunk_base
= (tags
.chunk_id
- 1) *
1039 dev
->data_bytes_per_chunk
;
1043 yaffs_set_chunk_bit(dev
, blk
, chunk_in_block
);
1046 in
= yaffs_find_or_create_by_number(dev
,
1048 YAFFS_OBJECT_TYPE_FILE
);
1054 in
->variant_type
== YAFFS_OBJECT_TYPE_FILE
&&
1055 chunk_base
< in
->variant
.file_variant
.shrink_size
) {
1056 /* This has not been invalidated by
1058 if (!yaffs_put_chunk_in_file(in
, tags
.chunk_id
,
1062 /* File size is calculated by looking at
1063 * the data chunks if we have not
1064 * seen an object header yet.
1065 * Stop this practice once we find an
1068 endpos
= chunk_base
+ tags
.n_bytes
;
1071 in
->variant
.file_variant
.scanned_size
< endpos
) {
1072 in
->variant
.file_variant
.
1073 scanned_size
= endpos
;
1074 in
->variant
.file_variant
.
1078 /* This chunk has been invalidated by a
1079 * resize, or a past file deletion
1080 * so delete the chunk*/
1081 yaffs_chunk_del(dev
, chunk
, 1, __LINE__
);
1084 /* chunk_id == 0, so it is an ObjectHeader.
1085 * Thus, we read in the object header and make
1090 yaffs_set_chunk_bit(dev
, blk
, chunk_in_block
);
1096 if (tags
.extra_available
) {
1097 in
= yaffs_find_or_create_by_number(dev
,
1099 tags
.extra_obj_type
);
1105 (!in
->valid
&& dev
->param
.disable_lazy_load
) ||
1106 tags
.extra_shadows
||
1107 (!in
->valid
&& (tags
.obj_id
== YAFFS_OBJECTID_ROOT
||
1108 tags
.obj_id
== YAFFS_OBJECTID_LOSTNFOUND
))) {
1110 /* If we don't have valid info then we
1111 * need to read the chunk
1112 * TODO In future we can probably defer
1113 * reading the chunk and living with
1114 * invalid data until needed.
1117 result
= yaffs_rd_chunk_tags_nand(dev
,
1122 oh
= (struct yaffs_obj_hdr
*)chunk_data
;
1124 if (dev
->param
.inband_tags
) {
1125 /* Fix up the header if they got
1126 * corrupted by inband tags */
1128 oh
->inband_shadowed_obj_id
;
1130 oh
->inband_is_shrink
;
1134 in
= yaffs_find_or_create_by_number(dev
,
1135 tags
.obj_id
, oh
->type
);
1142 /* TODO Hoosterman we have a problem! */
1143 yaffs_trace(YAFFS_TRACE_ERROR
,
1144 "yaffs tragedy: Could not make object for object %d at chunk %d during scan",
1145 tags
.obj_id
, chunk
);
1150 /* We have already filled this one.
1151 * We have a duplicate that will be
1152 * discarded, but we first have to suck
1153 * out resize info if it is a file.
1155 if ((in
->variant_type
== YAFFS_OBJECT_TYPE_FILE
) &&
1156 ((oh
&& oh
->type
== YAFFS_OBJECT_TYPE_FILE
) ||
1157 (tags
.extra_available
&&
1158 tags
.extra_obj_type
== YAFFS_OBJECT_TYPE_FILE
)
1160 loff_t this_size
= (oh
) ?
1161 yaffs_oh_to_size(oh
) :
1162 tags
.extra_file_size
;
1163 u32 parent_obj_id
= (oh
) ?
1165 tags
.extra_parent_id
;
1169 tags
.extra_is_shrink
;
1171 /* If it is deleted (unlinked
1172 * at start also means deleted)
1173 * we treat the file size as
1174 * being zeroed at this point.
1176 if (parent_obj_id
== YAFFS_OBJECTID_DELETED
||
1177 parent_obj_id
== YAFFS_OBJECTID_UNLINKED
) {
1183 in
->variant
.file_variant
.shrink_size
>
1185 in
->variant
.file_variant
.shrink_size
=
1189 bi
->has_shrink_hdr
= 1;
1191 /* Use existing - destroy this one. */
1192 yaffs_chunk_del(dev
, chunk
, 1, __LINE__
);
1195 if (!in
->valid
&& in
->variant_type
!=
1196 (oh
? oh
->type
: tags
.extra_obj_type
)) {
1197 yaffs_trace(YAFFS_TRACE_ERROR
,
1198 "yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan",
1199 oh
? oh
->type
: tags
.extra_obj_type
,
1200 in
->variant_type
, tags
.obj_id
,
1202 in
= yaffs_retype_obj(in
, oh
? oh
->type
: tags
.extra_obj_type
);
1206 (tags
.obj_id
== YAFFS_OBJECTID_ROOT
||
1207 tags
.obj_id
== YAFFS_OBJECTID_LOSTNFOUND
)) {
1208 /* We only load some info, don't fiddle
1209 * with directory structure */
1213 in
->yst_mode
= oh
->yst_mode
;
1214 yaffs_load_attribs(in
, oh
);
1215 in
->lazy_loaded
= 0;
1217 in
->lazy_loaded
= 1;
1219 in
->hdr_chunk
= chunk
;
1221 } else if (!in
->valid
) {
1222 /* we need to load this info */
1224 in
->hdr_chunk
= chunk
;
1226 in
->variant_type
= oh
->type
;
1227 in
->yst_mode
= oh
->yst_mode
;
1228 yaffs_load_attribs(in
, oh
);
1230 if (oh
->shadows_obj
> 0)
1231 yaffs_handle_shadowed_obj(dev
,
1232 oh
->shadows_obj
, 1);
1234 yaffs_set_obj_name_from_oh(in
, oh
);
1235 parent
= yaffs_find_or_create_by_number(dev
,
1237 YAFFS_OBJECT_TYPE_DIRECTORY
);
1238 file_size
= yaffs_oh_to_size(oh
);
1239 is_shrink
= oh
->is_shrink
;
1240 equiv_id
= oh
->equiv_id
;
1242 in
->variant_type
= tags
.extra_obj_type
;
1243 parent
= yaffs_find_or_create_by_number(dev
,
1244 tags
.extra_parent_id
,
1245 YAFFS_OBJECT_TYPE_DIRECTORY
);
1246 file_size
= tags
.extra_file_size
;
1247 is_shrink
= tags
.extra_is_shrink
;
1248 equiv_id
= tags
.extra_equiv_id
;
1249 in
->lazy_loaded
= 1;
1256 /* directory stuff...
1261 parent
->variant_type
== YAFFS_OBJECT_TYPE_UNKNOWN
) {
1262 /* Set up as a directory */
1263 parent
->variant_type
=
1264 YAFFS_OBJECT_TYPE_DIRECTORY
;
1265 INIT_LIST_HEAD(&parent
->
1266 variant
.dir_variant
.children
);
1267 } else if (!parent
||
1268 parent
->variant_type
!=
1269 YAFFS_OBJECT_TYPE_DIRECTORY
) {
1270 /* Hoosterman, another problem....
1271 * Trying to use a non-directory as a directory
1274 yaffs_trace(YAFFS_TRACE_ERROR
,
1275 "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
1277 parent
= dev
->lost_n_found
;
1279 yaffs_add_obj_to_dir(parent
, in
);
1281 is_unlinked
= (parent
== dev
->del_dir
) ||
1282 (parent
== dev
->unlinked_dir
);
1285 /* Mark the block */
1286 bi
->has_shrink_hdr
= 1;
1288 /* Note re hardlinks.
1289 * Since we might scan a hardlink before its equivalent
1290 * object is scanned we put them all in a list.
1291 * After scanning is complete, we should have all the
1292 * objects, so we run through this list and fix up all
1296 switch (in
->variant_type
) {
1297 case YAFFS_OBJECT_TYPE_UNKNOWN
:
1298 /* Todo got a problem */
1300 case YAFFS_OBJECT_TYPE_FILE
:
1301 file_var
= &in
->variant
.file_variant
;
1302 if (file_var
->scanned_size
< file_size
) {
1303 /* This covers the case where the file
1304 * size is greater than the data held.
1305 * This will happen if the file is
1306 * resized to be larger than its
1307 * current data extents.
1309 file_var
->file_size
= file_size
;
1310 file_var
->scanned_size
= file_size
;
1313 if (file_var
->shrink_size
> file_size
)
1314 file_var
->shrink_size
= file_size
;
1317 case YAFFS_OBJECT_TYPE_HARDLINK
:
1318 hl_var
= &in
->variant
.hardlink_variant
;
1320 hl_var
->equiv_id
= equiv_id
;
1321 list_add(&in
->hard_links
, hard_list
);
1324 case YAFFS_OBJECT_TYPE_DIRECTORY
:
1327 case YAFFS_OBJECT_TYPE_SPECIAL
:
1330 case YAFFS_OBJECT_TYPE_SYMLINK
:
1331 sl_var
= &in
->variant
.symlink_variant
;
1334 yaffs_clone_str(oh
->alias
);
1342 return alloc_failed
? YAFFS_FAIL
: YAFFS_OK
;
1345 int yaffs2_scan_backwards(struct yaffs_dev
*dev
)
1352 enum yaffs_block_state state
;
1355 LIST_HEAD(hard_list
);
1356 struct yaffs_block_info
*bi
;
1358 int n_blocks
= dev
->internal_end_block
- dev
->internal_start_block
+ 1;
1361 int alloc_failed
= 0;
1362 struct yaffs_block_index
*block_index
= NULL
;
1363 int alt_block_index
= 0;
1364 int summary_available
;
1366 yaffs_trace(YAFFS_TRACE_SCAN
,
1367 "yaffs2_scan_backwards starts intstartblk %d intendblk %d...",
1368 dev
->internal_start_block
, dev
->internal_end_block
);
1370 dev
->seq_number
= YAFFS_LOWEST_SEQUENCE_NUMBER
;
1373 kmalloc(n_blocks
* sizeof(struct yaffs_block_index
), GFP_NOFS
);
1377 vmalloc(n_blocks
* sizeof(struct yaffs_block_index
));
1378 alt_block_index
= 1;
1382 yaffs_trace(YAFFS_TRACE_SCAN
,
1383 "yaffs2_scan_backwards() could not allocate block index!"
1388 dev
->blocks_in_checkpt
= 0;
1390 chunk_data
= yaffs_get_temp_buffer(dev
);
1392 /* Scan all the blocks to determine their state */
1393 bi
= dev
->block_info
;
1394 for (blk
= dev
->internal_start_block
; blk
<= dev
->internal_end_block
;
1396 yaffs_clear_chunk_bits(dev
, blk
);
1397 bi
->pages_in_use
= 0;
1398 bi
->soft_del_pages
= 0;
1400 yaffs_query_init_block_state(dev
, blk
, &state
, &seq_number
);
1402 bi
->block_state
= state
;
1403 bi
->seq_number
= seq_number
;
1405 if (bi
->seq_number
== YAFFS_SEQUENCE_CHECKPOINT_DATA
)
1406 bi
->block_state
= YAFFS_BLOCK_STATE_CHECKPOINT
;
1407 if (bi
->seq_number
== YAFFS_SEQUENCE_BAD_BLOCK
)
1408 bi
->block_state
= YAFFS_BLOCK_STATE_DEAD
;
1410 yaffs_trace(YAFFS_TRACE_SCAN_DEBUG
,
1411 "Block scanning block %d state %d seq %d",
1412 blk
, bi
->block_state
, seq_number
);
1414 if (bi
->block_state
== YAFFS_BLOCK_STATE_CHECKPOINT
) {
1415 dev
->blocks_in_checkpt
++;
1417 } else if (bi
->block_state
== YAFFS_BLOCK_STATE_DEAD
) {
1418 yaffs_trace(YAFFS_TRACE_BAD_BLOCKS
,
1419 "block %d is bad", blk
);
1420 } else if (bi
->block_state
== YAFFS_BLOCK_STATE_EMPTY
) {
1421 yaffs_trace(YAFFS_TRACE_SCAN_DEBUG
, "Block empty ");
1422 dev
->n_erased_blocks
++;
1423 dev
->n_free_chunks
+= dev
->param
.chunks_per_block
;
1424 } else if (bi
->block_state
==
1425 YAFFS_BLOCK_STATE_NEEDS_SCAN
) {
1426 /* Determine the highest sequence number */
1427 if (seq_number
>= YAFFS_LOWEST_SEQUENCE_NUMBER
&&
1428 seq_number
< YAFFS_HIGHEST_SEQUENCE_NUMBER
) {
1429 block_index
[n_to_scan
].seq
= seq_number
;
1430 block_index
[n_to_scan
].block
= blk
;
1432 if (seq_number
>= dev
->seq_number
)
1433 dev
->seq_number
= seq_number
;
1435 /* TODO: Nasty sequence number! */
1436 yaffs_trace(YAFFS_TRACE_SCAN
,
1437 "Block scanning block %d has bad sequence number %d",
1444 yaffs_trace(YAFFS_TRACE_ALWAYS
, "%d blocks to be sorted...", n_to_scan
);
1448 /* Sort the blocks by sequence number */
1449 sort(block_index
, n_to_scan
, sizeof(struct yaffs_block_index
),
1450 yaffs2_ybicmp
, NULL
);
1454 yaffs_trace(YAFFS_TRACE_SCAN
, "...done");
1456 /* Now scan the blocks looking at the data. */
1458 end_iter
= n_to_scan
- 1;
1459 yaffs_trace(YAFFS_TRACE_SCAN_DEBUG
, "%d blocks to scan", n_to_scan
);
1461 /* For each block.... backwards */
1462 for (block_iter
= end_iter
;
1463 !alloc_failed
&& block_iter
>= start_iter
;
1465 /* Cooperative multitasking! This loop can run for so
1466 long that watchdog timers expire. */
1469 /* get the block to scan in the correct order */
1470 blk
= block_index
[block_iter
].block
;
1471 bi
= yaffs_get_block_info(dev
, blk
);
1474 summary_available
= yaffs_summary_read(dev
, dev
->sum_tags
, blk
);
1476 /* For each chunk in each block that needs scanning.... */
1478 if (summary_available
)
1479 c
= dev
->chunks_per_summary
- 1;
1481 c
= dev
->param
.chunks_per_block
- 1;
1483 for (/* c is already initialised */;
1484 !alloc_failed
&& c
>= 0 &&
1485 (bi
->block_state
== YAFFS_BLOCK_STATE_NEEDS_SCAN
||
1486 bi
->block_state
== YAFFS_BLOCK_STATE_ALLOCATING
);
1488 /* Scan backwards...
1489 * Read the tags and decide what to do
1491 if (yaffs2_scan_chunk(dev
, bi
, blk
, c
,
1492 &found_chunks
, chunk_data
,
1493 &hard_list
, summary_available
) ==
1498 if (bi
->block_state
== YAFFS_BLOCK_STATE_NEEDS_SCAN
) {
1499 /* If we got this far while scanning, then the block
1500 * is fully allocated. */
1501 bi
->block_state
= YAFFS_BLOCK_STATE_FULL
;
1504 /* Now let's see if it was dirty */
1505 if (bi
->pages_in_use
== 0 &&
1506 !bi
->has_shrink_hdr
&&
1507 bi
->block_state
== YAFFS_BLOCK_STATE_FULL
) {
1508 yaffs_block_became_dirty(dev
, blk
);
1512 yaffs_skip_rest_of_block(dev
);
1514 if (alt_block_index
)
1519 /* Ok, we've done all the scanning.
1520 * Fix up the hard link chains.
1521 * We have scanned all the objects, now it's time to add these
1524 yaffs_link_fixup(dev
, &hard_list
);
1526 yaffs_release_temp_buffer(dev
, chunk_data
);
1531 yaffs_trace(YAFFS_TRACE_SCAN
, "yaffs2_scan_backwards ends");