1/*
2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3 *
4 * Copyright (C) 2002-2010 Aleph One Ltd.
5 *   for Toby Churchill Ltd and Brightstar Engineering
6 *
7 * Created by Charles Manning <charles@aleph1.co.uk>
8 *
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.
12 */
13
14
15#include "yaffs_guts.h"
16#include "yaffs_trace.h"
17#include "yaffs_yaffs2.h"
18#include "yaffs_checkptrw.h"
19#include "yaffs_bitmap.h"
20#include "yaffs_qsort.h"
21#include "yaffs_nand.h"
22#include "yaffs_getblockinfo.h"
23#include "yaffs_verify.h"
24
25/*
26 * Checkpoints are really no benefit on very small partitions.
27 *
28 * To save space on small partitions don't bother with checkpoints unless
29 * the partition is at least this big.
30 */
31#define YAFFS_CHECKPOINT_MIN_BLOCKS 60
32
33#define YAFFS_SMALL_HOLE_THRESHOLD 4
34
35
36/*
37 * Oldest Dirty Sequence Number handling.
38 */
39
40/* yaffs_calc_oldest_dirty_seq()
41 * yaffs2_find_oldest_dirty_seq()
42 * Calculate the oldest dirty sequence number if we don't know it.
43 */
44void yaffs_calc_oldest_dirty_seq(yaffs_dev_t *dev)
45{
46	int i;
47	unsigned seq;
48	unsigned block_no = 0;
49	yaffs_block_info_t *b;
50
51	if(!dev->param.is_yaffs2)
52		return;
53
54	/* Find the oldest dirty sequence number. */
55	seq = dev->seq_number + 1;
56	b = dev->block_info;
57	for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
58		if (b->block_state == YAFFS_BLOCK_STATE_FULL &&
59			(b->pages_in_use - b->soft_del_pages) < dev->param.chunks_per_block &&
60			b->seq_number < seq) {
61			seq = b->seq_number;
62			block_no = i;
63		}
64		b++;
65	}
66
67	if(block_no){
68		dev->oldest_dirty_seq = seq;
69		dev->oldest_dirty_block = block_no;
70	}
71
72}
73
74
75void yaffs2_find_oldest_dirty_seq(yaffs_dev_t *dev)
76{
77	if(!dev->param.is_yaffs2)
78		return;
79
80	if(!dev->oldest_dirty_seq)
81		yaffs_calc_oldest_dirty_seq(dev);
82}
83
84/*
85 * yaffs_clear_oldest_dirty_seq()
86 * Called when a block is erased or marked bad. (ie. when its seq_number
87 * becomes invalid). If the value matches the oldest then we clear
88 * dev->oldest_dirty_seq to force its recomputation.
89 */
90void yaffs2_clear_oldest_dirty_seq(yaffs_dev_t *dev, yaffs_block_info_t *bi)
91{
92
93	if(!dev->param.is_yaffs2)
94		return;
95
96	if(!bi || bi->seq_number == dev->oldest_dirty_seq){
97		dev->oldest_dirty_seq = 0;
98		dev->oldest_dirty_block = 0;
99	}
100}
101
102/*
103 * yaffs2_update_oldest_dirty_seq()
104 * Update the oldest dirty sequence number whenever we dirty a block.
105 * Only do this if the oldest_dirty_seq is actually being tracked.
106 */
107void yaffs2_update_oldest_dirty_seq(yaffs_dev_t *dev, unsigned block_no, yaffs_block_info_t *bi)
108{
109	if(!dev->param.is_yaffs2)
110		return;
111
112	if(dev->oldest_dirty_seq){
113		if(dev->oldest_dirty_seq > bi->seq_number){
114			dev->oldest_dirty_seq = bi->seq_number;
115			dev->oldest_dirty_block = block_no;
116		}
117	}
118}
119
120int yaffs_block_ok_for_gc(yaffs_dev_t *dev,
121					yaffs_block_info_t *bi)
122{
123
124	if (!dev->param.is_yaffs2)
125		return 1;	/* disqualification only applies to yaffs2. */
126
127	if (!bi->has_shrink_hdr)
128		return 1;	/* can gc */
129
130	yaffs2_find_oldest_dirty_seq(dev);
131
132	/* Can't do gc of this block if there are any blocks older than this one that have
133	 * discarded pages.
134	 */
135	return (bi->seq_number <= dev->oldest_dirty_seq);
136}
137
138/*
139 * yaffs2_find_refresh_block()
140 * periodically finds the oldest full block by sequence number for refreshing.
141 * Only for yaffs2.
142 */
143__u32 yaffs2_find_refresh_block(yaffs_dev_t *dev)
144{
145	__u32 b ;
146
147	__u32 oldest = 0;
148	__u32 oldestSequence = 0;
149
150	yaffs_block_info_t *bi;
151
152	if(!dev->param.is_yaffs2)
153		return oldest;
154
155	/*
156	 * If refresh period < 10 then refreshing is disabled.
157	 */
158	if(dev->param.refresh_period < 10)
159	        return oldest;
160
161        /*
162         * Fix broken values.
163         */
164        if(dev->refresh_skip > dev->param.refresh_period)
165                dev->refresh_skip = dev->param.refresh_period;
166
167	if(dev->refresh_skip > 0)
168	        return oldest;
169
170	/*
171	 * Refresh skip is now zero.
172	 * We'll do a refresh this time around....
173	 * Update the refresh skip and find the oldest block.
174	 */
175	dev->refresh_skip = dev->param.refresh_period;
176	dev->refresh_count++;
177	bi = dev->block_info;
178	for (b = dev->internal_start_block; b <=dev->internal_end_block; b++){
179
180		if (bi->block_state == YAFFS_BLOCK_STATE_FULL){
181
182			if(oldest < 1 ||
183                                bi->seq_number < oldestSequence){
184                                oldest = b;
185                                oldestSequence = bi->seq_number;
186                        }
187		}
188		bi++;
189	}
190
191	if (oldest > 0) {
192		T(YAFFS_TRACE_GC,
193		  (TSTR("GC refresh count %d selected block %d with seq_number %d" TENDSTR),
194		   dev->refresh_count, oldest, oldestSequence));
195	}
196
197	return oldest;
198}
199
200int yaffs2_checkpt_required(yaffs_dev_t *dev)
201{
202	int nblocks;
203
204	if(!dev->param.is_yaffs2)
205		return 0;
206
207	nblocks = dev->internal_end_block - dev->internal_start_block + 1 ;
208
209	return 	!dev->param.skip_checkpt_wr &&
210		!dev->read_only &&
211		(nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS);
212}
213
214int yaffs_calc_checkpt_blocks_required(yaffs_dev_t *dev)
215{
216	int retval;
217
218	if(!dev->param.is_yaffs2)
219		return 0;
220
221	if (!dev->checkpoint_blocks_required &&
222		yaffs2_checkpt_required(dev)){
223		/* Not a valid value so recalculate */
224		int n_bytes = 0;
225		int nBlocks;
226		int devBlocks = (dev->param.end_block - dev->param.start_block + 1);
227
228		n_bytes += sizeof(yaffs_checkpt_validty_t);
229		n_bytes += sizeof(yaffs_checkpt_dev_t);
230		n_bytes += devBlocks * sizeof(yaffs_block_info_t);
231		n_bytes += devBlocks * dev->chunk_bit_stride;
232		n_bytes += (sizeof(yaffs_checkpt_obj_t) + sizeof(__u32)) * (dev->n_obj);
233		n_bytes += (dev->tnode_size + sizeof(__u32)) * (dev->n_tnodes);
234		n_bytes += sizeof(yaffs_checkpt_validty_t);
235		n_bytes += sizeof(__u32); /* checksum*/
236
237		/* Round up and add 2 blocks to allow for some bad blocks, so add 3 */
238
239		nBlocks = (n_bytes/(dev->data_bytes_per_chunk * dev->param.chunks_per_block)) + 3;
240
241		dev->checkpoint_blocks_required = nBlocks;
242	}
243
244	retval = dev->checkpoint_blocks_required - dev->blocks_in_checkpt;
245	if(retval < 0)
246		retval = 0;
247	return retval;
248}
249
250/*--------------------- Checkpointing --------------------*/
251
252
253static int yaffs2_wr_checkpt_validity_marker(yaffs_dev_t *dev, int head)
254{
255	yaffs_checkpt_validty_t cp;
256
257	memset(&cp, 0, sizeof(cp));
258
259	cp.struct_type = sizeof(cp);
260	cp.magic = YAFFS_MAGIC;
261	cp.version = YAFFS_CHECKPOINT_VERSION;
262	cp.head = (head) ? 1 : 0;
263
264	return (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)) ?
265		1 : 0;
266}
267
268static int yaffs2_rd_checkpt_validty_marker(yaffs_dev_t *dev, int head)
269{
270	yaffs_checkpt_validty_t cp;
271	int ok;
272
273	ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
274
275	if (ok)
276		ok = (cp.struct_type == sizeof(cp)) &&
277		     (cp.magic == YAFFS_MAGIC) &&
278		     (cp.version == YAFFS_CHECKPOINT_VERSION) &&
279		     (cp.head == ((head) ? 1 : 0));
280	return ok ? 1 : 0;
281}
282
283static void yaffs2_dev_to_checkpt_dev(yaffs_checkpt_dev_t *cp,
284					   yaffs_dev_t *dev)
285{
286	cp->n_erased_blocks = dev->n_erased_blocks;
287	cp->alloc_block = dev->alloc_block;
288	cp->alloc_page = dev->alloc_page;
289	cp->n_free_chunks = dev->n_free_chunks;
290
291	cp->n_deleted_files = dev->n_deleted_files;
292	cp->n_unlinked_files = dev->n_unlinked_files;
293	cp->n_bg_deletions = dev->n_bg_deletions;
294	cp->seq_number = dev->seq_number;
295
296}
297
298static void yaffs_checkpt_dev_to_dev(yaffs_dev_t *dev,
299					   yaffs_checkpt_dev_t *cp)
300{
301	dev->n_erased_blocks = cp->n_erased_blocks;
302	dev->alloc_block = cp->alloc_block;
303	dev->alloc_page = cp->alloc_page;
304	dev->n_free_chunks = cp->n_free_chunks;
305
306	dev->n_deleted_files = cp->n_deleted_files;
307	dev->n_unlinked_files = cp->n_unlinked_files;
308	dev->n_bg_deletions = cp->n_bg_deletions;
309	dev->seq_number = cp->seq_number;
310}
311
312
313static int yaffs2_wr_checkpt_dev(yaffs_dev_t *dev)
314{
315	yaffs_checkpt_dev_t cp;
316	__u32 n_bytes;
317	__u32 nBlocks = (dev->internal_end_block - dev->internal_start_block + 1);
318
319	int ok;
320
321	/* Write device runtime values*/
322	yaffs2_dev_to_checkpt_dev(&cp, dev);
323	cp.struct_type = sizeof(cp);
324
325	ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
326
327	/* Write block info */
328	if (ok) {
329		n_bytes = nBlocks * sizeof(yaffs_block_info_t);
330		ok = (yaffs2_checkpt_wr(dev, dev->block_info, n_bytes) == n_bytes);
331	}
332
333	/* Write chunk bits */
334	if (ok) {
335		n_bytes = nBlocks * dev->chunk_bit_stride;
336		ok = (yaffs2_checkpt_wr(dev, dev->chunk_bits, n_bytes) == n_bytes);
337	}
338	return	 ok ? 1 : 0;
339
340}
341
342static int yaffs2_rd_checkpt_dev(yaffs_dev_t *dev)
343{
344	yaffs_checkpt_dev_t cp;
345	__u32 n_bytes;
346	__u32 nBlocks = (dev->internal_end_block - dev->internal_start_block + 1);
347
348	int ok;
349
350	ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
351	if (!ok)
352		return 0;
353
354	if (cp.struct_type != sizeof(cp))
355		return 0;
356
357
358	yaffs_checkpt_dev_to_dev(dev, &cp);
359
360	n_bytes = nBlocks * sizeof(yaffs_block_info_t);
361
362	ok = (yaffs2_checkpt_rd(dev, dev->block_info, n_bytes) == n_bytes);
363
364	if (!ok)
365		return 0;
366	n_bytes = nBlocks * dev->chunk_bit_stride;
367
368	ok = (yaffs2_checkpt_rd(dev, dev->chunk_bits, n_bytes) == n_bytes);
369
370	return ok ? 1 : 0;
371}
372
373static void yaffs2_obj_checkpt_obj(yaffs_checkpt_obj_t *cp,
374					   yaffs_obj_t *obj)
375{
376
377	cp->obj_id = obj->obj_id;
378	cp->parent_id = (obj->parent) ? obj->parent->obj_id : 0;
379	cp->hdr_chunk = obj->hdr_chunk;
380	cp->variant_type = obj->variant_type;
381	cp->deleted = obj->deleted;
382	cp->soft_del = obj->soft_del;
383	cp->unlinked = obj->unlinked;
384	cp->fake = obj->fake;
385	cp->rename_allowed = obj->rename_allowed;
386	cp->unlink_allowed = obj->unlink_allowed;
387	cp->serial = obj->serial;
388	cp->n_data_chunks = obj->n_data_chunks;
389
390	if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
391		cp->size_or_equiv_obj = obj->variant.file_variant.file_size;
392	else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK)
393		cp->size_or_equiv_obj = obj->variant.hardlink_variant.equiv_id;
394}
395
396static int taffs2_checkpt_obj_to_obj(yaffs_obj_t *obj, yaffs_checkpt_obj_t *cp)
397{
398
399	yaffs_obj_t *parent;
400
401	if (obj->variant_type != cp->variant_type) {
402		T(YAFFS_TRACE_ERROR, (TSTR("Checkpoint read object %d type %d "
403			TCONT("chunk %d does not match existing object type %d")
404			TENDSTR), cp->obj_id, cp->variant_type, cp->hdr_chunk,
405			obj->variant_type));
406		return 0;
407	}
408
409	obj->obj_id = cp->obj_id;
410
411	if (cp->parent_id)
412		parent = yaffs_find_or_create_by_number(
413					obj->my_dev,
414					cp->parent_id,
415					YAFFS_OBJECT_TYPE_DIRECTORY);
416	else
417		parent = NULL;
418
419	if (parent) {
420		if (parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
421			T(YAFFS_TRACE_ALWAYS, (TSTR("Checkpoint read object %d parent %d type %d"
422				TCONT(" chunk %d Parent type, %d, not directory")
423				TENDSTR),
424				cp->obj_id, cp->parent_id, cp->variant_type,
425				cp->hdr_chunk, parent->variant_type));
426			return 0;
427		}
428		yaffs_add_obj_to_dir(parent, obj);
429	}
430
431	obj->hdr_chunk = cp->hdr_chunk;
432	obj->variant_type = cp->variant_type;
433	obj->deleted = cp->deleted;
434	obj->soft_del = cp->soft_del;
435	obj->unlinked = cp->unlinked;
436	obj->fake = cp->fake;
437	obj->rename_allowed = cp->rename_allowed;
438	obj->unlink_allowed = cp->unlink_allowed;
439	obj->serial = cp->serial;
440	obj->n_data_chunks = cp->n_data_chunks;
441
442	if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
443		obj->variant.file_variant.file_size = cp->size_or_equiv_obj;
444	else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK)
445		obj->variant.hardlink_variant.equiv_id = cp->size_or_equiv_obj;
446
447	if (obj->hdr_chunk > 0)
448		obj->lazy_loaded = 1;
449	return 1;
450}
451
452
453
454static int yaffs2_checkpt_tnode_worker(yaffs_obj_t *in, yaffs_tnode_t *tn,
455					__u32 level, int chunk_offset)
456{
457	int i;
458	yaffs_dev_t *dev = in->my_dev;
459	int ok = 1;
460
461	if (tn) {
462		if (level > 0) {
463
464			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {
465				if (tn->internal[i]) {
466					ok = yaffs2_checkpt_tnode_worker(in,
467							tn->internal[i],
468							level - 1,
469							(chunk_offset<<YAFFS_TNODES_INTERNAL_BITS) + i);
470				}
471			}
472		} else if (level == 0) {
473			__u32 baseOffset = chunk_offset <<  YAFFS_TNODES_LEVEL0_BITS;
474			ok = (yaffs2_checkpt_wr(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset));
475			if (ok)
476				ok = (yaffs2_checkpt_wr(dev, tn, dev->tnode_size) == dev->tnode_size);
477		}
478	}
479
480	return ok;
481
482}
483
484static int yaffs2_wr_checkpt_tnodes(yaffs_obj_t *obj)
485{
486	__u32 endMarker = ~0;
487	int ok = 1;
488
489	if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) {
490		ok = yaffs2_checkpt_tnode_worker(obj,
491					    obj->variant.file_variant.top,
492					    obj->variant.file_variant.top_level,
493					    0);
494		if (ok)
495			ok = (yaffs2_checkpt_wr(obj->my_dev, &endMarker, sizeof(endMarker)) ==
496				sizeof(endMarker));
497	}
498
499	return ok ? 1 : 0;
500}
501
502static int yaffs2_rd_checkpt_tnodes(yaffs_obj_t *obj)
503{
504	__u32 baseChunk;
505	int ok = 1;
506	yaffs_dev_t *dev = obj->my_dev;
507	yaffs_file_s *fileStructPtr = &obj->variant.file_variant;
508	yaffs_tnode_t *tn;
509	int nread = 0;
510
511	ok = (yaffs2_checkpt_rd(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));
512
513	while (ok && (~baseChunk)) {
514		nread++;
515		/* Read level 0 tnode */
516
517
518		tn = yaffs_get_tnode(dev);
519		if (tn){
520			ok = (yaffs2_checkpt_rd(dev, tn, dev->tnode_size) == dev->tnode_size);
521		} else
522			ok = 0;
523
524		if (tn && ok)
525			ok = yaffs_add_find_tnode_0(dev,
526							fileStructPtr,
527							baseChunk,
528							tn) ? 1 : 0;
529
530		if (ok)
531			ok = (yaffs2_checkpt_rd(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));
532
533	}
534
535	T(YAFFS_TRACE_CHECKPOINT, (
536		TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR),
537		nread, baseChunk, ok));
538
539	return ok ? 1 : 0;
540}
541
542
543static int yaffs2_wr_checkpt_objs(yaffs_dev_t *dev)
544{
545	yaffs_obj_t *obj;
546	yaffs_checkpt_obj_t cp;
547	int i;
548	int ok = 1;
549	struct ylist_head *lh;
550
551
552	/* Iterate through the objects in each hash entry,
553	 * dumping them to the checkpointing stream.
554	 */
555
556	for (i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++) {
557		ylist_for_each(lh, &dev->obj_bucket[i].list) {
558			if (lh) {
559				obj = ylist_entry(lh, yaffs_obj_t, hash_link);
560				if (!obj->defered_free) {
561					yaffs2_obj_checkpt_obj(&cp, obj);
562					cp.struct_type = sizeof(cp);
563
564					T(YAFFS_TRACE_CHECKPOINT, (
565						TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %p" TENDSTR),
566						cp.obj_id, cp.parent_id, cp.variant_type, cp.hdr_chunk, obj));
567
568					ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
569
570					if (ok && obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
571						ok = yaffs2_wr_checkpt_tnodes(obj);
572				}
573			}
574		}
575	}
576
577	/* Dump end of list */
578	memset(&cp, 0xFF, sizeof(yaffs_checkpt_obj_t));
579	cp.struct_type = sizeof(cp);
580
581	if (ok)
582		ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
583
584	return ok ? 1 : 0;
585}
586
587static int yaffs2_rd_checkpt_objs(yaffs_dev_t *dev)
588{
589	yaffs_obj_t *obj;
590	yaffs_checkpt_obj_t cp;
591	int ok = 1;
592	int done = 0;
593	yaffs_obj_t *hard_list = NULL;
594
595	while (ok && !done) {
596		ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
597		if (cp.struct_type != sizeof(cp)) {
598			T(YAFFS_TRACE_CHECKPOINT, (TSTR("struct size %d instead of %d ok %d"TENDSTR),
599				cp.struct_type, (int)sizeof(cp), ok));
600			ok = 0;
601		}
602
603		T(YAFFS_TRACE_CHECKPOINT, (TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
604			cp.obj_id, cp.parent_id, cp.variant_type, cp.hdr_chunk));
605
606		if (ok && cp.obj_id == ~0)
607			done = 1;
608		else if (ok) {
609			obj = yaffs_find_or_create_by_number(dev, cp.obj_id, cp.variant_type);
610			if (obj) {
611				ok = taffs2_checkpt_obj_to_obj(obj, &cp);
612				if (!ok)
613					break;
614				if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) {
615					ok = yaffs2_rd_checkpt_tnodes(obj);
616				} else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
617					obj->hard_links.next =
618						(struct ylist_head *) hard_list;
619					hard_list = obj;
620				}
621			} else
622				ok = 0;
623		}
624	}
625
626	if (ok)
627		yaffs_link_fixup(dev, hard_list);
628
629	return ok ? 1 : 0;
630}
631
632static int yaffs2_wr_checkpt_sum(yaffs_dev_t *dev)
633{
634	__u32 checkpt_sum;
635	int ok;
636
637	yaffs2_get_checkpt_sum(dev, &checkpt_sum);
638
639	ok = (yaffs2_checkpt_wr(dev, &checkpt_sum, sizeof(checkpt_sum)) == sizeof(checkpt_sum));
640
641	if (!ok)
642		return 0;
643
644	return 1;
645}
646
647static int yaffs2_rd_checkpt_sum(yaffs_dev_t *dev)
648{
649	__u32 checkpt_sum0;
650	__u32 checkpt_sum1;
651	int ok;
652
653	yaffs2_get_checkpt_sum(dev, &checkpt_sum0);
654
655	ok = (yaffs2_checkpt_rd(dev, &checkpt_sum1, sizeof(checkpt_sum1)) == sizeof(checkpt_sum1));
656
657	if (!ok)
658		return 0;
659
660	if (checkpt_sum0 != checkpt_sum1)
661		return 0;
662
663	return 1;
664}
665
666
667static int yaffs2_wr_checkpt_data(yaffs_dev_t *dev)
668{
669	int ok = 1;
670
671	if (!yaffs2_checkpt_required(dev)) {
672		T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint write" TENDSTR)));
673		ok = 0;
674	}
675
676	if (ok)
677		ok = yaffs2_checkpt_open(dev, 1);
678
679	if (ok) {
680		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR)));
681		ok = yaffs2_wr_checkpt_validity_marker(dev, 1);
682	}
683	if (ok) {
684		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint device" TENDSTR)));
685		ok = yaffs2_wr_checkpt_dev(dev);
686	}
687	if (ok) {
688		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint objects" TENDSTR)));
689		ok = yaffs2_wr_checkpt_objs(dev);
690	}
691	if (ok) {
692		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR)));
693		ok = yaffs2_wr_checkpt_validity_marker(dev, 0);
694	}
695
696	if (ok)
697		ok = yaffs2_wr_checkpt_sum(dev);
698
699	if (!yaffs_checkpt_close(dev))
700		ok = 0;
701
702	if (ok)
703		dev->is_checkpointed = 1;
704	else
705		dev->is_checkpointed = 0;
706
707	return dev->is_checkpointed;
708}
709
710static int yaffs2_rd_checkpt_data(yaffs_dev_t *dev)
711{
712	int ok = 1;
713
714	if(!dev->param.is_yaffs2)
715		ok = 0;
716
717	if (ok && dev->param.skip_checkpt_rd) {
718		T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint read" TENDSTR)));
719		ok = 0;
720	}
721
722	if (ok)
723		ok = yaffs2_checkpt_open(dev, 0); /* open for read */
724
725	if (ok) {
726		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR)));
727		ok = yaffs2_rd_checkpt_validty_marker(dev, 1);
728	}
729	if (ok) {
730		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint device" TENDSTR)));
731		ok = yaffs2_rd_checkpt_dev(dev);
732	}
733	if (ok) {
734		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint objects" TENDSTR)));
735		ok = yaffs2_rd_checkpt_objs(dev);
736	}
737	if (ok) {
738		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR)));
739		ok = yaffs2_rd_checkpt_validty_marker(dev, 0);
740	}
741
742	if (ok) {
743		ok = yaffs2_rd_checkpt_sum(dev);
744		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint checksum %d" TENDSTR), ok));
745	}
746
747	if (!yaffs_checkpt_close(dev))
748		ok = 0;
749
750	if (ok)
751		dev->is_checkpointed = 1;
752	else
753		dev->is_checkpointed = 0;
754
755	return ok ? 1 : 0;
756
757}
758
759void yaffs2_checkpt_invalidate(yaffs_dev_t *dev)
760{
761	if (dev->is_checkpointed ||
762			dev->blocks_in_checkpt > 0) {
763		dev->is_checkpointed = 0;
764		yaffs2_checkpt_invalidate_stream(dev);
765	}
766	if (dev->param.sb_dirty_fn)
767		dev->param.sb_dirty_fn(dev);
768}
769
770
771int yaffs_checkpoint_save(yaffs_dev_t *dev)
772{
773
774	T(YAFFS_TRACE_CHECKPOINT, (TSTR("save entry: is_checkpointed %d"TENDSTR), dev->is_checkpointed));
775
776	yaffs_verify_objects(dev);
777	yaffs_verify_blocks(dev);
778	yaffs_verify_free_chunks(dev);
779
780	if (!dev->is_checkpointed) {
781		yaffs2_checkpt_invalidate(dev);
782		yaffs2_wr_checkpt_data(dev);
783	}
784
785	T(YAFFS_TRACE_ALWAYS, (TSTR("save exit: is_checkpointed %d"TENDSTR), dev->is_checkpointed));
786
787	return dev->is_checkpointed;
788}
789
790int yaffs2_checkpt_restore(yaffs_dev_t *dev)
791{
792	int retval;
793	T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore entry: is_checkpointed %d"TENDSTR), dev->is_checkpointed));
794
795	retval = yaffs2_rd_checkpt_data(dev);
796
797	if (dev->is_checkpointed) {
798		yaffs_verify_objects(dev);
799		yaffs_verify_blocks(dev);
800		yaffs_verify_free_chunks(dev);
801	}
802
803	T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore exit: is_checkpointed %d"TENDSTR), dev->is_checkpointed));
804
805	return retval;
806}
807
808int yaffs2_handle_hole(yaffs_obj_t *obj, loff_t new_size)
809{
810	/* if newsSize > oldFileSize.
811	 * We're going to be writing a hole.
812	 * If the hole is small then write zeros otherwise write a start of hole marker.
813	 */
814
815
816	loff_t oldFileSize;
817	int increase;
818	int smallHole   ;
819	int result = YAFFS_OK;
820	yaffs_dev_t *dev = NULL;
821
822	__u8 *localBuffer = NULL;
823
824	int smallIncreaseOk = 0;
825
826	if(!obj)
827		return YAFFS_FAIL;
828
829	if(obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
830		return YAFFS_FAIL;
831
832	dev = obj->my_dev;
833
834	/* Bail out if not yaffs2 mode */
835	if(!dev->param.is_yaffs2)
836		return YAFFS_OK;
837
838	oldFileSize = obj->variant.file_variant.file_size;
839
840	if (new_size <= oldFileSize)
841		return YAFFS_OK;
842
843	increase = new_size - oldFileSize;
844
845	if(increase < YAFFS_SMALL_HOLE_THRESHOLD * dev->data_bytes_per_chunk &&
846		yaffs_check_alloc_available(dev, YAFFS_SMALL_HOLE_THRESHOLD + 1))
847		smallHole = 1;
848	else
849		smallHole = 0;
850
851	if(smallHole)
852		localBuffer= yaffs_get_temp_buffer(dev, __LINE__);
853
854	if(localBuffer){
855		/* fill hole with zero bytes */
856		int pos = oldFileSize;
857		int thisWrite;
858		int written;
859		memset(localBuffer,0,dev->data_bytes_per_chunk);
860		smallIncreaseOk = 1;
861
862		while(increase > 0 && smallIncreaseOk){
863			thisWrite = increase;
864			if(thisWrite > dev->data_bytes_per_chunk)
865				thisWrite = dev->data_bytes_per_chunk;
866			written = yaffs_do_file_wr(obj,localBuffer,pos,thisWrite,0);
867			if(written == thisWrite){
868				pos += thisWrite;
869				increase -= thisWrite;
870			} else
871				smallIncreaseOk = 0;
872		}
873
874		yaffs_release_temp_buffer(dev,localBuffer,__LINE__);
875
876		/* If we were out of space then reverse any chunks we've added */
877		if(!smallIncreaseOk)
878			yaffs_resize_file_down(obj, oldFileSize);
879	}
880
881	if (!smallIncreaseOk &&
882		obj->parent &&
883		obj->parent->obj_id != YAFFS_OBJECTID_UNLINKED &&
884		obj->parent->obj_id != YAFFS_OBJECTID_DELETED){
885		/* Write a hole start header with the old file size */
886		yaffs_update_oh(obj, NULL, 0, 1, 0, NULL);
887	}
888
889	return result;
890
891}
892
893
894typedef struct {
895	int seq;
896	int block;
897} yaffs_BlockIndex;
898
899
900static int yaffs2_ybicmp(const void *a, const void *b)
901{
902	register int aseq = ((yaffs_BlockIndex *)a)->seq;
903	register int bseq = ((yaffs_BlockIndex *)b)->seq;
904	register int ablock = ((yaffs_BlockIndex *)a)->block;
905	register int bblock = ((yaffs_BlockIndex *)b)->block;
906	if (aseq == bseq)
907		return ablock - bblock;
908	else
909		return aseq - bseq;
910}
911
912int yaffs2_scan_backwards(yaffs_dev_t *dev)
913{
914	yaffs_ext_tags tags;
915	int blk;
916	int blockIterator;
917	int startIterator;
918	int endIterator;
919	int nBlocksToScan = 0;
920
921	int chunk;
922	int result;
923	int c;
924	int deleted;
925	yaffs_block_state_t state;
926	yaffs_obj_t *hard_list = NULL;
927	yaffs_block_info_t *bi;
928	__u32 seq_number;
929	yaffs_obj_header *oh;
930	yaffs_obj_t *in;
931	yaffs_obj_t *parent;
932	int nBlocks = dev->internal_end_block - dev->internal_start_block + 1;
933	int itsUnlinked;
934	__u8 *chunkData;
935
936	int file_size;
937	int is_shrink;
938	int foundChunksInBlock;
939	int equiv_id;
940	int alloc_failed = 0;
941
942
943	yaffs_BlockIndex *blockIndex = NULL;
944	int altBlockIndex = 0;
945
946	T(YAFFS_TRACE_SCAN,
947	  (TSTR
948	   ("yaffs2_scan_backwards starts  intstartblk %d intendblk %d..."
949	    TENDSTR), dev->internal_start_block, dev->internal_end_block));
950
951
952	dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
953
954	blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
955
956	if (!blockIndex) {
957		blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
958		altBlockIndex = 1;
959	}
960
961	if (!blockIndex) {
962		T(YAFFS_TRACE_SCAN,
963		  (TSTR("yaffs2_scan_backwards() could not allocate block index!" TENDSTR)));
964		return YAFFS_FAIL;
965	}
966
967	dev->blocks_in_checkpt = 0;
968
969	chunkData = yaffs_get_temp_buffer(dev, __LINE__);
970
971	/* Scan all the blocks to determine their state */
972	bi = dev->block_info;
973	for (blk = dev->internal_start_block; blk <= dev->internal_end_block; blk++) {
974		yaffs_clear_chunk_bits(dev, blk);
975		bi->pages_in_use = 0;
976		bi->soft_del_pages = 0;
977
978		yaffs_query_init_block_state(dev, blk, &state, &seq_number);
979
980		bi->block_state = state;
981		bi->seq_number = seq_number;
982
983		if (bi->seq_number == YAFFS_SEQUENCE_CHECKPOINT_DATA)
984			bi->block_state = state = YAFFS_BLOCK_STATE_CHECKPOINT;
985		if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK)
986			bi->block_state = state = YAFFS_BLOCK_STATE_DEAD;
987
988		T(YAFFS_TRACE_SCAN_DEBUG,
989		  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
990		   state, seq_number));
991
992
993		if (state == YAFFS_BLOCK_STATE_CHECKPOINT) {
994			dev->blocks_in_checkpt++;
995
996		} else if (state == YAFFS_BLOCK_STATE_DEAD) {
997			T(YAFFS_TRACE_BAD_BLOCKS,
998			  (TSTR("block %d is bad" TENDSTR), blk));
999		} else if (state == YAFFS_BLOCK_STATE_EMPTY) {
1000			T(YAFFS_TRACE_SCAN_DEBUG,
1001			  (TSTR("Block empty " TENDSTR)));
1002			dev->n_erased_blocks++;
1003			dev->n_free_chunks += dev->param.chunks_per_block;
1004		} else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
1005
1006			/* Determine the highest sequence number */
1007			if (seq_number >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
1008			    seq_number < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
1009
1010				blockIndex[nBlocksToScan].seq = seq_number;
1011				blockIndex[nBlocksToScan].block = blk;
1012
1013				nBlocksToScan++;
1014
1015				if (seq_number >= dev->seq_number)
1016					dev->seq_number = seq_number;
1017			} else {
1018				/* TODO: Nasty sequence number! */
1019				T(YAFFS_TRACE_SCAN,
1020				  (TSTR
1021				   ("Block scanning block %d has bad sequence number %d"
1022				    TENDSTR), blk, seq_number));
1023
1024			}
1025		}
1026		bi++;
1027	}
1028
1029	T(YAFFS_TRACE_SCAN,
1030	(TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan));
1031
1032
1033
1034	YYIELD();
1035
1036	/* Sort the blocks by sequence number*/
1037	yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), yaffs2_ybicmp);
1038
1039	YYIELD();
1040
1041	T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR)));
1042
1043	/* Now scan the blocks looking at the data. */
1044	startIterator = 0;
1045	endIterator = nBlocksToScan - 1;
1046	T(YAFFS_TRACE_SCAN_DEBUG,
1047	  (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
1048
1049	/* For each block.... backwards */
1050	for (blockIterator = endIterator; !alloc_failed && blockIterator >= startIterator;
1051			blockIterator--) {
1052		/* Cooperative multitasking! This loop can run for so
1053		   long that watchdog timers expire. */
1054		YYIELD();
1055
1056		/* get the block to scan in the correct order */
1057		blk = blockIndex[blockIterator].block;
1058
1059		bi = yaffs_get_block_info(dev, blk);
1060
1061
1062		state = bi->block_state;
1063
1064		deleted = 0;
1065
1066		/* For each chunk in each block that needs scanning.... */
1067		foundChunksInBlock = 0;
1068		for (c = dev->param.chunks_per_block - 1;
1069		     !alloc_failed && c >= 0 &&
1070		     (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
1071		      state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
1072			/* Scan backwards...
1073			 * Read the tags and decide what to do
1074			 */
1075
1076			chunk = blk * dev->param.chunks_per_block + c;
1077
1078			result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL,
1079							&tags);
1080
1081			/* Let's have a good look at this chunk... */
1082
1083			if (!tags.chunk_used) {
1084				/* An unassigned chunk in the block.
1085				 * If there are used chunks after this one, then
1086				 * it is a chunk that was skipped due to failing the erased
1087				 * check. Just skip it so that it can be deleted.
1088				 * But, more typically, We get here when this is an unallocated
1089				 * chunk and his means that either the block is empty or
1090				 * this is the one being allocated from
1091				 */
1092
1093				if (foundChunksInBlock) {
1094					/* This is a chunk that was skipped due to failing the erased check */
1095				} else if (c == 0) {
1096					/* We're looking at the first chunk in the block so the block is unused */
1097					state = YAFFS_BLOCK_STATE_EMPTY;
1098					dev->n_erased_blocks++;
1099				} else {
1100					if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
1101					    state == YAFFS_BLOCK_STATE_ALLOCATING) {
1102						if (dev->seq_number == bi->seq_number) {
1103							/* this is the block being allocated from */
1104
1105							T(YAFFS_TRACE_SCAN,
1106							  (TSTR
1107							   (" Allocating from %d %d"
1108							    TENDSTR), blk, c));
1109
1110							state = YAFFS_BLOCK_STATE_ALLOCATING;
1111							dev->alloc_block = blk;
1112							dev->alloc_page = c;
1113							dev->alloc_block_finder = blk;
1114						} else {
1115							/* This is a partially written block that is not
1116							 * the current allocation block.
1117							 */
1118
1119							 T(YAFFS_TRACE_SCAN,
1120							 (TSTR("Partially written block %d detected" TENDSTR),
1121							 blk));
1122						}
1123					}
1124				}
1125
1126				dev->n_free_chunks++;
1127
1128			} else if (tags.ecc_result == YAFFS_ECC_RESULT_UNFIXED) {
1129				T(YAFFS_TRACE_SCAN,
1130				  (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR),
1131				  blk, c));
1132
1133				  dev->n_free_chunks++;
1134
1135			} else if (tags.obj_id > YAFFS_MAX_OBJECT_ID ||
1136				tags.chunk_id > YAFFS_MAX_CHUNK_ID ||
1137				(tags.chunk_id > 0 && tags.n_bytes > dev->data_bytes_per_chunk) ||
1138				tags.seq_number != bi->seq_number ) {
1139				T(YAFFS_TRACE_SCAN,
1140				  (TSTR("Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored"TENDSTR),
1141				  blk, c,tags.obj_id, tags.chunk_id, tags.n_bytes));
1142
1143				  dev->n_free_chunks++;
1144
1145			} else if (tags.chunk_id > 0) {
1146				/* chunk_id > 0 so it is a data chunk... */
1147				unsigned int endpos;
1148				__u32 chunkBase =
1149				    (tags.chunk_id - 1) * dev->data_bytes_per_chunk;
1150
1151				foundChunksInBlock = 1;
1152
1153
1154				yaffs_set_chunk_bit(dev, blk, c);
1155				bi->pages_in_use++;
1156
1157				in = yaffs_find_or_create_by_number(dev,
1158								      tags.
1159								      obj_id,
1160								      YAFFS_OBJECT_TYPE_FILE);
1161				if (!in) {
1162					/* Out of memory */
1163					alloc_failed = 1;
1164				}
1165
1166				if (in &&
1167				    in->variant_type == YAFFS_OBJECT_TYPE_FILE
1168				    && chunkBase < in->variant.file_variant.shrink_size) {
1169					/* This has not been invalidated by a resize */
1170					if (!yaffs_put_chunk_in_file(in, tags.chunk_id, chunk, -1)) {
1171						alloc_failed = 1;
1172					}
1173
1174					/* File size is calculated by looking at the data chunks if we have not
1175					 * seen an object header yet. Stop this practice once we find an object header.
1176					 */
1177					endpos = chunkBase + tags.n_bytes;
1178
1179					if (!in->valid &&	/* have not got an object header yet */
1180					    in->variant.file_variant.scanned_size < endpos) {
1181						in->variant.file_variant.scanned_size = endpos;
1182						in->variant.file_variant.file_size = endpos;
1183					}
1184
1185				} else if (in) {
1186					/* This chunk has been invalidated by a resize, or a past file deletion
1187					 * so delete the chunk*/
1188					yaffs_chunk_del(dev, chunk, 1, __LINE__);
1189
1190				}
1191			} else {
1192				/* chunk_id == 0, so it is an ObjectHeader.
1193				 * Thus, we read in the object header and make the object
1194				 */
1195				foundChunksInBlock = 1;
1196
1197				yaffs_set_chunk_bit(dev, blk, c);
1198				bi->pages_in_use++;
1199
1200				oh = NULL;
1201				in = NULL;
1202
1203				if (tags.extra_available) {
1204					in = yaffs_find_or_create_by_number(dev,
1205						tags.obj_id,
1206						tags.extra_obj_type);
1207					if (!in)
1208						alloc_failed = 1;
1209				}
1210
1211				if (!in ||
1212				    (!in->valid && dev->param.disable_lazy_load) ||
1213				    tags.extra_shadows ||
1214				    (!in->valid &&
1215				    (tags.obj_id == YAFFS_OBJECTID_ROOT ||
1216				     tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND))) {
1217
1218					/* If we don't have  valid info then we need to read the chunk
1219					 * TODO In future we can probably defer reading the chunk and
1220					 * living with invalid data until needed.
1221					 */
1222
1223					result = yaffs_rd_chunk_tags_nand(dev,
1224									chunk,
1225									chunkData,
1226									NULL);
1227
1228					oh = (yaffs_obj_header *) chunkData;
1229
1230					if (dev->param.inband_tags) {
1231						/* Fix up the header if they got corrupted by inband tags */
1232						oh->shadows_obj = oh->inband_shadowed_obj_id;
1233						oh->is_shrink = oh->inband_is_shrink;
1234					}
1235
1236					if (!in) {
1237						in = yaffs_find_or_create_by_number(dev, tags.obj_id, oh->type);
1238						if (!in)
1239							alloc_failed = 1;
1240					}
1241
1242				}
1243
1244				if (!in) {
1245					/* TODO Hoosterman we have a problem! */
1246					T(YAFFS_TRACE_ERROR,
1247					  (TSTR
1248					   ("yaffs tragedy: Could not make object for object  %d at chunk %d during scan"
1249					    TENDSTR), tags.obj_id, chunk));
1250					continue;
1251				}
1252
1253				if (in->valid) {
1254					/* We have already filled this one.
1255					 * We have a duplicate that will be discarded, but
1256					 * we first have to suck out resize info if it is a file.
1257					 */
1258
1259					if ((in->variant_type == YAFFS_OBJECT_TYPE_FILE) &&
1260					     ((oh &&
1261					       oh->type == YAFFS_OBJECT_TYPE_FILE) ||
1262					      (tags.extra_available  &&
1263					       tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE))) {
1264						__u32 thisSize =
1265						    (oh) ? oh->file_size : tags.
1266						    extra_length;
1267						__u32 parent_obj_id =
1268						    (oh) ? oh->
1269						    parent_obj_id : tags.
1270						    extra_parent_id;
1271
1272
1273						is_shrink =
1274						    (oh) ? oh->is_shrink : tags.
1275						    extra_is_shrink;
1276
1277						/* If it is deleted (unlinked at start also means deleted)
1278						 * we treat the file size as being zeroed at this point.
1279						 */
1280						if (parent_obj_id ==
1281						    YAFFS_OBJECTID_DELETED
1282						    || parent_obj_id ==
1283						    YAFFS_OBJECTID_UNLINKED) {
1284							thisSize = 0;
1285							is_shrink = 1;
1286						}
1287
1288						if (is_shrink && in->variant.file_variant.shrink_size > thisSize)
1289							in->variant.file_variant.shrink_size = thisSize;
1290
1291						if (is_shrink)
1292							bi->has_shrink_hdr = 1;
1293
1294					}
1295					/* Use existing - destroy this one. */
1296					yaffs_chunk_del(dev, chunk, 1, __LINE__);
1297
1298				}
1299
1300				if (!in->valid && in->variant_type !=
1301				    (oh ? oh->type : tags.extra_obj_type))
1302					T(YAFFS_TRACE_ERROR, (
1303						TSTR("yaffs tragedy: Bad object type, "
1304					    TCONT("%d != %d, for object %d at chunk ")
1305					    TCONT("%d during scan")
1306						TENDSTR), oh ?
1307					    oh->type : tags.extra_obj_type,
1308					    in->variant_type, tags.obj_id,
1309					    chunk));
1310
1311				if (!in->valid &&
1312				    (tags.obj_id == YAFFS_OBJECTID_ROOT ||
1313				     tags.obj_id ==
1314				     YAFFS_OBJECTID_LOSTNFOUND)) {
1315					/* We only load some info, don't fiddle with directory structure */
1316					in->valid = 1;
1317
1318					if (oh) {
1319
1320						in->yst_mode = oh->yst_mode;
1321#ifdef CONFIG_YAFFS_WINCE
1322						in->win_atime[0] = oh->win_atime[0];
1323						in->win_ctime[0] = oh->win_ctime[0];
1324						in->win_mtime[0] = oh->win_mtime[0];
1325						in->win_atime[1] = oh->win_atime[1];
1326						in->win_ctime[1] = oh->win_ctime[1];
1327						in->win_mtime[1] = oh->win_mtime[1];
1328#else
1329						in->yst_uid = oh->yst_uid;
1330						in->yst_gid = oh->yst_gid;
1331						in->yst_atime = oh->yst_atime;
1332						in->yst_mtime = oh->yst_mtime;
1333						in->yst_ctime = oh->yst_ctime;
1334						in->yst_rdev = oh->yst_rdev;
1335
1336						in->lazy_loaded = 0;
1337
1338#endif
1339					} else
1340						in->lazy_loaded = 1;
1341
1342					in->hdr_chunk = chunk;
1343
1344				} else if (!in->valid) {
1345					/* we need to load this info */
1346
1347					in->valid = 1;
1348					in->hdr_chunk = chunk;
1349
1350					if (oh) {
1351						in->variant_type = oh->type;
1352
1353						in->yst_mode = oh->yst_mode;
1354#ifdef CONFIG_YAFFS_WINCE
1355						in->win_atime[0] = oh->win_atime[0];
1356						in->win_ctime[0] = oh->win_ctime[0];
1357						in->win_mtime[0] = oh->win_mtime[0];
1358						in->win_atime[1] = oh->win_atime[1];
1359						in->win_ctime[1] = oh->win_ctime[1];
1360						in->win_mtime[1] = oh->win_mtime[1];
1361#else
1362						in->yst_uid = oh->yst_uid;
1363						in->yst_gid = oh->yst_gid;
1364						in->yst_atime = oh->yst_atime;
1365						in->yst_mtime = oh->yst_mtime;
1366						in->yst_ctime = oh->yst_ctime;
1367						in->yst_rdev = oh->yst_rdev;
1368#endif
1369
1370						if (oh->shadows_obj > 0)
1371							yaffs_handle_shadowed_obj(dev,
1372									   oh->
1373									   shadows_obj,
1374									   1);
1375
1376
1377
1378						yaffs_set_obj_name_from_oh(in, oh);
1379						parent =
1380						    yaffs_find_or_create_by_number
1381							(dev, oh->parent_obj_id,
1382							 YAFFS_OBJECT_TYPE_DIRECTORY);
1383
1384						 file_size = oh->file_size;
1385						 is_shrink = oh->is_shrink;
1386						 equiv_id = oh->equiv_id;
1387
1388					} else {
1389						in->variant_type = tags.extra_obj_type;
1390						parent =
1391						    yaffs_find_or_create_by_number
1392							(dev, tags.extra_parent_id,
1393							 YAFFS_OBJECT_TYPE_DIRECTORY);
1394						 file_size = tags.extra_length;
1395						 is_shrink = tags.extra_is_shrink;
1396						 equiv_id = tags.extra_equiv_id;
1397						in->lazy_loaded = 1;
1398
1399					}
1400					in->dirty = 0;
1401
1402					if (!parent)
1403						alloc_failed = 1;
1404
1405					/* directory stuff...
1406					 * hook up to parent
1407					 */
1408
1409					if (parent && parent->variant_type ==
1410					    YAFFS_OBJECT_TYPE_UNKNOWN) {
1411						/* Set up as a directory */
1412						parent->variant_type =
1413							YAFFS_OBJECT_TYPE_DIRECTORY;
1414						YINIT_LIST_HEAD(&parent->variant.
1415							dir_variant.
1416							children);
1417					} else if (!parent || parent->variant_type !=
1418						   YAFFS_OBJECT_TYPE_DIRECTORY) {
1419						/* Hoosterman, another problem....
1420						 * We're trying to use a non-directory as a directory
1421						 */
1422
1423						T(YAFFS_TRACE_ERROR,
1424						  (TSTR
1425						   ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
1426						    TENDSTR)));
1427						parent = dev->lost_n_found;
1428					}
1429
1430					yaffs_add_obj_to_dir(parent, in);
1431
1432					itsUnlinked = (parent == dev->del_dir) ||
1433						      (parent == dev->unlinked_dir);
1434
1435					if (is_shrink) {
1436						/* Mark the block as having a shrinkHeader */
1437						bi->has_shrink_hdr = 1;
1438					}
1439
1440					/* Note re hardlinks.
1441					 * Since we might scan a hardlink before its equivalent object is scanned
1442					 * we put them all in a list.
1443					 * After scanning is complete, we should have all the objects, so we run
1444					 * through this list and fix up all the chains.
1445					 */
1446
1447					switch (in->variant_type) {
1448					case YAFFS_OBJECT_TYPE_UNKNOWN:
1449						/* Todo got a problem */
1450						break;
1451					case YAFFS_OBJECT_TYPE_FILE:
1452
1453						if (in->variant.file_variant.
1454						    scanned_size < file_size) {
1455							/* This covers the case where the file size is greater
1456							 * than where the data is
1457							 * This will happen if the file is resized to be larger
1458							 * than its current data extents.
1459							 */
1460							in->variant.file_variant.file_size = file_size;
1461							in->variant.file_variant.scanned_size = file_size;
1462						}
1463
1464						if (in->variant.file_variant.shrink_size > file_size)
1465							in->variant.file_variant.shrink_size = file_size;
1466
1467
1468						break;
1469					case YAFFS_OBJECT_TYPE_HARDLINK:
1470						if (!itsUnlinked) {
1471							in->variant.hardlink_variant.equiv_id =
1472								equiv_id;
1473							in->hard_links.next =
1474								(struct ylist_head *) hard_list;
1475							hard_list = in;
1476						}
1477						break;
1478					case YAFFS_OBJECT_TYPE_DIRECTORY:
1479						/* Do nothing */
1480						break;
1481					case YAFFS_OBJECT_TYPE_SPECIAL:
1482						/* Do nothing */
1483						break;
1484					case YAFFS_OBJECT_TYPE_SYMLINK:
1485						if (oh) {
1486							in->variant.symlink_variant.alias =
1487								yaffs_clone_str(oh->alias);
1488							if (!in->variant.symlink_variant.alias)
1489								alloc_failed = 1;
1490						}
1491						break;
1492					}
1493
1494				}
1495
1496			}
1497
1498		} /* End of scanning for each chunk */
1499
1500		if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
1501			/* If we got this far while scanning, then the block is fully allocated. */
1502			state = YAFFS_BLOCK_STATE_FULL;
1503		}
1504
1505
1506		bi->block_state = state;
1507
1508		/* Now let's see if it was dirty */
1509		if (bi->pages_in_use == 0 &&
1510		    !bi->has_shrink_hdr &&
1511		    bi->block_state == YAFFS_BLOCK_STATE_FULL) {
1512			yaffs_block_became_dirty(dev, blk);
1513		}
1514
1515	}
1516
1517	yaffs_skip_rest_of_block(dev);
1518
1519	if (altBlockIndex)
1520		YFREE_ALT(blockIndex);
1521	else
1522		YFREE(blockIndex);
1523
1524	/* Ok, we've done all the scanning.
1525	 * Fix up the hard link chains.
1526	 * We should now have scanned all the objects, now it's time to add these
1527	 * hardlinks.
1528	 */
1529	yaffs_link_fixup(dev, hard_list);
1530
1531
1532	yaffs_release_temp_buffer(dev, chunkData, __LINE__);
1533
1534	if (alloc_failed)
1535		return YAFFS_FAIL;
1536
1537	T(YAFFS_TRACE_SCAN, (TSTR("yaffs2_scan_backwards ends" TENDSTR)));
1538
1539	return YAFFS_OK;
1540}
1541