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
;
949 int alloc_failed
= 0;
950 int chunk
= blk
* dev
->param
.chunks_per_block
+ chunk_in_block
;
951 struct yaffs_file_var
*file_var
;
952 struct yaffs_hardlink_var
*hl_var
;
953 struct yaffs_symlink_var
*sl_var
;
955 if (summary_available
) {
956 yaffs_summary_fetch(dev
, &tags
, chunk_in_block
);
957 tags
.seq_number
= bi
->seq_number
;
960 if (!summary_available
|| tags
.obj_id
== 0) {
961 yaffs_rd_chunk_tags_nand(dev
, chunk
, NULL
, &tags
);
967 /* Let's have a good look at this chunk... */
969 if (!tags
.chunk_used
) {
970 /* An unassigned chunk in the block.
971 * If there are used chunks after this one, then
972 * it is a chunk that was skipped due to failing
973 * the erased check. Just skip it so that it can
975 * But, more typically, We get here when this is
976 * an unallocated chunk and his means that
977 * either the block is empty or this is the one
978 * being allocated from
982 /* This is a chunk that was skipped due
983 * to failing the erased check */
984 } else if (chunk_in_block
== 0) {
985 /* We're looking at the first chunk in
986 * the block so the block is unused */
987 bi
->block_state
= YAFFS_BLOCK_STATE_EMPTY
;
988 dev
->n_erased_blocks
++;
990 if (bi
->block_state
== YAFFS_BLOCK_STATE_NEEDS_SCAN
||
991 bi
->block_state
== YAFFS_BLOCK_STATE_ALLOCATING
) {
992 if (dev
->seq_number
== bi
->seq_number
) {
993 /* Allocating from this block*/
994 yaffs_trace(YAFFS_TRACE_SCAN
,
995 " Allocating from %d %d",
996 blk
, chunk_in_block
);
999 YAFFS_BLOCK_STATE_ALLOCATING
;
1000 dev
->alloc_block
= blk
;
1001 dev
->alloc_page
= chunk_in_block
;
1002 dev
->alloc_block_finder
= blk
;
1004 /* This is a partially written block
1005 * that is not the current
1008 yaffs_trace(YAFFS_TRACE_SCAN
,
1009 "Partially written block %d detected. gc will fix this.",
1015 dev
->n_free_chunks
++;
1017 } else if (tags
.ecc_result
==
1018 YAFFS_ECC_RESULT_UNFIXED
) {
1019 yaffs_trace(YAFFS_TRACE_SCAN
,
1020 " Unfixed ECC in chunk(%d:%d), chunk ignored",
1021 blk
, chunk_in_block
);
1022 dev
->n_free_chunks
++;
1023 } else if (tags
.obj_id
> YAFFS_MAX_OBJECT_ID
||
1024 tags
.chunk_id
> YAFFS_MAX_CHUNK_ID
||
1025 tags
.obj_id
== YAFFS_OBJECTID_SUMMARY
||
1026 (tags
.chunk_id
> 0 &&
1027 tags
.n_bytes
> dev
->data_bytes_per_chunk
) ||
1028 tags
.seq_number
!= bi
->seq_number
) {
1029 yaffs_trace(YAFFS_TRACE_SCAN
,
1030 "Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored",
1031 blk
, chunk_in_block
, tags
.obj_id
,
1032 tags
.chunk_id
, tags
.n_bytes
);
1033 dev
->n_free_chunks
++;
1034 } else if (tags
.chunk_id
> 0) {
1035 /* chunk_id > 0 so it is a data chunk... */
1037 loff_t chunk_base
= (tags
.chunk_id
- 1) *
1038 dev
->data_bytes_per_chunk
;
1042 yaffs_set_chunk_bit(dev
, blk
, chunk_in_block
);
1045 in
= yaffs_find_or_create_by_number(dev
,
1047 YAFFS_OBJECT_TYPE_FILE
);
1053 in
->variant_type
== YAFFS_OBJECT_TYPE_FILE
&&
1054 chunk_base
< in
->variant
.file_variant
.shrink_size
) {
1055 /* This has not been invalidated by
1057 if (!yaffs_put_chunk_in_file(in
, tags
.chunk_id
,
1061 /* File size is calculated by looking at
1062 * the data chunks if we have not
1063 * seen an object header yet.
1064 * Stop this practice once we find an
1067 endpos
= chunk_base
+ tags
.n_bytes
;
1070 in
->variant
.file_variant
.scanned_size
< endpos
) {
1071 in
->variant
.file_variant
.
1072 scanned_size
= endpos
;
1073 in
->variant
.file_variant
.
1077 /* This chunk has been invalidated by a
1078 * resize, or a past file deletion
1079 * so delete the chunk*/
1080 yaffs_chunk_del(dev
, chunk
, 1, __LINE__
);
1083 /* chunk_id == 0, so it is an ObjectHeader.
1084 * Thus, we read in the object header and make
1089 yaffs_set_chunk_bit(dev
, blk
, chunk_in_block
);
1095 if (tags
.extra_available
) {
1096 in
= yaffs_find_or_create_by_number(dev
,
1098 tags
.extra_obj_type
);
1104 (!in
->valid
&& dev
->param
.disable_lazy_load
) ||
1105 tags
.extra_shadows
||
1106 (!in
->valid
&& (tags
.obj_id
== YAFFS_OBJECTID_ROOT
||
1107 tags
.obj_id
== YAFFS_OBJECTID_LOSTNFOUND
))) {
1109 /* If we don't have valid info then we
1110 * need to read the chunk
1111 * TODO In future we can probably defer
1112 * reading the chunk and living with
1113 * invalid data until needed.
1116 yaffs_rd_chunk_tags_nand(dev
, chunk
, chunk_data
, NULL
);
1118 oh
= (struct yaffs_obj_hdr
*)chunk_data
;
1120 if (dev
->param
.inband_tags
) {
1121 /* Fix up the header if they got
1122 * corrupted by inband tags */
1124 oh
->inband_shadowed_obj_id
;
1126 oh
->inband_is_shrink
;
1130 in
= yaffs_find_or_create_by_number(dev
,
1131 tags
.obj_id
, oh
->type
);
1138 /* TODO Hoosterman we have a problem! */
1139 yaffs_trace(YAFFS_TRACE_ERROR
,
1140 "yaffs tragedy: Could not make object for object %d at chunk %d during scan",
1141 tags
.obj_id
, chunk
);
1146 /* We have already filled this one.
1147 * We have a duplicate that will be
1148 * discarded, but we first have to suck
1149 * out resize info if it is a file.
1151 if ((in
->variant_type
== YAFFS_OBJECT_TYPE_FILE
) &&
1152 ((oh
&& oh
->type
== YAFFS_OBJECT_TYPE_FILE
) ||
1153 (tags
.extra_available
&&
1154 tags
.extra_obj_type
== YAFFS_OBJECT_TYPE_FILE
)
1156 loff_t this_size
= (oh
) ?
1157 yaffs_oh_to_size(oh
) :
1158 tags
.extra_file_size
;
1159 u32 parent_obj_id
= (oh
) ?
1161 tags
.extra_parent_id
;
1165 tags
.extra_is_shrink
;
1167 /* If it is deleted (unlinked
1168 * at start also means deleted)
1169 * we treat the file size as
1170 * being zeroed at this point.
1172 if (parent_obj_id
== YAFFS_OBJECTID_DELETED
||
1173 parent_obj_id
== YAFFS_OBJECTID_UNLINKED
) {
1179 in
->variant
.file_variant
.shrink_size
>
1181 in
->variant
.file_variant
.shrink_size
=
1185 bi
->has_shrink_hdr
= 1;
1187 /* Use existing - destroy this one. */
1188 yaffs_chunk_del(dev
, chunk
, 1, __LINE__
);
1191 if (!in
->valid
&& in
->variant_type
!=
1192 (oh
? oh
->type
: tags
.extra_obj_type
))
1193 yaffs_trace(YAFFS_TRACE_ERROR
,
1194 "yaffs tragedy: Bad object type, %d != %d, for object %d at chunk %d during scan",
1195 oh
? oh
->type
: tags
.extra_obj_type
,
1196 in
->variant_type
, tags
.obj_id
,
1200 (tags
.obj_id
== YAFFS_OBJECTID_ROOT
||
1201 tags
.obj_id
== YAFFS_OBJECTID_LOSTNFOUND
)) {
1202 /* We only load some info, don't fiddle
1203 * with directory structure */
1207 in
->yst_mode
= oh
->yst_mode
;
1208 yaffs_load_attribs(in
, oh
);
1209 in
->lazy_loaded
= 0;
1211 in
->lazy_loaded
= 1;
1213 in
->hdr_chunk
= chunk
;
1215 } else if (!in
->valid
) {
1216 /* we need to load this info */
1218 in
->hdr_chunk
= chunk
;
1220 in
->variant_type
= oh
->type
;
1221 in
->yst_mode
= oh
->yst_mode
;
1222 yaffs_load_attribs(in
, oh
);
1224 if (oh
->shadows_obj
> 0)
1225 yaffs_handle_shadowed_obj(dev
,
1226 oh
->shadows_obj
, 1);
1228 yaffs_set_obj_name_from_oh(in
, oh
);
1229 parent
= yaffs_find_or_create_by_number(dev
,
1231 YAFFS_OBJECT_TYPE_DIRECTORY
);
1232 file_size
= yaffs_oh_to_size(oh
);
1233 is_shrink
= oh
->is_shrink
;
1234 equiv_id
= oh
->equiv_id
;
1236 in
->variant_type
= tags
.extra_obj_type
;
1237 parent
= yaffs_find_or_create_by_number(dev
,
1238 tags
.extra_parent_id
,
1239 YAFFS_OBJECT_TYPE_DIRECTORY
);
1240 file_size
= tags
.extra_file_size
;
1241 is_shrink
= tags
.extra_is_shrink
;
1242 equiv_id
= tags
.extra_equiv_id
;
1243 in
->lazy_loaded
= 1;
1250 /* directory stuff...
1255 parent
->variant_type
== YAFFS_OBJECT_TYPE_UNKNOWN
) {
1256 /* Set up as a directory */
1257 parent
->variant_type
=
1258 YAFFS_OBJECT_TYPE_DIRECTORY
;
1259 INIT_LIST_HEAD(&parent
->
1260 variant
.dir_variant
.children
);
1261 } else if (!parent
||
1262 parent
->variant_type
!=
1263 YAFFS_OBJECT_TYPE_DIRECTORY
) {
1264 /* Hoosterman, another problem....
1265 * Trying to use a non-directory as a directory
1268 yaffs_trace(YAFFS_TRACE_ERROR
,
1269 "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
1271 parent
= dev
->lost_n_found
;
1273 yaffs_add_obj_to_dir(parent
, in
);
1275 is_unlinked
= (parent
== dev
->del_dir
) ||
1276 (parent
== dev
->unlinked_dir
);
1279 /* Mark the block */
1280 bi
->has_shrink_hdr
= 1;
1282 /* Note re hardlinks.
1283 * Since we might scan a hardlink before its equivalent
1284 * object is scanned we put them all in a list.
1285 * After scanning is complete, we should have all the
1286 * objects, so we run through this list and fix up all
1290 switch (in
->variant_type
) {
1291 case YAFFS_OBJECT_TYPE_UNKNOWN
:
1292 /* Todo got a problem */
1294 case YAFFS_OBJECT_TYPE_FILE
:
1295 file_var
= &in
->variant
.file_variant
;
1296 if (file_var
->scanned_size
< file_size
) {
1297 /* This covers the case where the file
1298 * size is greater than the data held.
1299 * This will happen if the file is
1300 * resized to be larger than its
1301 * current data extents.
1303 file_var
->file_size
= file_size
;
1304 file_var
->scanned_size
= file_size
;
1307 if (file_var
->shrink_size
> file_size
)
1308 file_var
->shrink_size
= file_size
;
1311 case YAFFS_OBJECT_TYPE_HARDLINK
:
1312 hl_var
= &in
->variant
.hardlink_variant
;
1314 hl_var
->equiv_id
= equiv_id
;
1315 list_add(&in
->hard_links
, hard_list
);
1318 case YAFFS_OBJECT_TYPE_DIRECTORY
:
1321 case YAFFS_OBJECT_TYPE_SPECIAL
:
1324 case YAFFS_OBJECT_TYPE_SYMLINK
:
1325 sl_var
= &in
->variant
.symlink_variant
;
1328 yaffs_clone_str(oh
->alias
);
1336 return alloc_failed
? YAFFS_FAIL
: YAFFS_OK
;
1339 int yaffs2_scan_backwards(struct yaffs_dev
*dev
)
1346 enum yaffs_block_state state
;
1348 LIST_HEAD(hard_list
);
1349 struct yaffs_block_info
*bi
;
1351 int n_blocks
= dev
->internal_end_block
- dev
->internal_start_block
+ 1;
1354 int alloc_failed
= 0;
1355 struct yaffs_block_index
*block_index
= NULL
;
1356 int alt_block_index
= 0;
1357 int summary_available
;
1359 yaffs_trace(YAFFS_TRACE_SCAN
,
1360 "yaffs2_scan_backwards starts intstartblk %d intendblk %d...",
1361 dev
->internal_start_block
, dev
->internal_end_block
);
1363 dev
->seq_number
= YAFFS_LOWEST_SEQUENCE_NUMBER
;
1366 kmalloc(n_blocks
* sizeof(struct yaffs_block_index
), GFP_NOFS
);
1370 vmalloc(n_blocks
* sizeof(struct yaffs_block_index
));
1371 alt_block_index
= 1;
1375 yaffs_trace(YAFFS_TRACE_SCAN
,
1376 "yaffs2_scan_backwards() could not allocate block index!"
1381 dev
->blocks_in_checkpt
= 0;
1383 chunk_data
= yaffs_get_temp_buffer(dev
);
1385 /* Scan all the blocks to determine their state */
1386 bi
= dev
->block_info
;
1387 for (blk
= dev
->internal_start_block
; blk
<= dev
->internal_end_block
;
1389 yaffs_clear_chunk_bits(dev
, blk
);
1390 bi
->pages_in_use
= 0;
1391 bi
->soft_del_pages
= 0;
1393 yaffs_query_init_block_state(dev
, blk
, &state
, &seq_number
);
1395 bi
->block_state
= state
;
1396 bi
->seq_number
= seq_number
;
1398 if (bi
->seq_number
== YAFFS_SEQUENCE_CHECKPOINT_DATA
)
1399 bi
->block_state
= YAFFS_BLOCK_STATE_CHECKPOINT
;
1400 if (bi
->seq_number
== YAFFS_SEQUENCE_BAD_BLOCK
)
1401 bi
->block_state
= YAFFS_BLOCK_STATE_DEAD
;
1403 yaffs_trace(YAFFS_TRACE_SCAN_DEBUG
,
1404 "Block scanning block %d state %d seq %d",
1405 blk
, bi
->block_state
, seq_number
);
1407 if (bi
->block_state
== YAFFS_BLOCK_STATE_CHECKPOINT
) {
1408 dev
->blocks_in_checkpt
++;
1410 } else if (bi
->block_state
== YAFFS_BLOCK_STATE_DEAD
) {
1411 yaffs_trace(YAFFS_TRACE_BAD_BLOCKS
,
1412 "block %d is bad", blk
);
1413 } else if (bi
->block_state
== YAFFS_BLOCK_STATE_EMPTY
) {
1414 yaffs_trace(YAFFS_TRACE_SCAN_DEBUG
, "Block empty ");
1415 dev
->n_erased_blocks
++;
1416 dev
->n_free_chunks
+= dev
->param
.chunks_per_block
;
1417 } else if (bi
->block_state
==
1418 YAFFS_BLOCK_STATE_NEEDS_SCAN
) {
1419 /* Determine the highest sequence number */
1420 if (seq_number
>= YAFFS_LOWEST_SEQUENCE_NUMBER
&&
1421 seq_number
< YAFFS_HIGHEST_SEQUENCE_NUMBER
) {
1422 block_index
[n_to_scan
].seq
= seq_number
;
1423 block_index
[n_to_scan
].block
= blk
;
1425 if (seq_number
>= dev
->seq_number
)
1426 dev
->seq_number
= seq_number
;
1428 /* TODO: Nasty sequence number! */
1429 yaffs_trace(YAFFS_TRACE_SCAN
,
1430 "Block scanning block %d has bad sequence number %d",
1437 yaffs_trace(YAFFS_TRACE_SCAN
, "%d blocks to be sorted...", n_to_scan
);
1441 /* Sort the blocks by sequence number */
1442 sort(block_index
, n_to_scan
, sizeof(struct yaffs_block_index
),
1443 yaffs2_ybicmp
, NULL
);
1447 yaffs_trace(YAFFS_TRACE_SCAN
, "...done");
1449 /* Now scan the blocks looking at the data. */
1451 end_iter
= n_to_scan
- 1;
1452 yaffs_trace(YAFFS_TRACE_SCAN_DEBUG
, "%d blocks to scan", n_to_scan
);
1454 /* For each block.... backwards */
1455 for (block_iter
= end_iter
;
1456 !alloc_failed
&& block_iter
>= start_iter
;
1458 /* Cooperative multitasking! This loop can run for so
1459 long that watchdog timers expire. */
1462 /* get the block to scan in the correct order */
1463 blk
= block_index
[block_iter
].block
;
1464 bi
= yaffs_get_block_info(dev
, blk
);
1466 summary_available
= yaffs_summary_read(dev
, dev
->sum_tags
, blk
);
1468 /* For each chunk in each block that needs scanning.... */
1470 if (summary_available
)
1471 c
= dev
->chunks_per_summary
- 1;
1473 c
= dev
->param
.chunks_per_block
- 1;
1475 for (/* c is already initialised */;
1476 !alloc_failed
&& c
>= 0 &&
1477 (bi
->block_state
== YAFFS_BLOCK_STATE_NEEDS_SCAN
||
1478 bi
->block_state
== YAFFS_BLOCK_STATE_ALLOCATING
);
1480 /* Scan backwards...
1481 * Read the tags and decide what to do
1483 if (yaffs2_scan_chunk(dev
, bi
, blk
, c
,
1484 &found_chunks
, chunk_data
,
1485 &hard_list
, summary_available
) ==
1490 if (bi
->block_state
== YAFFS_BLOCK_STATE_NEEDS_SCAN
) {
1491 /* If we got this far while scanning, then the block
1492 * is fully allocated. */
1493 bi
->block_state
= YAFFS_BLOCK_STATE_FULL
;
1496 /* Now let's see if it was dirty */
1497 if (bi
->pages_in_use
== 0 &&
1498 !bi
->has_shrink_hdr
&&
1499 bi
->block_state
== YAFFS_BLOCK_STATE_FULL
) {
1500 yaffs_block_became_dirty(dev
, blk
);
1504 yaffs_skip_rest_of_block(dev
);
1506 if (alt_block_index
)
1511 /* Ok, we've done all the scanning.
1512 * Fix up the hard link chains.
1513 * We have scanned all the objects, now it's time to add these
1516 yaffs_link_fixup(dev
, &hard_list
);
1518 yaffs_release_temp_buffer(dev
, chunk_data
);
1523 yaffs_trace(YAFFS_TRACE_SCAN
, "yaffs2_scan_backwards ends");