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