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