140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * YAFFS: Yet another FFS. A NAND-flash specific file system.
340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd.
540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   for Toby Churchill Ltd and Brightstar Engineering
640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Created by Charles Manning <charles@aleph1.co.uk>
840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This program is free software; you can redistribute it and/or modify
1040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * it under the terms of the GNU General Public License version 2 as
1140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * published by the Free Software Foundation.
1240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectconst char *yaffs_guts_c_version =
1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    "$Id: yaffs_guts.c,v 1.40 2006/10/13 08:52:49 charles Exp $";
1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yportenv.h"
1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffsinterface.h"
2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_guts.h"
2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_tagsvalidity.h"
2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_tagscompat.h"
2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifndef CONFIG_YAFFS_OWN_SORT
2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_qsort.h"
2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_nand.h"
2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_checkptrw.h"
3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_nand.h"
3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_packedtags2.h"
3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yfsd_LockYAFFS(BOOL fsLockOnly);
3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yfsd_UnlockYAFFS(BOOL fsLockOnly);
3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define YAFFS_PASSIVE_GC_CHUNKS 2
4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_ecc.h"
4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Robustification (if it ever comes about...) */
4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND);
4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk);
4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const __u8 * data,
5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const yaffs_ExtendedTags * tags);
5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    const yaffs_ExtendedTags * tags);
5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Other local prototypes */
5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_UnlinkObject( yaffs_Object *obj);
5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj);
5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList);
6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev,
6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     const __u8 * buffer,
6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     yaffs_ExtendedTags * tags,
6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     int useReserve);
6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  int chunkInNAND, int inScan);
6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   yaffs_ObjectType type);
7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_AddObjectToDirectory(yaffs_Object * directory,
7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       yaffs_Object * obj);
7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name,
7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    int force, int isShrink, int shadows);
7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj);
7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckStructures(void);
7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,
7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      int chunkOffset, int *limit);
7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_DoGenericObjectDeletion(yaffs_Object * in);
7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    int lineNo);
8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  int chunkInNAND);
8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_UnlinkWorker(yaffs_Object * obj);
9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_DestroyObject(yaffs_Object * obj);
9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,
9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   int chunkInObject);
9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectloff_t yaffs_GetFileSize(yaffs_Object * obj);
9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr);
9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_VerifyFreeChunks(yaffs_Device * dev);
10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef YAFFS_PARANOID
10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckFileSanity(yaffs_Object * in);
10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define yaffs_CheckFileSanity(in)
10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InvalidateWholeChunkCache(yaffs_Object * in);
10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId);
10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InvalidateCheckpoint(yaffs_Device *dev);
11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Function to calculate chunk and offset */
11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(dev->chunkShift){
11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Easy-peasy power of 2 case */
12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*chunk  = (__u32)(addr >> dev->chunkShift);
12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*offset = (__u32)(addr & dev->chunkMask);
12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if(dev->crumbsPerChunk)
12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Case where we're using "crumbs" */
12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*offset = (__u32)(addr & dev->crumbMask);
12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		addr >>= dev->crumbShift;
12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*chunk = ((__u32)addr)/dev->crumbsPerChunk;
12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Function to return the number of shifts for a power of 2 greater than or equal
13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * to the given number
13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Note we don't try to cater for all possible numbers and this does not have to
13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * be hellishly efficient.
13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic __u32 ShiftsGE(__u32 x)
14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int extraBits;
14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nShifts;
14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nShifts = extraBits = 0;
14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while(x>1){
14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(x & 1) extraBits++;
15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x>>=1;
15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nShifts++;
15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(extraBits)
15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nShifts++;
15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nShifts;
15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Function to return the number of shifts to get a 1 in bit 0
16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic __u32 ShiftDiv(__u32 x)
16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nShifts;
16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nShifts =  0;
16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!x) return 0;
17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while( !(x&1)){
17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x>>=1;
17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nShifts++;
17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nShifts;
17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Temporary buffer manipulations.
18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i, j;
18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->tempBuffer[i].line == 0) {
19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->tempBuffer[i].line = lineNo;
19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if ((i + 1) > dev->maxTemp) {
19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->maxTemp = i + 1;
19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				for (j = 0; j <= i; j++)
19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->tempBuffer[j].maxLine =
19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    dev->tempBuffer[j].line;
19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return dev->tempBuffer[i].buffer;
19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_BUFFERS,
20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("Out of temp buffers at line %d, other held by lines:"),
20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   lineNo));
20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_BUFFERS, (TSTR(" %d "), dev->tempBuffer[i].line));
20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR)));
20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/*
21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * If we got here then we have to allocate an unmanaged one
21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * This is not good.
21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->unmanagedTempAllocations++;
21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YMALLOC(dev->nDataBytesPerChunk);
21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    int lineNo)
22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->tempBuffer[i].buffer == buffer) {
22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->tempBuffer[i].line = 0;
22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return;
22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (buffer) {
23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* assume it is an unmanaged one. */
23340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_BUFFERS,
23440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR),
23540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   lineNo));
23640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(buffer);
23740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->unmanagedTempDeallocations++;
23840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
23940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
24140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
24340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Determine if we have a managed buffer.
24440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
24540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer)
24640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
24740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
24840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
24940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->tempBuffer[i].buffer == buffer)
25040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return 1;
25140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
25340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    for (i = 0; i < dev->nShortOpCaches; i++) {
25540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project        if( dev->srCache[i].data == buffer )
25640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project            return 1;
25740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    }
25940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    if (buffer == dev->checkpointBuffer)
26140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project      return 1;
26240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    T(YAFFS_TRACE_ALWAYS,
26440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR)));
26540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    return 0;
26640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
26740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
26940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Chunk bitmap manipulations
27040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
27140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device * dev, int blk)
27340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
27440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
27540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERROR,
27640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),
27740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   blk));
27840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
27940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
28040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return dev->chunkBits +
28140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    (dev->chunkBitmapStride * (blk - dev->internalStartBlock));
28240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
28340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk)
28540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
28640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *blkBits = yaffs_BlockBits(dev, blk);
28740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	memset(blkBits, 0, dev->chunkBitmapStride);
28940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
29040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic Y_INLINE void yaffs_ClearChunkBit(yaffs_Device * dev, int blk, int chunk)
29240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
29340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *blkBits = yaffs_BlockBits(dev, blk);
29440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blkBits[chunk / 8] &= ~(1 << (chunk & 7));
29640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
29740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk)
29940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
30040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *blkBits = yaffs_BlockBits(dev, blk);
30140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blkBits[chunk / 8] |= (1 << (chunk & 7));
30340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
30440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk)
30640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
30740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *blkBits = yaffs_BlockBits(dev, blk);
30840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
30940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
31040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
31140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk)
31240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
31340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *blkBits = yaffs_BlockBits(dev, blk);
31440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
31540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < dev->chunkBitmapStride; i++) {
31640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (*blkBits)
31740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return 1;
31840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blkBits++;
31940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
32040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
32140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
32240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
32440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *  Simple hash function. Needs to have a reasonable spread
32540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
32640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic Y_INLINE int yaffs_HashFunction(int n)
32840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
32940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	n = abs(n);
33040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return (n % YAFFS_NOBJECT_BUCKETS);
33140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
33240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
33440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Access functions to useful fake objects
33540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
33640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_Root(yaffs_Device * dev)
33840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
33940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return dev->rootDir;
34040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
34140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_LostNFound(yaffs_Device * dev)
34340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
34440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return dev->lostNFoundDir;
34540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
34640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
34940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *  Erased NAND checking functions
35040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
35140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
35240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckFF(__u8 * buffer, int nBytes)
35340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
35440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Horrible, slow implementation */
35540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (nBytes--) {
35640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (*buffer != 0xFF)
35740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return 0;
35840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		buffer++;
35940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
36040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
36140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
36240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
36440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  int chunkInNAND)
36540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
36640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retval = YAFFS_OK;
36840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *data = yaffs_GetTempBuffer(dev, __LINE__);
36940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
37040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int result;
37140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
37340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
37540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retval = YAFFS_FAIL;
37640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
37940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_NANDACCESS,
38040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND));
38140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retval = YAFFS_FAIL;
38240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
38340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
38440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ReleaseTempBuffer(dev, data, __LINE__);
38540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
38640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retval;
38740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
38840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
38940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
39040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
39140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     const __u8 * data,
39240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     yaffs_ExtendedTags * tags,
39340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     int useReserve)
39440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
39540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunk;
39640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
39740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int writeOk = 0;
39840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int erasedOk = 1;
39940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int attempts = 0;
40040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
40140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
40240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InvalidateCheckpoint(dev);
40340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
40440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	do {
40540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		chunk = yaffs_AllocateChunk(dev, useReserve,&bi);
40640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
40740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (chunk >= 0) {
40840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* First check this chunk is erased, if it needs checking.
40940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * The checking policy (unless forced always on) is as follows:
41040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * Check the first page we try to write in a block.
41140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * - If the check passes then we don't need to check any more.
41240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * - If the check fails, we check again...
41340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * If the block has been erased, we don't need to check.
41440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 *
41540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * However, if the block has been prioritised for gc, then
41640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * we think there might be something odd about this block
41740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * and stop using it.
41840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 *
41940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * Rationale:
42040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * We should only ever see chunks that have not been erased
42140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * if there was a partially written chunk due to power loss
42240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * This checking policy should catch that case with very
42340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * few checks and thus save a lot of checks that are most likely not
42440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * needed.
42540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
42640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
42740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 if(bi->gcPrioritise){
42840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 		yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
42940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
43040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
43140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				bi->skipErasedCheck = 0;
43340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
43540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if(!bi->skipErasedCheck){
43640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					erasedOk = yaffs_CheckChunkErased(dev, chunk);
43740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if(erasedOk && !bi->gcPrioritise)
43840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						bi->skipErasedCheck = 1;
43940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
44040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
44140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!erasedOk) {
44240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					T(YAFFS_TRACE_ERROR,
44340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  (TSTR
44440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   ("**>> yaffs chunk %d was not erased"
44540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    TENDSTR), chunk));
44640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else {
44740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					writeOk =
44840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    yaffs_WriteChunkWithTagsToNAND(dev, chunk,
44940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									   data, tags);
45040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
45140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
45240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				attempts++;
45340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
45440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (writeOk) {
45540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/*
45640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 *  Copy the data into the robustification buffer.
45740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 *  NB We do this at the end to prevent duplicates in the case of a write error.
45840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 *  Todo
45940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
46040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
46140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
46240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else {
46340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* The erased check or write failed */
46440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_HandleWriteChunkError(dev, chunk, erasedOk);
46540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
46640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
46740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
46840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
46940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} while (chunk >= 0 && !writeOk);
47040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
47140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (attempts > 1) {
47240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERROR,
47340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("**>> yaffs write required %d attempts" TENDSTR),
47440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   attempts));
47540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nRetriedWrites += (attempts - 1);
47640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
47740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
47840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return chunk;
47940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
48040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
48240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Block retiring for handling a broken block.
48340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
48440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
48640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
48740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InvalidateCheckpoint(dev);
48940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_MarkBlockBad(dev, blockInNAND);
49140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_GetBlockInfo(dev, blockInNAND)->blockState =
49340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    YAFFS_BLOCK_STATE_DEAD;
49440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nRetiredBlocks++;
49640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
49740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
49940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Functions for robustisizing TODO
50040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
50140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
50240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
50340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
50440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const __u8 * data,
50540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const yaffs_ExtendedTags * tags)
50640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
50740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
50840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
50940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
51040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    const yaffs_ExtendedTags * tags)
51140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
51240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
51340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
51440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi)
51540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
51640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!bi->gcPrioritise){
51740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->gcPrioritise = 1;
51840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->hasPendingPrioritisedGCs = 1;
51940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->chunkErrorStrikes ++;
52040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
52140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(bi->chunkErrorStrikes > 3){
52240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bi->needsRetiring = 1; /* Too many stikes, so retire this */
52340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
52440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
52540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
52640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
52740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
52840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
52940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
53040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk)
53140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
53240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
53340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
53440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
53540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
53640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_HandleChunkError(dev,bi);
53740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
53840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
53940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(erasedOk ) {
54040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Was an actual write failure, so mark the block for retirement  */
54140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->needsRetiring = 1;
54240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
54340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
54440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
54540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Delete the chunk */
54640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
54740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
54840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
54940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
55040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*---------------- Name handling functions ------------*/
55140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
55240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic __u16 yaffs_CalcNameSum(const YCHAR * name)
55340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
55440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u16 sum = 0;
55540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u16 i = 1;
55640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
55740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YUCHAR *bname = (YUCHAR *) name;
55840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (bname) {
55940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		while ((*bname) && (i <= YAFFS_MAX_NAME_LENGTH)) {
56040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
56140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
56240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			sum += yaffs_toupper(*bname) * i;
56340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
56440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			sum += (*bname) * i;
56540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
56640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			i++;
56740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bname++;
56840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
56940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
57040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return sum;
57140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
57240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
57440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
57540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
57640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
57740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_strcpy(obj->shortName, name);
57840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
57940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->shortName[0] = _Y('\0');
58040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
58140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
58240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->sum = yaffs_CalcNameSum(name);
58340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
58440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
58540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*-------------------- TNODES -------------------
58640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
58740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * List of spare tnodes
58840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * The list is hooked together using the first pointer
58940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * in the tnode.
59040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
59140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
59240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* yaffs_CreateTnodes creates a bunch more tnodes and
59340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * adds them to the tnode free list.
59440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Don't use this function directly
59540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
59640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
59740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)
59840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
59940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
60040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int tnodeSize;
60140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *newTnodes;
60240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *mem;
60340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *curr;
60440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *next;
60540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_TnodeList *tnl;
60640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
60740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (nTnodes < 1)
60840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
60940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
61040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Calculate the tnode size in bytes for variable width tnode support.
61140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Must be a multiple of 32-bits  */
61240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
61340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
61440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* make these things */
61540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
61640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newTnodes = YMALLOC(nTnodes * tnodeSize);
61740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mem = (__u8 *)newTnodes;
61840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
61940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!newTnodes) {
62040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERROR,
62140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
62240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
62340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
62440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
62540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Hook them into the free list */
62640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if 0
62740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < nTnodes - 1; i++) {
62840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTnodes[i].internal[0] = &newTnodes[i + 1];
62940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
63040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
63140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
63240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
63340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
63440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;
63540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
63640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
63740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
63840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeTnodes = newTnodes;
63940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
64040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* New hookup for wide tnodes */
64140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i = 0; i < nTnodes -1; i++) {
64240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		curr = (yaffs_Tnode *) &mem[i * tnodeSize];
64340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
64440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		curr->internal[0] = next;
64540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
64640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
64740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
64840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	curr->internal[0] = dev->freeTnodes;
64940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeTnodes = (yaffs_Tnode *)mem;
65040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
65140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
65240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
65340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
65440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeTnodes += nTnodes;
65540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nTnodesCreated += nTnodes;
65640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
65740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now add this bunch of tnodes to a list for freeing up.
65840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * NB If we can't add this to the management list it isn't fatal
65940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * but it just means we can't free this bunch of tnodes later.
66040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
66140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
66240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tnl = YMALLOC(sizeof(yaffs_TnodeList));
66340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!tnl) {
66440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERROR,
66540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
66640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("yaffs: Could not add tnodes to management list" TENDSTR)));
66740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
66840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
66940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tnl->tnodes = newTnodes;
67040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tnl->next = dev->allocatedTnodeList;
67140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocatedTnodeList = tnl;
67240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
67340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
67440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
67540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
67640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
67740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
67840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
67940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */
68040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
68140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device * dev)
68240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
68340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn = NULL;
68440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
68540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* If there are none left make more */
68640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->freeTnodes) {
68740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
68840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
68940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
69040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->freeTnodes) {
69140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn = dev->freeTnodes;
69240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
69340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) {
69440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Hoosterman, this thing looks like it isn't in the list */
69540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ALWAYS,
69640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("yaffs: Tnode list bug 1" TENDSTR)));
69740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
69840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
69940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->freeTnodes = dev->freeTnodes->internal[0];
70040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nFreeTnodes--;
70140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
70240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
70340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return tn;
70440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
70540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
70640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
70740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
70840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
70940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
71040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(tn)
71140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
71240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
71340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return tn;
71440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
71540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
71640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* FreeTnode frees up a tnode and puts it back on the free list */
71740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_FreeTnode(yaffs_Device * dev, yaffs_Tnode * tn)
71840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
71940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn) {
72040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
72140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) {
72240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Hoosterman, this thing looks like it is already in the list */
72340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ALWAYS,
72440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("yaffs: Tnode list bug 2" TENDSTR)));
72540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
72640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
72740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
72840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn->internal[0] = dev->freeTnodes;
72940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->freeTnodes = tn;
73040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nFreeTnodes++;
73140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
73240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
73340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
73440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
73540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
73640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Free the list of allocated tnodes */
73740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_TnodeList *tmp;
73840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
73940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (dev->allocatedTnodeList) {
74040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tmp = dev->allocatedTnodeList->next;
74140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
74240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(dev->allocatedTnodeList->tnodes);
74340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(dev->allocatedTnodeList);
74440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocatedTnodeList = tmp;
74540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
74640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
74740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
74840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeTnodes = NULL;
74940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeTnodes = 0;
75040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
75140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
75240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InitialiseTnodes(yaffs_Device * dev)
75340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
75440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->allocatedTnodeList = NULL;
75540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeTnodes = NULL;
75640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeTnodes = 0;
75740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nTnodesCreated = 0;
75840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
75940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
76040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
76140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
76240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val)
76340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
76440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 *map = (__u32 *)tn;
76540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 bitInMap;
76640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 bitInWord;
76740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 wordInMap;
76840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 mask;
76940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
77040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  pos &= YAFFS_TNODES_LEVEL0_MASK;
77140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  val >>= dev->chunkGroupBits;
77240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
77340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  bitInMap = pos * dev->tnodeWidth;
77440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  wordInMap = bitInMap /32;
77540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  bitInWord = bitInMap & (32 -1);
77640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
77740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  mask = dev->tnodeMask << bitInWord;
77840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
77940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  map[wordInMap] &= ~mask;
78040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  map[wordInMap] |= (mask & (val << bitInWord));
78140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
78240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  if(dev->tnodeWidth > (32-bitInWord)) {
78340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    bitInWord = (32 - bitInWord);
78440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    wordInMap++;;
78540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord);
78640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    map[wordInMap] &= ~mask;
78740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    map[wordInMap] |= (mask & (val >> bitInWord));
78840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  }
78940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
79040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
79140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos)
79240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
79340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 *map = (__u32 *)tn;
79440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 bitInMap;
79540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 bitInWord;
79640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 wordInMap;
79740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  __u32 val;
79840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
79940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  pos &= YAFFS_TNODES_LEVEL0_MASK;
80040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
80140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  bitInMap = pos * dev->tnodeWidth;
80240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  wordInMap = bitInMap /32;
80340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  bitInWord = bitInMap & (32 -1);
80440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
80540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  val = map[wordInMap] >> bitInWord;
80640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
80740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  if(dev->tnodeWidth > (32-bitInWord)) {
80840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    bitInWord = (32 - bitInWord);
80940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    wordInMap++;;
81040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    val |= (map[wordInMap] << bitInWord);
81140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  }
81240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
81340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  val &= dev->tnodeMask;
81440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  val <<= dev->chunkGroupBits;
81540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
81640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project  return val;
81740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
81840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
81940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* ------------------- End of individual tnode manipulation -----------------*/
82040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
82140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
82240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * The look up tree is represented by the top tnode and the number of topLevel
82340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * in the tree. 0 means only the level 0 tnode is in the tree.
82440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
82540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
82640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* FindLevel0Tnode finds the level 0 tnode, if one exists. */
82740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,
82840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  yaffs_FileStructure * fStruct,
82940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  __u32 chunkId)
83040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
83140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
83240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn = fStruct->top;
83340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 i;
83440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int requiredTallness;
83540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int level = fStruct->topLevel;
83640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
83740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Check sane level and chunk Id */
83840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) {
83940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
84040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
84140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
84240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (chunkId > YAFFS_MAX_CHUNK_ID) {
84340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
84440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
84540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
84640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* First check we're tall enough (ie enough topLevel) */
84740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
84840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	i = chunkId >> YAFFS_TNODES_LEVEL0_BITS;
84940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	requiredTallness = 0;
85040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (i) {
85140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		i >>= YAFFS_TNODES_INTERNAL_BITS;
85240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		requiredTallness++;
85340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
85440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
85540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (requiredTallness > fStruct->topLevel) {
85640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Not tall enough, so we can't find it, return NULL. */
85740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
85840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
85940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
86040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Traverse down to level 0 */
86140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (level > 0 && tn) {
86240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn = tn->
86340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    internal[(chunkId >>
86440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			       ( YAFFS_TNODES_LEVEL0_BITS +
86540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			         (level - 1) *
86640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			         YAFFS_TNODES_INTERNAL_BITS)
86740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      ) &
86840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     YAFFS_TNODES_INTERNAL_MASK];
86940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		level--;
87040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
87140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
87240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
87340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return tn;
87440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
87540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
87640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree.
87740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This happens in two steps:
87840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *  1. If the tree isn't tall enough, then make it taller.
87940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *  2. Scan down the tree towards the level 0 tnode adding tnodes if required.
88040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
88140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Used when modifying the tree.
88240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
88340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *  If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
88440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *  be plugged into the ttree.
88540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
88640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
88740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
88840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       yaffs_FileStructure * fStruct,
88940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       __u32 chunkId,
89040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       yaffs_Tnode *passedTn)
89140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
89240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
89340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int requiredTallness;
89440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
89540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int l;
89640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn;
89740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
89840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 x;
89940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
90040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
90140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Check sane level and page Id */
90240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) {
90340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
90440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
90540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
90640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (chunkId > YAFFS_MAX_CHUNK_ID) {
90740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
90840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
90940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
91040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* First check we're tall enough (ie enough topLevel) */
91140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
91240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	x = chunkId >> YAFFS_TNODES_LEVEL0_BITS;
91340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	requiredTallness = 0;
91440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (x) {
91540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x >>= YAFFS_TNODES_INTERNAL_BITS;
91640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		requiredTallness++;
91740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
91840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
91940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
92040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (requiredTallness > fStruct->topLevel) {
92140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Not tall enough,gotta make the tree taller */
92240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = fStruct->topLevel; i < requiredTallness; i++) {
92340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
92440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			tn = yaffs_GetTnode(dev);
92540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
92640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (tn) {
92740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				tn->internal[0] = fStruct->top;
92840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				fStruct->top = tn;
92940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
93040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
93140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR("yaffs: no more tnodes" TENDSTR)));
93240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
93340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
93440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
93540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		fStruct->topLevel = requiredTallness;
93640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
93740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
93840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Traverse down to level 0, adding anything we need */
93940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
94040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	l = fStruct->topLevel;
94140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tn = fStruct->top;
94240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
94340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(l > 0) {
94440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		while (l > 0 && tn) {
94540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			x = (chunkId >>
94640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     ( YAFFS_TNODES_LEVEL0_BITS +
94740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &
94840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    YAFFS_TNODES_INTERNAL_MASK;
94940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
95040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
95140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if((l>1) && !tn->internal[x]){
95240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Add missing non-level-zero tnode */
95340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				tn->internal[x] = yaffs_GetTnode(dev);
95440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
95540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if(l == 1) {
95640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Looking from level 1 at level 0 */
95740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 	if (passedTn) {
95840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* If we already have one, then release it.*/
95940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if(tn->internal[x])
96040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_FreeTnode(dev,tn->internal[x]);
96140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					tn->internal[x] = passedTn;
96240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
96340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else if(!tn->internal[x]) {
96440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Don't have one, none passed in */
96540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					tn->internal[x] = yaffs_GetTnode(dev);
96640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
96740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
96840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
96940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			tn = tn->internal[x];
97040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			l--;
97140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
97240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
97340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* top is level 0 */
97440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(passedTn) {
97540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memcpy(tn,passedTn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
97640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_FreeTnode(dev,passedTn);
97740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
97840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
97940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
98040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return tn;
98140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
98240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
98340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_FindChunkInGroup(yaffs_Device * dev, int theChunk,
98440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  yaffs_ExtendedTags * tags, int objectId,
98540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  int chunkInInode)
98640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
98740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int j;
98840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
98940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (j = 0; theChunk && j < dev->chunkGroupSize; j++) {
99040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (yaffs_CheckChunkBit
99140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    (dev, theChunk / dev->nChunksPerBlock,
99240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     theChunk % dev->nChunksPerBlock)) {
99340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL,
99440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							tags);
99540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (yaffs_TagsMatch(tags, objectId, chunkInInode)) {
99640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* found it; */
99740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				return theChunk;
99840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
99940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
100040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
100140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theChunk++;
100240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
100340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return -1;
100440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
100540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
100640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
100740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* DeleteWorker scans backwards through the tnode tree and deletes all the
100840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * chunks and tnodes in the file
100940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Returns 1 if the tree was deleted.
101040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
101140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
101240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
101340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,
101440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      int chunkOffset, int *limit)
101540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
101640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
101740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkInInode;
101840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int theChunk;
101940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
102040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int foundChunk;
102140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
102240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
102340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int allDone = 1;
102440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
102540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn) {
102640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (level > 0) {
102740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
102840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;
102940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     i--) {
103040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (tn->internal[i]) {
103140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (limit && (*limit) < 0) {
103240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						allDone = 0;
103340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					} else {
103440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						allDone =
103540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    yaffs_DeleteWorker(in,
103640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       tn->
103740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       internal
103840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       [i],
103940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       level -
104040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       1,
104140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       (chunkOffset
104240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									<<
104340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									YAFFS_TNODES_INTERNAL_BITS)
104440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       + i,
104540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								       limit);
104640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
104740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (allDone) {
104840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_FreeTnode(dev,
104940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								tn->
105040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								internal[i]);
105140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						tn->internal[i] = NULL;
105240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
105340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
105440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
105540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
105640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return (allDone) ? 1 : 0;
105740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (level == 0) {
105840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			int hitLimit = 0;
105940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
106040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit;
106140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     i--) {
106240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			        theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
106340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (theChunk) {
106440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
106540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					chunkInInode =
106640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    (chunkOffset <<
106740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     YAFFS_TNODES_LEVEL0_BITS) + i;
106840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
106940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					foundChunk =
107040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    yaffs_FindChunkInGroup(dev,
107140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   theChunk,
107240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   &tags,
107340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   in->objectId,
107440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   chunkInInode);
107540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
107640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (foundChunk > 0) {
107740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_DeleteChunk(dev,
107840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								  foundChunk, 1,
107940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								  __LINE__);
108040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->nDataChunks--;
108140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (limit) {
108240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							*limit = *limit - 1;
108340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							if (*limit <= 0) {
108440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								hitLimit = 1;
108540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							}
108640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
108740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
108840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
108940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
109040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_PutLevel0Tnode(dev,tn,i,0);
109140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
109240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
109340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
109440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return (i < 0) ? 1 : 0;
109540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
109640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
109740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
109840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
109940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
110040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
110140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
110240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
110340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
110440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk)
110540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
110640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
110740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *theBlock;
110840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
110940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk));
111040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
111140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	theBlock = yaffs_GetBlockInfo(dev, chunk / dev->nChunksPerBlock);
111240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (theBlock) {
111340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theBlock->softDeletions++;
111440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nFreeChunks++;
111540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
111640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
111740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
111840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file.
111940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * All soft deleting does is increment the block's softdelete count and pulls the chunk out
112040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * of the tnode.
112140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
112240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
112340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
112440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
112540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  __u32 level, int chunkOffset)
112640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
112740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
112840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int theChunk;
112940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int allDone = 1;
113040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
113140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
113240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn) {
113340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (level > 0) {
113440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
113540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;
113640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     i--) {
113740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (tn->internal[i]) {
113840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					allDone =
113940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    yaffs_SoftDeleteWorker(in,
114040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   tn->
114140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   internal[i],
114240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   level - 1,
114340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   (chunkOffset
114440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								    <<
114540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								    YAFFS_TNODES_INTERNAL_BITS)
114640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   + i);
114740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (allDone) {
114840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_FreeTnode(dev,
114940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								tn->
115040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								internal[i]);
115140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						tn->internal[i] = NULL;
115240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					} else {
115340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Hoosterman... how could this happen? */
115440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
115540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
115640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
115740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return (allDone) ? 1 : 0;
115840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (level == 0) {
115940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
116040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
116140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
116240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (theChunk) {
116340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Note this does not find the real chunk, only the chunk group.
116440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * We make an assumption that a chunk group is not larger than
116540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * a block.
116640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
116740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_SoftDeleteChunk(dev, theChunk);
116840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_PutLevel0Tnode(dev,tn,i,0);
116940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
117040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
117140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
117240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return 1;
117340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
117440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
117540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
117640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
117740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
117840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
117940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
118040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
118140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
118240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_SoftDeleteFile(yaffs_Object * obj)
118340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
118440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->deleted &&
118540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) {
118640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (obj->nDataChunks <= 0) {
118740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Empty file with no duplicate object headers, just delete it immediately */
118840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_FreeTnode(obj->myDev,
118940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					obj->variant.fileVariant.top);
119040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			obj->variant.fileVariant.top = NULL;
119140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_TRACING,
119240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("yaffs: Deleting empty file %d" TENDSTR),
119340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   obj->objectId));
119440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_DoGenericObjectDeletion(obj);
119540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
119640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_SoftDeleteWorker(obj,
119740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       obj->variant.fileVariant.top,
119840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       obj->variant.fileVariant.
119940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       topLevel, 0);
120040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			obj->softDeleted = 1;
120140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
120240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
120340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
120440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
120540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Pruning removes any part of the file structure tree that is beyond the
120640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * bounds of the file (ie that does not point to chunks).
120740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
120840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * A file should only get pruned when its size is reduced.
120940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
121040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Before pruning, the chunks must be pulled from the tree and the
121140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * level 0 tnode entries must be zeroed out.
121240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Could also use this for file deletion, but that's probably better handled
121340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * by a special case.
121440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
121540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
121640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn,
121740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      __u32 level, int del0)
121840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
121940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
122040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int hasData;
122140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
122240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn) {
122340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		hasData = 0;
122440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
122540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) {
122640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (tn->internal[i] && level > 0) {
122740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				tn->internal[i] =
122840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_PruneWorker(dev, tn->internal[i],
122940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						      level - 1,
123040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						      (i == 0) ? del0 : 1);
123140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
123240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
123340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (tn->internal[i]) {
123440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				hasData++;
123540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
123640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
123740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
123840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (hasData == 0 && del0) {
123940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Free and return NULL */
124040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
124140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_FreeTnode(dev, tn);
124240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			tn = NULL;
124340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
124440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
124540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
124640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
124740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return tn;
124840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
124940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
125040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
125140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_PruneFileStructure(yaffs_Device * dev,
125240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_FileStructure * fStruct)
125340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
125440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
125540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int hasData;
125640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int done = 0;
125740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn;
125840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
125940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (fStruct->topLevel > 0) {
126040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		fStruct->top =
126140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    yaffs_PruneWorker(dev, fStruct->top, fStruct->topLevel, 0);
126240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
126340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Now we have a tree with all the non-zero branches NULL but the height
126440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * is the same as it was.
126540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * Let's see if we can trim internal tnodes to shorten the tree.
126640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * We can do this if only the 0th element in the tnode is in use
126740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * (ie all the non-zero are NULL)
126840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
126940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
127040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		while (fStruct->topLevel && !done) {
127140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			tn = fStruct->top;
127240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
127340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			hasData = 0;
127440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) {
127540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (tn->internal[i]) {
127640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					hasData++;
127740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
127840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
127940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
128040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!hasData) {
128140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				fStruct->top = tn->internal[0];
128240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				fStruct->topLevel--;
128340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_FreeTnode(dev, tn);
128440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
128540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				done = 1;
128640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
128740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
128840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
128940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
129040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
129140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
129240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
129340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*-------------------- End of File Structure functions.-------------------*/
129440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
129540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* yaffs_CreateFreeObjects creates a bunch more objects and
129640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * adds them to the object free list.
129740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
129840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects)
129940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
130040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
130140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *newObjects;
130240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ObjectList *list;
130340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
130440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (nObjects < 1)
130540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
130640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
130740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* make these things */
130840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
130940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
131040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!newObjects) {
131140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALLOCATE,
131240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
131340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
131440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
131540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
131640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Hook them into the free list */
131740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < nObjects - 1; i++) {
131840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newObjects[i].siblings.next =
131940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    (struct list_head *)(&newObjects[i + 1]);
132040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
132140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
132240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
132340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeObjects = newObjects;
132440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeObjects += nObjects;
132540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nObjectsCreated += nObjects;
132640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
132740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now add this bunch of Objects to a list for freeing up. */
132840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
132940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list = YMALLOC(sizeof(yaffs_ObjectList));
133040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!list) {
133140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALLOCATE,
133240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Could not add objects to management list" TENDSTR)));
133340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
133440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list->objects = newObjects;
133540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list->next = dev->allocatedObjectList;
133640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocatedObjectList = list;
133740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
133840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
133940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
134040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
134140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
134240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
134340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */
134440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
134540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
134640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *tn = NULL;
134740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
134840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* If there are none left make more */
134940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->freeObjects) {
135040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
135140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
135240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
135340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->freeObjects) {
135440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn = dev->freeObjects;
135540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->freeObjects =
135640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    (yaffs_Object *) (dev->freeObjects->siblings.next);
135740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nFreeObjects--;
135840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
135940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Now sweeten it up... */
136040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
136140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(tn, 0, sizeof(yaffs_Object));
136240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn->myDev = dev;
136340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn->chunkId = -1;
136440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
136540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		INIT_LIST_HEAD(&(tn->hardLinks));
136640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		INIT_LIST_HEAD(&(tn->hashLink));
136740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		INIT_LIST_HEAD(&tn->siblings);
136840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
136940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Add it to the lost and found directory.
137040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * NB Can't put root or lostNFound in lostNFound so
137140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * check if lostNFound exists first
137240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
137340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->lostNFoundDir) {
137440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
137540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
137640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
137740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
137840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return tn;
137940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
138040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
138140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number,
138240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       __u32 mode)
138340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
138440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
138540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *obj =
138640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
138740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj) {
138840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->fake = 1;		/* it is fake so it has no NAND presence... */
138940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->renameAllowed = 0;	/* ... and we're not allowed to rename it... */
139040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->unlinkAllowed = 0;	/* ... or unlink it */
139140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->deleted = 0;
139240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->unlinked = 0;
139340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->yst_mode = mode;
139440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->myDev = dev;
139540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->chunkId = 0;	/* Not a valid chunk. */
139640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
139740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
139840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return obj;
139940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
140040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
140140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
140240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_UnhashObject(yaffs_Object * tn)
140340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
140440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int bucket;
140540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = tn->myDev;
140640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
140740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* If it is still linked into the bucket list, free from the list */
140840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!list_empty(&tn->hashLink)) {
140940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list_del_init(&tn->hashLink);
141040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bucket = yaffs_HashFunction(tn->objectId);
141140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->objectBucket[bucket].count--;
141240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
141340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
141440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
141540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
141640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*  FreeObject frees up a Object and puts it back on the free list */
141740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_FreeObject(yaffs_Object * tn)
141840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
141940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
142040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = tn->myDev;
142140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
142240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef  __KERNEL__
142340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn->myInode) {
142440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* We're still hooked up to a cached inode.
142540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * Don't delete now, but mark for later deletion
142640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
142740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn->deferedFree = 1;
142840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return;
142940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
143040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
143140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
143240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_UnhashObject(tn);
143340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
143440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Link into the free list. */
143540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tn->siblings.next = (struct list_head *)(dev->freeObjects);
143640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeObjects = tn;
143740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeObjects++;
143840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
143940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
144040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef __KERNEL__
144140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
144240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_HandleDeferedFree(yaffs_Object * obj)
144340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
144440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->deferedFree) {
144540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_FreeObject(obj);
144640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
144740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
144840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
144940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
145040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
145140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_DeinitialiseObjects(yaffs_Device * dev)
145240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
145340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Free the list of allocated Objects */
145440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
145540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ObjectList *tmp;
145640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
145740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (dev->allocatedObjectList) {
145840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tmp = dev->allocatedObjectList->next;
145940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(dev->allocatedObjectList->objects);
146040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(dev->allocatedObjectList);
146140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
146240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocatedObjectList = tmp;
146340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
146440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
146540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeObjects = NULL;
146640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeObjects = 0;
146740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
146840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
146940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InitialiseObjects(yaffs_Device * dev)
147040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
147140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
147240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
147340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->allocatedObjectList = NULL;
147440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->freeObjects = NULL;
147540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeObjects = 0;
147640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
147740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
147840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		INIT_LIST_HEAD(&dev->objectBucket[i].list);
147940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->objectBucket[i].count = 0;
148040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
148140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
148240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
148340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
148440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_FindNiceObjectBucket(yaffs_Device * dev)
148540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
148640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static int x = 0;
148740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
148840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int l = 999;
148940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int lowest = 999999;
149040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
149140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* First let's see if we can find one that's empty. */
149240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
149340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < 10 && lowest > 0; i++) {
149440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x++;
149540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x %= YAFFS_NOBJECT_BUCKETS;
149640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->objectBucket[x].count < lowest) {
149740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			lowest = dev->objectBucket[x].count;
149840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			l = x;
149940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
150040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
150140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
150240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
150340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* If we didn't find an empty list, then try
150440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * looking a bit further for a short one
150540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
150640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
150740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < 10 && lowest > 3; i++) {
150840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x++;
150940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x %= YAFFS_NOBJECT_BUCKETS;
151040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->objectBucket[x].count < lowest) {
151140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			lowest = dev->objectBucket[x].count;
151240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			l = x;
151340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
151440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
151540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
151640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
151740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return l;
151840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
151940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
152040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CreateNewObjectNumber(yaffs_Device * dev)
152140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
152240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int bucket = yaffs_FindNiceObjectBucket(dev);
152340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
152440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now find an object value that has not already been taken
152540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * by scanning the list.
152640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
152740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
152840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int found = 0;
152940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct list_head *i;
153040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
153140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 n = (__u32) bucket;
153240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
153340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* yaffs_CheckObjectHashSanity();  */
153440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
153540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (!found) {
153640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		found = 1;
153740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		n += YAFFS_NOBJECT_BUCKETS;
153840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (1 || dev->objectBucket[bucket].count > 0) {
153940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			list_for_each(i, &dev->objectBucket[bucket].list) {
154040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* If there is already one in the list */
154140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (i
154240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    && list_entry(i, yaffs_Object,
154340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  hashLink)->objectId == n) {
154440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					found = 0;
154540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
154640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
154740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
154840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
154940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
155040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
155140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return n;
155240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
155340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
155440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HashObject(yaffs_Object * in)
155540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
155640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int bucket = yaffs_HashFunction(in->objectId);
155740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
155840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
155940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_add(&in->hashLink, &dev->objectBucket[bucket].list);
156040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->objectBucket[bucket].count++;
156140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
156240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
156340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
156440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
156540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
156640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int bucket = yaffs_HashFunction(number);
156740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct list_head *i;
156840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *in;
156940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
157040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_for_each(i, &dev->objectBucket[bucket].list) {
157140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Look if it is in the list */
157240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (i) {
157340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in = list_entry(i, yaffs_Object, hashLink);
157440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (in->objectId == number) {
157540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef __KERNEL__
157640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Don't tell the VFS about this one if it is defered free */
157740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (in->deferedFree)
157840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					return NULL;
157940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
158040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
158140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				return in;
158240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
158340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
158440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
158540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
158640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return NULL;
158740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
158840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
158940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
159040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_ObjectType type)
159140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
159240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
159340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *theObject;
159440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
159540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (number < 0) {
159640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		number = yaffs_CreateNewObjectNumber(dev);
159740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
159840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
159940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	theObject = yaffs_AllocateEmptyObject(dev);
160040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
160140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (theObject) {
160240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->fake = 0;
160340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->renameAllowed = 1;
160440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->unlinkAllowed = 1;
160540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->objectId = number;
160640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_HashObject(theObject);
160740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->variantType = type;
160840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
160940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yfsd_WinFileTimeNow(theObject->win_atime);
161040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->win_ctime[0] = theObject->win_mtime[0] =
161140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    theObject->win_atime[0];
161240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->win_ctime[1] = theObject->win_mtime[1] =
161340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    theObject->win_atime[1];
161440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
161540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
161640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
161740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject->yst_atime = theObject->yst_mtime =
161840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    theObject->yst_ctime = Y_CURRENT_TIME;
161940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
162040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		switch (type) {
162140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_FILE:
162240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			theObject->variant.fileVariant.fileSize = 0;
162340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			theObject->variant.fileVariant.scannedFileSize = 0;
162440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF;	/* max __u32 */
162540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			theObject->variant.fileVariant.topLevel = 0;
162640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			theObject->variant.fileVariant.top =
162740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_GetTnode(dev);
162840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
162940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_DIRECTORY:
163040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			INIT_LIST_HEAD(&theObject->variant.directoryVariant.
163140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       children);
163240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
163340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SYMLINK:
163440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_HARDLINK:
163540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SPECIAL:
163640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* No action required */
163740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
163840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_UNKNOWN:
163940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* todo this should not happen */
164040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
164140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
164240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
164340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
164440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return theObject;
164540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
164640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
164740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev,
164840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						      int number,
164940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						      yaffs_ObjectType type)
165040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
165140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *theObject = NULL;
165240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
165340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (number > 0) {
165440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject = yaffs_FindObjectByNumber(dev, number);
165540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
165640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
165740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!theObject) {
165840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theObject = yaffs_CreateNewObject(dev, number, type);
165940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
166040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
166140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return theObject;
166240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
166340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
166440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
166540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
166640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic YCHAR *yaffs_CloneString(const YCHAR * str)
166740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
166840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YCHAR *newStr = NULL;
166940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
167040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (str && *str) {
167140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR));
167240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_strcpy(newStr, str);
167340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
167440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
167540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return newStr;
167640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
167740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
167840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
167940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
168040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Mknod (create) a new object.
168140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * equivalentObject only has meaning for a hard link;
168240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * aliasString only has meaning for a sumlink.
168340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * rdev only has meaning for devices (a subset of special objects)
168440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
168540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
168640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
168740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       yaffs_Object * parent,
168840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       const YCHAR * name,
168940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       __u32 mode,
169040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       __u32 uid,
169140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       __u32 gid,
169240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       yaffs_Object * equivalentObject,
169340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       const YCHAR * aliasString, __u32 rdev)
169440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
169540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *in;
169640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
169740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = parent->myDev;
169840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
169940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Check if the entry exists. If it does then fail the call since we don't want a dup.*/
170040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (yaffs_FindObjectByName(parent, name)) {
170140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
170240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
170340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
170440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	in = yaffs_CreateNewObject(dev, -1, type);
170540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
170640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in) {
170740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->chunkId = -1;
170840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->valid = 1;
170940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->variantType = type;
171040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
171140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_mode = mode;
171240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
171340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
171440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yfsd_WinFileTimeNow(in->win_atime);
171540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];
171640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];
171740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
171840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
171940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME;
172040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
172140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_rdev = rdev;
172240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_uid = uid;
172340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_gid = gid;
172440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
172540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->nDataChunks = 0;
172640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
172740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_SetObjectName(in, name);
172840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->dirty = 1;
172940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
173040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_AddObjectToDirectory(parent, in);
173140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
173240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->myDev = parent->myDev;
173340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
173440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		switch (type) {
173540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SYMLINK:
173640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->variant.symLinkVariant.alias =
173740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_CloneString(aliasString);
173840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
173940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_HARDLINK:
174040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->variant.hardLinkVariant.equivalentObject =
174140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    equivalentObject;
174240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->variant.hardLinkVariant.equivalentObjectId =
174340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    equivalentObject->objectId;
174440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			list_add(&in->hardLinks, &equivalentObject->hardLinks);
174540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
174640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_FILE:
174740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_DIRECTORY:
174840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SPECIAL:
174940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_UNKNOWN:
175040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* do nothing */
175140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
175240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
175340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
175440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) {
175540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Could not create the object header, fail the creation */
175640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_DestroyObject(in);
175740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in = NULL;
175840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
175940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
176040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
176140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
176240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return in;
176340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
176440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
176540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
176640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      __u32 mode, __u32 uid, __u32 gid)
176740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
176840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,
176940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 uid, gid, NULL, NULL, 0);
177040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
177140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
177240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name,
177340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   __u32 mode, __u32 uid, __u32 gid)
177440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
177540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,
177640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 mode, uid, gid, NULL, NULL, 0);
177740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
177840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
177940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name,
178040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 __u32 mode, __u32 uid, __u32 gid, __u32 rdev)
178140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
178240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,
178340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 uid, gid, NULL, NULL, rdev);
178440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
178540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
178640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name,
178740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 __u32 mode, __u32 uid, __u32 gid,
178840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 const YCHAR * alias)
178940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
179040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,
179140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 uid, gid, NULL, alias, 0);
179240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
179340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
179440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* yaffs_Link returns the object id of the equivalent object.*/
179540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name,
179640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 yaffs_Object * equivalentObject)
179740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
179840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Get the real object in case we were fed a hard link as an equivalent object */
179940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
180040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
180140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (yaffs_MknodObject
180240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    (YAFFS_OBJECT_TYPE_HARDLINK, parent, name, 0, 0, 0,
180340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     equivalentObject, NULL, 0)) {
180440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return equivalentObject;
180540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
180640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
180740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
180840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
180940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
181040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
181140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir,
181240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  const YCHAR * newName, int force, int shadows)
181340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
181440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int unlinkOp;
181540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int deleteOp;
181640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
181740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *existingTarget;
181840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
181940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (newDir == NULL) {
182040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newDir = obj->parent;	/* use the old directory */
182140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
182240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
182340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
182440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
182540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
182640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
182740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    TENDSTR)));
182840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
182940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
183040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
183140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
183240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->myDev->isYaffs2) {
183340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		unlinkOp = (newDir == obj->myDev->unlinkedDir);
183440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
183540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		unlinkOp = (newDir == obj->myDev->unlinkedDir
183640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    && obj->variantType == YAFFS_OBJECT_TYPE_FILE);
183740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
183840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
183940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	deleteOp = (newDir == obj->myDev->deletedDir);
184040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
184140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	existingTarget = yaffs_FindObjectByName(newDir, newName);
184240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
184340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* If the object is a file going into the unlinked directory,
184440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 *   then it is OK to just stuff it in since duplicate names are allowed.
184540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 *   else only proceed if the new name does not exist and if we're putting
184640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 *   it into a directory.
184740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
184840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((unlinkOp ||
184940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     deleteOp ||
185040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     force ||
185140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     (shadows > 0) ||
185240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     !existingTarget) &&
185340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) {
185440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_SetObjectName(obj, newName);
185540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->dirty = 1;
185640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
185740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_AddObjectToDirectory(newDir, obj);
185840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
185940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (unlinkOp)
186040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			obj->unlinked = 1;
186140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
186240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* If it is a deletion then we mark it as a shrink for gc purposes. */
186340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 0)
186440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return YAFFS_OK;
186540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
186640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
186740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_FAIL;
186840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
186940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
187040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
187140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		       yaffs_Object * newDir, const YCHAR * newName)
187240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
187340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *obj;
187440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *existingTarget;
187540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int force = 0;
187640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
187740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
187840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Special case for case insemsitive systems (eg. WinCE).
187940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * While look-up is case insensitive, the name isn't.
188040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Therefore we might want to change x.txt to X.txt
188140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*/
188240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0) {
188340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		force = 1;
188440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
188540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
188640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
188740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj = yaffs_FindObjectByName(oldDir, oldName);
188840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Check new name to long. */
188940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
189040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
189140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  /* ENAMETOOLONG */
189240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  return YAFFS_FAIL;
189340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
189440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
189540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  /* ENAMETOOLONG */
189640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  return YAFFS_FAIL;
189740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
189840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj && obj->renameAllowed) {
189940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
190040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Now do the handling for an existing target, if there is one */
190140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
190240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		existingTarget = yaffs_FindObjectByName(newDir, newName);
190340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (existingTarget &&
190440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
190540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    !list_empty(&existingTarget->variant.directoryVariant.children)) {
190640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* There is a target that is a non-empty directory, so we fail */
190740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return YAFFS_FAIL;	/* EEXIST or ENOTEMPTY */
190840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (existingTarget && existingTarget != obj) {
190940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Nuke the target first, using shadowing,
191040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * but only if it isn't the same object
191140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
191240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ChangeObjectName(obj, newDir, newName, force,
191340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       existingTarget->objectId);
191440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_UnlinkObject(existingTarget);
191540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
191640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
191740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0);
191840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
191940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_FAIL;
192040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
192140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
192240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*------------------------- Block Management and Page Allocation ----------------*/
192340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
192440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_InitialiseBlocks(yaffs_Device * dev)
192540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
192640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
192740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
192840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->allocationBlock = -1;	/* force it to get a new one */
192940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
193040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Todo we're assuming the malloc will pass. */
193140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo));
193240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!dev->blockInfo){
193340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo));
193440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->blockInfoAlt = 1;
193540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
193640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
193740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->blockInfoAlt = 0;
193840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
193940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Set up dynamic blockinfo stuff. */
194040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; // round up bytes
194140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
194240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!dev->chunkBits){
194340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks);
194440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkBitsAlt = 1;
194540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
194640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
194740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkBitsAlt = 0;
194840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
194940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->blockInfo && dev->chunkBits) {
195040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));
195140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);
195240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
195340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
195440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
195540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_FAIL;
195640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
195740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
195840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
195940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_DeinitialiseBlocks(yaffs_Device * dev)
196040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
196140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(dev->blockInfoAlt)
196240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE_ALT(dev->blockInfo);
196340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
196440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(dev->blockInfo);
196540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->blockInfoAlt = 0;
196640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
196740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->blockInfo = NULL;
196840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
196940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(dev->chunkBitsAlt)
197040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE_ALT(dev->chunkBits);
197140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
197240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(dev->chunkBits);
197340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->chunkBitsAlt = 0;
197440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->chunkBits = NULL;
197540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
197640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
197740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev,
197840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    yaffs_BlockInfo * bi)
197940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
198040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
198140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 seq;
198240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *b;
198340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
198440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->isYaffs2)
198540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 1;	/* disqualification only applies to yaffs2. */
198640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
198740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!bi->hasShrinkHeader)
198840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 1;	/* can gc */
198940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
199040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Find the oldest dirty sequence number if we don't know it and save it
199140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * so we don't have to keep recomputing it.
199240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
199340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->oldestDirtySequence) {
199440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		seq = dev->sequenceNumber;
199540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
199640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = dev->internalStartBlock; i <= dev->internalEndBlock;
199740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     i++) {
199840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			b = yaffs_GetBlockInfo(dev, i);
199940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (b->blockState == YAFFS_BLOCK_STATE_FULL &&
200040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (b->pagesInUse - b->softDeletions) <
200140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    dev->nChunksPerBlock && b->sequenceNumber < seq) {
200240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				seq = b->sequenceNumber;
200340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
200440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
200540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->oldestDirtySequence = seq;
200640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
200740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
200840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Can't do gc of this block if there are any blocks older than this one that have
200940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * discarded pages.
201040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
201140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return (bi->sequenceNumber <= dev->oldestDirtySequence);
201240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
201340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
201440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
201540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
201640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
201740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* FindDiretiestBlock is used to select the dirtiest block (or close enough)
201840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * for garbage collection.
201940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
202040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
202140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,
202240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       int aggressive)
202340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
202440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
202540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int b = dev->currentDirtyChecker;
202640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
202740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
202840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int iterations;
202940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int dirtiest = -1;
203040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pagesInUse;
203140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int prioritised=0;
203240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
203340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static int nonAggressiveSkip = 0;
203440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pendingPrioritisedExist = 0;
203540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
203640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* First let's see if we need to grab a prioritised block */
203740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(dev->hasPendingPrioritisedGCs){
203840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
203940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
204040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bi = yaffs_GetBlockInfo(dev, i);
204140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if(bi->gcPrioritise)
204240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				pendingPrioritisedExist = 1;
204340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
204440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   bi->gcPrioritise &&
204540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   yaffs_BlockNotDisqualifiedFromGC(dev, bi)){
204640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				pagesInUse = (bi->pagesInUse - bi->softDeletions);
204740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dirtiest = i;
204840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				prioritised = 1;
204940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				aggressive = 1; /* Fool the non-aggressive skip logiv below */
205040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
205140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
205240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
205340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(!pendingPrioritisedExist) /* None found, so we can clear this */
205440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->hasPendingPrioritisedGCs = 0;
205540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
205640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
205740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* If we're doing aggressive GC then we are happy to take a less-dirty block, and
205840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * search harder.
205940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * else (we're doing a leasurely gc), then we only bother to do this if the
206040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * block has only a few pages in use.
206140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
206240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
206340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nonAggressiveSkip--;
206440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
206540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!aggressive && (nonAggressiveSkip > 0)) {
206640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -1;
206740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
206840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
206940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!prioritised)
207040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		pagesInUse =
207140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    		(aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;
207240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
207340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (aggressive) {
207440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		iterations =
207540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    dev->internalEndBlock - dev->internalStartBlock + 1;
207640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
207740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		iterations =
207840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    dev->internalEndBlock - dev->internalStartBlock + 1;
207940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		iterations = iterations / 16;
208040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (iterations > 200) {
208140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			iterations = 200;
208240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
208340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
208440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
208540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) {
208640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		b++;
208740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (b < dev->internalStartBlock || b > dev->internalEndBlock) {
208840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			b = dev->internalStartBlock;
208940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
209040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
209140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (b < dev->internalStartBlock || b > dev->internalEndBlock) {
209240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ERROR,
209340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("**>> Block %d is not valid" TENDSTR), b));
209440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			YBUG();
209540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
209640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
209740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi = yaffs_GetBlockInfo(dev, b);
209840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
209940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if 0
210040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) {
210140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dirtiest = b;
210240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			pagesInUse = 0;
210340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
210440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else
210540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
210640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
210740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
210840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		       (bi->pagesInUse - bi->softDeletions) < pagesInUse &&
210940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		        yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {
211040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dirtiest = b;
211140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			pagesInUse = (bi->pagesInUse - bi->softDeletions);
211240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
211340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
211440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
211540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->currentDirtyChecker = b;
211640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
211740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dirtiest > 0) {
211840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_GC,
211940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("GC Selected block %d with %d free, prioritised:%d" TENDSTR), dirtiest,
212040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   dev->nChunksPerBlock - pagesInUse,prioritised));
212140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
212240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
212340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->oldestDirtySequence = 0;
212440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
212540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dirtiest > 0) {
212640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nonAggressiveSkip = 4;
212740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
212840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
212940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return dirtiest;
213040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
213140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
213240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo)
213340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
213440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockNo);
213540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
213640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int erasedOk = 0;
213740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
213840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* If the block is still healthy erase it and mark as clean.
213940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * If the block has had a data failure, then retire it.
214040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
214140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
214240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
214340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!bi->needsRetiring) {
214440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_InvalidateCheckpoint(dev);
214540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		erasedOk = yaffs_EraseBlockInNAND(dev, blockNo);
214640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (!erasedOk) {
214740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->nErasureFailures++;
214840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
214940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("**>> Erasure failed %d" TENDSTR), blockNo));
215040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
215140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
215240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
215340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE)) {
215440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int i;
215540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < dev->nChunksPerBlock; i++) {
215640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!yaffs_CheckChunkErased
215740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (dev, blockNo * dev->nChunksPerBlock + i)) {
215840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
215940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
216040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   (">>Block %d erasure supposedly OK, but chunk %d not erased"
216140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), blockNo, i));
216240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
216340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
216440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
216540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
216640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (erasedOk) {
216740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Clean it up... */
216840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
216940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nErasedBlocks++;
217040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->pagesInUse = 0;
217140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->softDeletions = 0;
217240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->hasShrinkHeader = 0;
217340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->skipErasedCheck = 1;  /* This is clean, so no need to check */
217440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->gcPrioritise = 0;
217540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ClearChunkBits(dev, blockNo);
217640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
217740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERASE,
217840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Erased block %d" TENDSTR), blockNo));
217940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
218040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nFreeChunks -= dev->nChunksPerBlock;	/* We lost a block of free space */
218140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
218240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_RetireBlock(dev, blockNo);
218340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
218440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("**>> Block %d retired" TENDSTR), blockNo));
218540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
218640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
218740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
218840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_FindBlockForAllocation(yaffs_Device * dev)
218940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
219040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
219140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
219240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
219340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
219440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nErasedBlocks < 1) {
219540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Hoosterman we've got a problem.
219640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * Can't get space to gc
219740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
219840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERROR,
219940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
220040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
220140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -1;
220240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
220340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
220440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Find an empty block. */
220540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
220640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
220740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocationBlockFinder++;
220840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->allocationBlockFinder < dev->internalStartBlock
220940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    || dev->allocationBlockFinder > dev->internalEndBlock) {
221040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->allocationBlockFinder = dev->internalStartBlock;
221140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
221240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
221340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi = yaffs_GetBlockInfo(dev, dev->allocationBlockFinder);
221440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
221540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) {
221640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING;
221740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->sequenceNumber++;
221840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bi->sequenceNumber = dev->sequenceNumber;
221940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->nErasedBlocks--;
222040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ALLOCATE,
222140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("Allocated block %d, seq  %d, %d left" TENDSTR),
222240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   dev->allocationBlockFinder, dev->sequenceNumber,
222340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   dev->nErasedBlocks));
222440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return dev->allocationBlockFinder;
222540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
222640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
222740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
222840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_ALWAYS,
222940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR
223040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   ("yaffs tragedy: no more eraased blocks, but there should have been %d"
223140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    TENDSTR), dev->nErasedBlocks));
223240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
223340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return -1;
223440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
223540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
223640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
223740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project// Check if there's space to allocate...
223840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project// Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
223940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
224040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
224140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int reservedChunks;
224240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int reservedBlocks = dev->nReservedBlocks;
224340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int checkpointBlocks;
224440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
224540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
224640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(checkpointBlocks < 0)
224740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		checkpointBlocks = 0;
224840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
224940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
225040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
225140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return (dev->nFreeChunks > reservedChunks);
225240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
225340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
225440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr)
225540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
225640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal;
225740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
225840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
225940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->allocationBlock < 0) {
226040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Get next block to allocate off */
226140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocationBlock = yaffs_FindBlockForAllocation(dev);
226240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocationPage = 0;
226340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
226440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
226540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!useReserve && !yaffs_CheckSpaceForAllocation(dev)) {
226640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Not enough space to allocate unless we're allowed to use the reserve. */
226740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -1;
226840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
226940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
227040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nErasedBlocks < dev->nReservedBlocks
227140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    && dev->allocationPage == 0) {
227240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR)));
227340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
227440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
227540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Next page please.... */
227640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->allocationBlock >= 0) {
227740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi = yaffs_GetBlockInfo(dev, dev->allocationBlock);
227840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
227940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal = (dev->allocationBlock * dev->nChunksPerBlock) +
228040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    dev->allocationPage;
228140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->pagesInUse++;
228240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_SetChunkBit(dev, dev->allocationBlock,
228340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  dev->allocationPage);
228440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
228540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->allocationPage++;
228640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
228740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nFreeChunks--;
228840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
228940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* If the block is full set the state to full */
229040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->allocationPage >= dev->nChunksPerBlock) {
229140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bi->blockState = YAFFS_BLOCK_STATE_FULL;
229240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->allocationBlock = -1;
229340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
229440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
229540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(blockUsedPtr)
229640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			*blockUsedPtr = bi;
229740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
229840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return retVal;
229940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
230040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
230140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_ERROR,
230240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
230340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
230440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return -1;
230540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
230640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
230740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_GetErasedChunks(yaffs_Device * dev)
230840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
230940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int n;
231040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
231140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	n = dev->nErasedBlocks * dev->nChunksPerBlock;
231240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
231340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->allocationBlock > 0) {
231440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		n += (dev->nChunksPerBlock - dev->allocationPage);
231540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
231640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
231740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return n;
231840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
231940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
232040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
232140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
232240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
232340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int oldChunk;
232440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int newChunk;
232540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkInBlock;
232640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int markNAND;
232740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal = YAFFS_OK;
232840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int cleanups = 0;
232940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
233040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int isCheckpointBlock;
233140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
233240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunksBefore = yaffs_GetErasedChunks(dev);
233340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunksAfter;
233440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
233540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
233640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
233740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, block);
233840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
233940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *object;
234040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
234140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);
234240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
234340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
234440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
234540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_TRACING,
234640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
234740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   bi->pagesInUse, bi->hasShrinkHeader));
234840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
234940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/*yaffs_VerifyFreeChunks(dev); */
235040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
235140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	bi->hasShrinkHeader = 0;	/* clear the flag so that the block can erase */
235240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
235340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Take off the number of soft deleted entries because
235440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * they're going to get really deleted during GC.
235540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
235640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeChunks -= bi->softDeletions;
235740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
235840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->isDoingGC = 1;
235940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
236040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (isCheckpointBlock ||
236140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    !yaffs_StillSomeChunkBits(dev, block)) {
236240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_TRACING,
236340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
236440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("Collecting block %d that has no chunks in use" TENDSTR),
236540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   block));
236640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_BlockBecameDirty(dev, block);
236740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
236840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
236940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
237040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
237140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
237240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     chunkInBlock < dev->nChunksPerBlock
237340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     && yaffs_StillSomeChunkBits(dev, block);
237440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     chunkInBlock++, oldChunk++) {
237540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
237640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
237740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* This page is in use and might need to be copied off */
237840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
237940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				markNAND = 1;
238040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
238140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_InitialiseTags(&tags);
238240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
238340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ReadChunkWithTagsFromNAND(dev, oldChunk,
238440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								buffer, &tags);
238540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
238640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				object =
238740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_FindObjectByNumber(dev,
238840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							     tags.objectId);
238940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
239040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_GC_DETAIL,
239140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
239240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("Collecting page %d, %d %d %d " TENDSTR),
239340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   chunkInBlock, tags.objectId, tags.chunkId,
239440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   tags.byteCount));
239540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
239640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!object) {
239740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					T(YAFFS_TRACE_ERROR,
239840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  (TSTR
239940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   ("page %d in gc has no object "
240040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    TENDSTR), oldChunk));
240140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
240240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
240340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (object && object->deleted
240440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    && tags.chunkId != 0) {
240540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Data chunk in a deleted file, throw it away
240640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * It's a soft deleted data chunk,
240740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * No need to copy this, just forget about it and
240840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * fix up the object.
240940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
241040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
241140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					object->nDataChunks--;
241240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
241340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (object->nDataChunks <= 0) {
241440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* remeber to clean up the object */
241540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						dev->gcCleanupList[cleanups] =
241640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    tags.objectId;
241740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						cleanups++;
241840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
241940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					markNAND = 0;
242040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else if (0
242140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   /* Todo object && object->deleted && object->nDataChunks == 0 */
242240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   ) {
242340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Deleted object header with no data chunks.
242440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * Can be discarded and the file deleted.
242540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
242640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					object->chunkId = 0;
242740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_FreeTnode(object->myDev,
242840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							object->variant.
242940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							fileVariant.top);
243040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					object->variant.fileVariant.top = NULL;
243140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_DoGenericObjectDeletion(object);
243240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
243340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else if (object) {
243440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* It's either a data chunk in a live file or
243540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * an ObjectHeader, so we're interested in it.
243640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * NB Need to keep the ObjectHeaders of deleted files
243740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * until the whole file has been deleted off
243840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
243940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					tags.serialNumber++;
244040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
244140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->nGCCopies++;
244240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
244340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (tags.chunkId == 0) {
244440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* It is an object Id,
244540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 * We need to nuke the shrinkheader flags first
244640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 * We no longer want the shrinkHeader flag since its work is done
244740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 * and if it is left in place it will mess up scanning.
244840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 * Also, clear out any shadowing stuff
244940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 */
245040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
245140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_ObjectHeader *oh;
245240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						oh = (yaffs_ObjectHeader *)buffer;
245340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						oh->isShrink = 0;
245440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						oh->shadowsObject = -1;
245540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						tags.extraShadows = 0;
245640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						tags.extraIsShrinkHeader = 0;
245740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
245840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
245940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					newChunk =
246040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags, 1);
246140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
246240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (newChunk < 0) {
246340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						retVal = YAFFS_FAIL;
246440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					} else {
246540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
246640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Ok, now fix up the Tnodes etc. */
246740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
246840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (tags.chunkId == 0) {
246940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							/* It's a header */
247040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							object->chunkId =  newChunk;
247140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							object->serial =   tags.serialNumber;
247240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						} else {
247340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							/* It's a data chunk */
247440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							yaffs_PutChunkIntoFile
247540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    (object,
247640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							     tags.chunkId,
247740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							     newChunk, 0);
247840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
247940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
248040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
248140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
248240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
248340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
248440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
248540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
248640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
248740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
248840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
248940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
249040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Do any required cleanups */
249140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < cleanups; i++) {
249240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Time to delete the file too */
249340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			object =
249440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_FindObjectByNumber(dev,
249540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     dev->gcCleanupList[i]);
249640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (object) {
249740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_FreeTnode(dev,
249840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						object->variant.fileVariant.
249940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						top);
250040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				object->variant.fileVariant.top = NULL;
250140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_GC,
250240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
250340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("yaffs: About to finally delete object %d"
250440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), object->objectId));
250540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DoGenericObjectDeletion(object);
250640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				object->myDev->nDeletedFiles--;
250740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
250840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
250940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
251040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
251140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
251240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
251340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {
251440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_GC,
251540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
251640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("gc did not increase free chunks before %d after %d"
251740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    TENDSTR), chunksBefore, chunksAfter));
251840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
251940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
252040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->isDoingGC = 0;
252140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
252240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
252340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
252440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
252540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* New garbage collector
252640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * If we're very low on erased blocks then we do aggressive garbage collection
252740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * otherwise we do "leasurely" garbage collection.
252840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Aggressive gc looks further (whole array) and will accept less dirty blocks.
252940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Passive gc only inspects smaller areas and will only accept more dirty blocks.
253040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
253140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * The idea is to help clear out space in a more spread-out manner.
253240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Dunno if it really does anything useful.
253340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
253440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckGarbageCollection(yaffs_Device * dev)
253540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
253640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int block;
253740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int aggressive;
253840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int gcOk = YAFFS_OK;
253940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int maxTries = 0;
254040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
254140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int checkpointBlockAdjust;
254240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
254340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isDoingGC) {
254440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Bail out so we don't get recursive gc */
254540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
254640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
254740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
254840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* This loop should pass the first time.
254940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * We'll only see looping here if the erase of the collected block fails.
255040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
255140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
255240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	do {
255340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		maxTries++;
255440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
255540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
255640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(checkpointBlockAdjust < 0)
255740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			checkpointBlockAdjust = 0;
255840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
255940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) {
256040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* We need a block soon...*/
256140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			aggressive = 1;
256240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
256340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* We're in no hurry */
256440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			aggressive = 0;
256540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
256640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
256740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
256840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
256940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (block > 0) {
257040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->garbageCollections++;
257140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!aggressive) {
257240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->passiveGarbageCollections++;
257340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
257440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
257540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_GC,
257640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR
257740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
257840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   dev->nErasedBlocks, aggressive));
257940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
258040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			gcOk = yaffs_GarbageCollectBlock(dev, block);
258140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
258240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
258340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
258440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_GC,
258540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR
258640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
258740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    TENDSTR), dev->nErasedBlocks, maxTries, block));
258840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
258940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
259040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 && (maxTries < 2));
259140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
259240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return aggressive ? gcOk : YAFFS_OK;
259340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
259440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
259540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*-------------------------  TAGS --------------------------------*/
259640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
259740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,
259840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   int chunkInObject)
259940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
260040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return (tags->chunkId == chunkInObject &&
260140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags->objectId == objectId && !tags->chunkDeleted) ? 1 : 0;
260240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
260340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
260440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
260540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
260640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*-------------------- Data file manipulation -----------------*/
260740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
260840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,
260940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 yaffs_ExtendedTags * tags)
261040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
261140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/*Get the Tnode, then get the level 0 offset chunk offset */
261240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn;
261340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int theChunk = -1;
261440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags localTags;
261540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal = -1;
261640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
261740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
261840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
261940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!tags) {
262040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Passed a NULL, so use our own tags space */
262140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags = &localTags;
262240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
262340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
262440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
262540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
262640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn) {
262740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
262840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
262940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal =
263040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
263140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   chunkInInode);
263240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
263340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retVal;
263440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
263540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
263640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode,
263740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  yaffs_ExtendedTags * tags)
263840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
263940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Get the Tnode, then get the level 0 offset chunk offset */
264040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn;
264140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int theChunk = -1;
264240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags localTags;
264340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
264440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
264540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal = -1;
264640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
264740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!tags) {
264840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Passed a NULL, so use our own tags space */
264940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags = &localTags;
265040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
265140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
265240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
265340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
265440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn) {
265540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
265640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
265740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
265840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal =
265940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
266040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   chunkInInode);
266140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
266240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Delete the entry in the filestructure (if found) */
266340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (retVal != -1) {
266440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0);
266540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
266640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
266740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/*T(("No level 0 found for %d\n", chunkInInode)); */
266840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
266940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
267040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (retVal == -1) {
267140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* T(("Could not find %d to delete\n",chunkInInode)); */
267240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
267340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retVal;
267440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
267540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
267640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef YAFFS_PARANOID
267740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
267840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckFileSanity(yaffs_Object * in)
267940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
268040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunk;
268140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nChunks;
268240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int fSize;
268340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int failed = 0;
268440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int objId;
268540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn;
268640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tags localTags;
268740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tags *tags = &localTags;
268840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int theChunk;
268940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkDeleted;
269040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
269140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
269240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* T(("Object not a file\n")); */
269340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
269440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
269540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
269640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	objId = in->objectId;
269740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	fSize = in->variant.fileVariant.fileSize;
269840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nChunks =
269940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    (fSize + in->myDev->nDataBytesPerChunk - 1) / in->myDev->nDataBytesPerChunk;
270040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
270140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (chunk = 1; chunk <= nChunks; chunk++) {
270240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn = yaffs_FindLevel0Tnode(in->myDev, &in->variant.fileVariant,
270340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   chunk);
270440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
270540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (tn) {
270640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
270740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk);
270840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
270940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (yaffs_CheckChunkBits
271040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (dev, theChunk / dev->nChunksPerBlock,
271140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     theChunk % dev->nChunksPerBlock)) {
271240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
271340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ReadChunkTagsFromNAND(in->myDev, theChunk,
271440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    tags,
271540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    &chunkDeleted);
271640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (yaffs_TagsMatch
271740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (tags, in->objectId, chunk, chunkDeleted)) {
271840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* found it; */
271940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
272040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
272140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
272240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
272340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				failed = 1;
272440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
272540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
272640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
272740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* T(("No level 0 found for %d\n", chunk)); */
272840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
272940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
273040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
273140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return failed ? YAFFS_FAIL : YAFFS_OK;
273240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
273340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
273440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
273540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
273640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
273740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  int chunkInNAND, int inScan)
273840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
273940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* NB inScan is zero unless scanning.
274040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * For forward scanning, inScan is > 0;
274140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * for backward scanning inScan is < 0
274240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
274340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
274440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn;
274540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
274640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int existingChunk;
274740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags existingTags;
274840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags newTags;
274940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned existingSerial, newSerial;
275040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
275140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
275240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Just ignore an attempt at putting a chunk into a non-file during scanning
275340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * If it is not during Scanning then something went wrong!
275440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
275540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (!inScan) {
275640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ERROR,
275740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR
275840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   ("yaffs tragedy:attempt to put data chunk into a non-file"
275940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    TENDSTR)));
276040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			YBUG();
276140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
276240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
276340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
276440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
276540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
276640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
276740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tn = yaffs_AddOrFindLevel0Tnode(dev,
276840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					&in->variant.fileVariant,
276940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					chunkInInode,
277040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					NULL);
277140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!tn) {
277240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
277340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
277440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
277540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
277640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
277740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (inScan != 0) {
277840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* If we're scanning then we need to test for duplicates
277940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * NB This does not need to be efficient since it should only ever
278040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * happen when the power fails during a write, then only one
278140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * chunk should ever be affected.
278240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 *
278340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * Correction for YAFFS2: This could happen quite a lot and we need to think about efficiency! TODO
278440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
278540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
278640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
278740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (existingChunk != 0) {
278840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* NB Right now existing chunk will not be real chunkId if the device >= 32MB
278940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 *    thus we have to do a FindChunkInFile to get the real chunk id.
279040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 *
279140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * We have a duplicate now we need to decide which one to use:
279240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 *
279340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * Backwards scanning YAFFS2: The old one is what we use, dump the new one.
279440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * Forward scanning YAFFS2: The new one is what we use, dump the old one.
279540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * YAFFS1: Get both sets of tags and compare serial numbers.
279640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
279740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
279840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (inScan > 0) {
279940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Only do this for forward scanning */
280040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ReadChunkWithTagsFromNAND(dev,
280140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								chunkInNAND,
280240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								NULL, &newTags);
280340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
280440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Do a proper find */
280540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				existingChunk =
280640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_FindChunkInFile(in, chunkInInode,
280740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							  &existingTags);
280840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
280940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
281040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (existingChunk <= 0) {
281140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/*Hoosterman - how did this happen? */
281240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
281340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
281440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
281540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("yaffs tragedy: existing chunk < 0 in scan"
281640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR)));
281740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
281840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
281940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
282040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* NB The deleted flags should be false, otherwise the chunks will
282140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * not be loaded during a scan
282240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
282340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
282440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			newSerial = newTags.serialNumber;
282540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			existingSerial = existingTags.serialNumber;
282640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
282740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if ((inScan > 0) &&
282840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (in->myDev->isYaffs2 ||
282940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     existingChunk <= 0 ||
283040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     ((existingSerial + 1) & 3) == newSerial)) {
283140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Forward scanning.
283240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Use new
283340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Delete the old one and drop through to update the tnode
283440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
283540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DeleteChunk(dev, existingChunk, 1,
283640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  __LINE__);
283740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
283840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Backward scanning or we want to use the existing one
283940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Use existing.
284040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Delete the new one and return early so that the tnode isn't changed
284140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
284240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DeleteChunk(dev, chunkInNAND, 1,
284340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  __LINE__);
284440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				return YAFFS_OK;
284540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
284640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
284740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
284840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
284940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
285040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (existingChunk == 0) {
285140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->nDataChunks++;
285240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
285340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
285440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND);
285540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
285640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
285740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
285840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
285940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ReadChunkDataFromObject(yaffs_Object * in, int chunkInInode,
286040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 __u8 * buffer)
286140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
286240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkInNAND = yaffs_FindChunkInFile(in, chunkInInode, NULL);
286340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
286440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (chunkInNAND >= 0) {
286540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_ReadChunkWithTagsFromNAND(in->myDev, chunkInNAND,
286640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						       buffer,NULL);
286740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
286840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_NANDACCESS,
286940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Chunk %d not found zero instead" TENDSTR),
287040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   chunkInNAND));
287140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* get sane (zero) data if you read a hole */
287240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(buffer, 0, in->myDev->nDataBytesPerChunk);
287340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
287440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
287540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
287640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
287740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
287840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn)
287940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
288040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int block;
288140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int page;
288240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
288340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
288440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
288540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (chunkId <= 0)
288640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return;
288740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
288840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nDeletions++;
288940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	block = chunkId / dev->nChunksPerBlock;
289040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	page = chunkId % dev->nChunksPerBlock;
289140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
289240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	bi = yaffs_GetBlockInfo(dev, block);
289340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
289440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_DELETION,
289540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));
289640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
289740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (markNAND &&
289840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->isYaffs2) {
289940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
290040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_InitialiseTags(&tags);
290140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
290240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags.chunkDeleted = 1;
290340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
290440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_WriteChunkWithTagsToNAND(dev, chunkId, NULL, &tags);
290540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_HandleUpdateChunk(dev, chunkId, &tags);
290640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
290740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nUnmarkedDeletions++;
290840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
290940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
291040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Pull out of the management area.
291140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * If the whole block became dirty, this will kick off an erasure.
291240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
291340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING ||
291440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    bi->blockState == YAFFS_BLOCK_STATE_FULL ||
291540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    bi->blockState == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
291640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
291740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->nFreeChunks++;
291840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
291940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ClearChunkBit(dev, block, page);
292040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
292140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->pagesInUse--;
292240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
292340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (bi->pagesInUse == 0 &&
292440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    !bi->hasShrinkHeader &&
292540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    bi->blockState != YAFFS_BLOCK_STATE_ALLOCATING &&
292640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    bi->blockState != YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
292740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_BlockBecameDirty(dev, block);
292840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
292940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
293040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
293140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* T(("Bad news deleting chunk %d\n",chunkId)); */
293240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
293340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
293440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
293540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
293640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,
293740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					const __u8 * buffer, int nBytes,
293840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					int useReserve)
293940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
294040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Find old chunk Need to do this to get serial number
294140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Write new one and patch into tree.
294240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Invalidate old tags.
294340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
294440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
294540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int prevChunkId;
294640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags prevTags;
294740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
294840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int newChunkId;
294940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags newTags;
295040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
295140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
295240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
295340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckGarbageCollection(dev);
295440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
295540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Get the previous chunk at this location in the file if it exists */
295640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	prevChunkId = yaffs_FindChunkInFile(in, chunkInInode, &prevTags);
295740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
295840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Set up new tags */
295940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InitialiseTags(&newTags);
296040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
296140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newTags.chunkId = chunkInInode;
296240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newTags.objectId = in->objectId;
296340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newTags.serialNumber =
296440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
296540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newTags.byteCount = nBytes;
296640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
296740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	newChunkId =
296840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
296940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					      useReserve);
297040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
297140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (newChunkId >= 0) {
297240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0);
297340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
297440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (prevChunkId >= 0) {
297540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__);
297640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
297740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
297840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
297940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_CheckFileSanity(in);
298040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
298140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return newChunkId;
298240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
298340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
298440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
298540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* UpdateObjectHeader updates the header on NAND for an object.
298640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * If name is not NULL, then that new name is used.
298740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
298840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,
298940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     int isShrink, int shadows)
299040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
299140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
299240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
299340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
299440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
299540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
299640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int prevChunkId;
299740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal = 0;
299840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int result = 0;
299940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
300040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int newChunkId;
300140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags newTags;
300240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
300340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *buffer = NULL;
300440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1];
300540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
300640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ObjectHeader *oh = NULL;
300740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
300840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!in->fake || force) {
300940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
301040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_CheckGarbageCollection(dev);
301140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
301240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
301340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh = (yaffs_ObjectHeader *) buffer;
301440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
301540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		prevChunkId = in->chunkId;
301640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
301740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (prevChunkId >= 0) {
301840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
301940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							buffer, NULL);
302040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memcpy(oldName, oh->name, sizeof(oh->name));
302140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
302240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
302340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(buffer, 0xFF, dev->nDataBytesPerChunk);
302440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
302540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->type = in->variantType;
302640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->yst_mode = in->yst_mode;
302740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->shadowsObject = shadows;
302840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
302940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
303040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->win_atime[0] = in->win_atime[0];
303140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->win_ctime[0] = in->win_ctime[0];
303240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->win_mtime[0] = in->win_mtime[0];
303340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->win_atime[1] = in->win_atime[1];
303440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->win_ctime[1] = in->win_ctime[1];
303540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->win_mtime[1] = in->win_mtime[1];
303640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
303740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->yst_uid = in->yst_uid;
303840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->yst_gid = in->yst_gid;
303940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->yst_atime = in->yst_atime;
304040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->yst_mtime = in->yst_mtime;
304140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->yst_ctime = in->yst_ctime;
304240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->yst_rdev = in->yst_rdev;
304340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
304440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (in->parent) {
304540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			oh->parentObjectId = in->parent->objectId;
304640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
304740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			oh->parentObjectId = 0;
304840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
304940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
305040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (name && *name) {
305140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memset(oh->name, 0, sizeof(oh->name));
305240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH);
305340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (prevChunkId) {
305440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memcpy(oh->name, oldName, sizeof(oh->name));
305540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
305640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memset(oh->name, 0, sizeof(oh->name));
305740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
305840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
305940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh->isShrink = isShrink;
306040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
306140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		switch (in->variantType) {
306240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_UNKNOWN:
306340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Should not happen */
306440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
306540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_FILE:
306640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			oh->fileSize =
306740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (oh->parentObjectId == YAFFS_OBJECTID_DELETED
306840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     || oh->parentObjectId ==
306940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     YAFFS_OBJECTID_UNLINKED) ? 0 : in->variant.
307040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    fileVariant.fileSize;
307140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
307240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_HARDLINK:
307340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			oh->equivalentObjectId =
307440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    in->variant.hardLinkVariant.equivalentObjectId;
307540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
307640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SPECIAL:
307740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Do nothing */
307840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
307940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_DIRECTORY:
308040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Do nothing */
308140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
308240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SYMLINK:
308340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_strncpy(oh->alias,
308440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      in->variant.symLinkVariant.alias,
308540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      YAFFS_MAX_ALIAS_LENGTH);
308640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
308740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
308840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
308940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
309040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Tags */
309140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_InitialiseTags(&newTags);
309240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->serial++;
309340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.chunkId = 0;
309440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.objectId = in->objectId;
309540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.serialNumber = in->serial;
309640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
309740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Add extra info for file header */
309840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
309940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.extraHeaderInfoAvailable = 1;
310040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.extraParentObjectId = oh->parentObjectId;
310140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.extraFileLength = oh->fileSize;
310240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.extraIsShrinkHeader = oh->isShrink;
310340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.extraEquivalentObjectId = oh->equivalentObjectId;
310440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0;
310540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newTags.extraObjectType = in->variantType;
310640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
310740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Create new chunk in NAND */
310840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		newChunkId =
310940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
311040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						      (prevChunkId >= 0) ? 1 : 0);
311140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
311240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (newChunkId >= 0) {
311340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
311440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->chunkId = newChunkId;
311540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
311640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (prevChunkId >= 0) {
311740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DeleteChunk(dev, prevChunkId, 1,
311840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  __LINE__);
311940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
312040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
312140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if(!yaffs_ObjectHasCachedWriteData(in))
312240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				in->dirty = 0;
312340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
312440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* If this was a shrink, then mark the block that the chunk lives on */
312540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (isShrink) {
312640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				bi = yaffs_GetBlockInfo(in->myDev,
312740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							newChunkId /in->myDev->	nChunksPerBlock);
312840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				bi->hasShrinkHeader = 1;
312940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
313040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
313140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
313240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
313340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal = newChunkId;
313440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
313540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
313640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
313740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (buffer)
313840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
313940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
314040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retVal;
314140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
314240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
314340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*------------------------ Short Operations Cache ----------------------------------------
314440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   In many situations where there is no high level buffering (eg WinCE) a lot of
314540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   reads might be short sequential reads, and a lot of writes may be short
314640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   sequential writes. eg. scanning/writing a jpeg file.
314740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   In these cases, a short read/write cache can provide a huge perfomance benefit
314840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   with dumb-as-a-rock code.
314940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   In Linux, the page cache provides read buffering aand the short op cache provides write
315040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   buffering.
315140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
315240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   There are a limited number (~10) of cache chunks per device so that we don't
315340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   need a very intelligent search.
315440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
315540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
315640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj)
315740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
315840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = obj->myDev;
315940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
316040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ChunkCache *cache;
316140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nCaches = obj->myDev->nShortOpCaches;
316240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
316340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i = 0; i < nCaches; i++){
316440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		cache = &dev->srCache[i];
316540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (cache->object == obj &&
316640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    cache->dirty)
316740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return 1;
316840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
316940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
317040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
317140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
317240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
317340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
317440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_FlushFilesChunkCache(yaffs_Object * obj)
317540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
317640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = obj->myDev;
317740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int lowest = -99;	/* Stop compiler whining. */
317840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
317940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ChunkCache *cache;
318040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkWritten = 0;
318140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nCaches = obj->myDev->nShortOpCaches;
318240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
318340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (nCaches > 0) {
318440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		do {
318540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			cache = NULL;
318640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
318740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Find the dirty cache for this object with the lowest chunk id. */
318840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = 0; i < nCaches; i++) {
318940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (dev->srCache[i].object == obj &&
319040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    dev->srCache[i].dirty) {
319140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (!cache
319240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    || dev->srCache[i].chunkId <
319340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    lowest) {
319440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						cache = &dev->srCache[i];
319540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						lowest = cache->chunkId;
319640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
319740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
319840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
319940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
320040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (cache && !cache->locked) {
320140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Write it out and free it up */
320240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
320340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				chunkWritten =
320440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_WriteChunkDataToObject(cache->object,
320540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								 cache->chunkId,
320640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								 cache->data,
320740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								 cache->nBytes,
320840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								 1);
320940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				cache->dirty = 0;
321040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				cache->object = NULL;
321140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
321240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
321340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} while (cache && chunkWritten > 0);
321440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
321540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (cache) {
321640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Hoosterman, disk full while writing cache out. */
321740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ERROR,
321840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("yaffs tragedy: no space during cache write" TENDSTR)));
321940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
322040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
322140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
322240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
322340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
322440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
322540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*yaffs_FlushEntireDeviceCache(dev)
322640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
322740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
322840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
322940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
323040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_FlushEntireDeviceCache(yaffs_Device *dev)
323140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
323240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *obj;
323340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nCaches = dev->nShortOpCaches;
323440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
323540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
323640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Find a dirty object in the cache and flush it...
323740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * until there are no further dirty objects.
323840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
323940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	do {
324040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj = NULL;
324140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for( i = 0; i < nCaches && !obj; i++) {
324240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->srCache[i].object &&
324340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    dev->srCache[i].dirty)
324440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				obj = dev->srCache[i].object;
324540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
324640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
324740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(obj)
324840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_FlushFilesChunkCache(obj);
324940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
325040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} while(obj);
325140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
325240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
325340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
325440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
325540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Grab us a cache chunk for use.
325640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * First look for an empty one.
325740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Then look for the least recently used non-dirty one.
325840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Then look for the least recently used dirty one...., flush and look again.
325940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
326040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev)
326140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
326240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
326340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int usage;
326440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int theOne;
326540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
326640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nShortOpCaches > 0) {
326740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < dev->nShortOpCaches; i++) {
326840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!dev->srCache[i].object)
326940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				return &dev->srCache[i];
327040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
327140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
327240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
327340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
327440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		theOne = -1;
327540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		usage = 0;	/* just to stop the compiler grizzling */
327640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
327740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < dev->nShortOpCaches; i++) {
327840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!dev->srCache[i].dirty &&
327940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    ((dev->srCache[i].lastUse < usage && theOne >= 0) ||
328040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     theOne < 0)) {
328140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				usage = dev->srCache[i].lastUse;
328240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				theOne = i;
328340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
328440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
328540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
328640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
328740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return theOne >= 0 ? &dev->srCache[theOne] : NULL;
328840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
328940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
329040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
329140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
329240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
329340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
329440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)
329540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
329640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ChunkCache *cache;
329740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *theObj;
329840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int usage;
329940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
330040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pushout;
330140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
330240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nShortOpCaches > 0) {
330340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Try find a non-dirty one... */
330440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
330540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		cache = yaffs_GrabChunkCacheWorker(dev);
330640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
330740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (!cache) {
330840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* They were all dirty, find the last recently used object and flush
330940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * its cache, then  find again.
331040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * NB what's here is not very accurate, we actually flush the object
331140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * the last recently used page.
331240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
331340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
331440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* With locking we can't assume we can use entry zero */
331540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
331640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			theObj = NULL;
331740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			usage = -1;
331840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			cache = NULL;
331940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			pushout = -1;
332040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
332140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = 0; i < dev->nShortOpCaches; i++) {
332240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (dev->srCache[i].object &&
332340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    !dev->srCache[i].locked &&
332440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (dev->srCache[i].lastUse < usage || !cache))
332540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				{
332640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					usage = dev->srCache[i].lastUse;
332740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					theObj = dev->srCache[i].object;
332840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache = &dev->srCache[i];
332940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					pushout = i;
333040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
333140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
333240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
333340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!cache || cache->dirty) {
333440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Flush and try again */
333540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_FlushFilesChunkCache(theObj);
333640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				cache = yaffs_GrabChunkCacheWorker(dev);
333740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
333840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
333940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
334040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return cache;
334140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else
334240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
334340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
334440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
334540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
334640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Find a cached chunk */
334740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object * obj,
334840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					      int chunkId)
334940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
335040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = obj->myDev;
335140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
335240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nShortOpCaches > 0) {
335340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < dev->nShortOpCaches; i++) {
335440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->srCache[i].object == obj &&
335540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    dev->srCache[i].chunkId == chunkId) {
335640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->cacheHits++;
335740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
335840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				return &dev->srCache[i];
335940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
336040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
336140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
336240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return NULL;
336340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
336440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
336540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Mark the chunk for the least recently used algorithym */
336640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache,
336740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				int isAWrite)
336840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
336940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
337040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nShortOpCaches > 0) {
337140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->srLastUse < 0 || dev->srLastUse > 100000000) {
337240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Reset the cache usages */
337340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			int i;
337440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = 1; i < dev->nShortOpCaches; i++) {
337540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->srCache[i].lastUse = 0;
337640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
337740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->srLastUse = 0;
337840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
337940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
338040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->srLastUse++;
338140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
338240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		cache->lastUse = dev->srLastUse;
338340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
338440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (isAWrite) {
338540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			cache->dirty = 1;
338640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
338740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
338840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
338940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
339040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Invalidate a single cache page.
339140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Do this when a whole page gets written,
339240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * ie the short cache for this page is no longer valid.
339340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
339440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId)
339540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
339640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (object->myDev->nShortOpCaches > 0) {
339740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ChunkCache *cache = yaffs_FindChunkCache(object, chunkId);
339840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
339940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (cache) {
340040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			cache->object = NULL;
340140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
340240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
340340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
340440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
340540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* Invalidate all the cache pages associated with this object
340640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Do this whenever ther file is deleted or resized.
340740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
340840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InvalidateWholeChunkCache(yaffs_Object * in)
340940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
341040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
341140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
341240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
341340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nShortOpCaches > 0) {
341440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Invalidate it. */
341540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < dev->nShortOpCaches; i++) {
341640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->srCache[i].object == in) {
341740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->srCache[i].object = NULL;
341840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
341940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
342040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
342140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
342240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
342340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*--------------------- Checkpointing --------------------*/
342440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
342540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
342640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
342740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
342840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckpointValidity cp;
342940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp.structType = sizeof(cp);
343040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp.magic = YAFFS_MAGIC;
343140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp.version = YAFFS_CHECKPOINT_VERSION;
343240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp.head = (head) ? 1 : 0;
343340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
343440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
343540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		1 : 0;
343640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
343740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
343840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)
343940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
344040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckpointValidity cp;
344140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok;
344240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
344340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
344440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
344540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
344640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = (cp.structType == sizeof(cp)) &&
344740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     (cp.magic == YAFFS_MAGIC) &&
344840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     (cp.version == YAFFS_CHECKPOINT_VERSION) &&
344940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     (cp.head == ((head) ? 1 : 0));
345040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok ? 1 : 0;
345140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
345240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
345340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
345440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   yaffs_Device *dev)
345540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
345640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->nErasedBlocks = dev->nErasedBlocks;
345740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->allocationBlock = dev->allocationBlock;
345840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->allocationPage = dev->allocationPage;
345940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->nFreeChunks = dev->nFreeChunks;
346040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
346140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->nDeletedFiles = dev->nDeletedFiles;
346240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->nUnlinkedFiles = dev->nUnlinkedFiles;
346340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->nBackgroundDeletions = dev->nBackgroundDeletions;
346440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->sequenceNumber = dev->sequenceNumber;
346540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->oldestDirtySequence = dev->oldestDirtySequence;
346640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
346740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
346840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
346940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
347040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   yaffs_CheckpointDevice *cp)
347140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
347240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nErasedBlocks = cp->nErasedBlocks;
347340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->allocationBlock = cp->allocationBlock;
347440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->allocationPage = cp->allocationPage;
347540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeChunks = cp->nFreeChunks;
347640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
347740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nDeletedFiles = cp->nDeletedFiles;
347840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nUnlinkedFiles = cp->nUnlinkedFiles;
347940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nBackgroundDeletions = cp->nBackgroundDeletions;
348040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->sequenceNumber = cp->sequenceNumber;
348140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->oldestDirtySequence = cp->oldestDirtySequence;
348240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
348340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
348440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
348540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteCheckpointDevice(yaffs_Device *dev)
348640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
348740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckpointDevice cp;
348840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 nBytes;
348940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
349040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
349140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok;
349240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
349340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Write device runtime values*/
349440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_DeviceToCheckpointDevice(&cp,dev);
349540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp.structType = sizeof(cp);
349640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
349740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
349840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
349940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Write block info */
350040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok) {
350140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nBytes = nBlocks * sizeof(yaffs_BlockInfo);
350240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes);
350340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
350440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
350540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Write chunk bits */
350640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok) {
350740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nBytes = nBlocks * dev->chunkBitmapStride;
350840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes);
350940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
351040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return	 ok ? 1 : 0;
351140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
351240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
351340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
351440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ReadCheckpointDevice(yaffs_Device *dev)
351540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
351640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckpointDevice cp;
351740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 nBytes;
351840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
351940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
352040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok;
352140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
352240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
352340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!ok)
352440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
352540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
352640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(cp.structType != sizeof(cp))
352740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
352840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
352940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
353040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckpointDeviceToDevice(dev,&cp);
353140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
353240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nBytes = nBlocks * sizeof(yaffs_BlockInfo);
353340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
353440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes);
353540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
353640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!ok)
353740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
353840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nBytes = nBlocks * dev->chunkBitmapStride;
353940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
354040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes);
354140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
354240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok ? 1 : 0;
354340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
354440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
354540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,
354640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   yaffs_Object *obj)
354740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
354840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
354940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->objectId = obj->objectId;
355040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
355140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->chunkId = obj->chunkId;
355240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->variantType = obj->variantType;
355340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->deleted = obj->deleted;
355440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->softDeleted = obj->softDeleted;
355540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->unlinked = obj->unlinked;
355640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->fake = obj->fake;
355740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->renameAllowed = obj->renameAllowed;
355840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->unlinkAllowed = obj->unlinkAllowed;
355940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->serial = obj->serial;
356040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp->nDataChunks = obj->nDataChunks;
356140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
356240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
356340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize;
356440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
356540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId;
356640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
356740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
356840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp)
356940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
357040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
357140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *parent;
357240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
357340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->objectId = cp->objectId;
357440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
357540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(cp->parentId)
357640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		parent = yaffs_FindOrCreateObjectByNumber(
357740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					obj->myDev,
357840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cp->parentId,
357940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					YAFFS_OBJECT_TYPE_DIRECTORY);
358040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
358140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		parent = NULL;
358240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
358340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(parent)
358440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_AddObjectToDirectory(parent, obj);
358540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
358640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->chunkId = cp->chunkId;
358740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->variantType = cp->variantType;
358840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->deleted = cp->deleted;
358940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->softDeleted = cp->softDeleted;
359040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->unlinked = cp->unlinked;
359140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->fake = cp->fake;
359240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->renameAllowed = cp->renameAllowed;
359340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->unlinkAllowed = cp->unlinkAllowed;
359440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->serial = cp->serial;
359540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->nDataChunks = cp->nDataChunks;
359640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
359740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
359840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
359940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
360040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
360140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
360240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
360340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->lazyLoaded = 1;
360440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
360540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
360640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
360740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
360840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn,
360940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  	__u32 level, int chunkOffset)
361040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
361140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
361240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
361340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok = 1;
361440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
361540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
361640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tn) {
361740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (level > 0) {
361840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
361940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){
362040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (tn->internal[i]) {
362140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					ok = yaffs_CheckpointTnodeWorker(in,
362240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							tn->internal[i],
362340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							level - 1,
362440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							(chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);
362540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
362640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
362740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (level == 0) {
362840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			__u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
362940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* printf("write tnode at %d\n",baseOffset); */
363040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
363140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if(ok)
363240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
363340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
363440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
363540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
363640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok;
363740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
363840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
363940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
364040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteCheckpointTnodes(yaffs_Object *obj)
364140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
364240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 endMarker = ~0;
364340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok = 1;
364440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
364540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){
364640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_CheckpointTnodeWorker(obj,
364740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    obj->variant.fileVariant.top,
364840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    obj->variant.fileVariant.topLevel,
364940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    0);
365040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(ok)
365140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
365240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				sizeof(endMarker));
365340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
365440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
365540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok ? 1 : 0;
365640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
365740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
365840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
365940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
366040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u32 baseChunk;
366140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok = 1;
366240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = obj->myDev;
366340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
366440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tnode *tn;
366540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
366640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
366740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
366840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while(ok && (~baseChunk)){
366940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Read level 0 tnode */
367040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
367140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* printf("read  tnode at %d\n",baseChunk); */
367240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tn = yaffs_GetTnodeRaw(dev);
367340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(tn)
367440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
367540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
367640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else
367740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ok = 0;
367840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
367940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(tn && ok){
368040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ok = yaffs_AddOrFindLevel0Tnode(dev,
368140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       		fileStructPtr,
368240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       		baseChunk,
368340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       		tn) ? 1 : 0;
368440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
368540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
368640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(ok)
368740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
368840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
368940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
369040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
369140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok ? 1 : 0;
369240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
369340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
369440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
369540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
369640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
369740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *obj;
369840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckpointObject cp;
369940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
370040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok = 1;
370140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct list_head *lh;
370240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
370340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
370440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Iterate through the objects in each hash entry,
370540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * dumping them to the checkpointing stream.
370640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
370740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
370840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
370940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 	list_for_each(lh, &dev->objectBucket[i].list) {
371040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (lh) {
371140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				obj = list_entry(lh, yaffs_Object, hashLink);
371240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!obj->deferedFree) {
371340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_ObjectToCheckpointObject(&cp,obj);
371440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cp.structType = sizeof(cp);
371540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* printf("Write out object %d type %d\n",obj->objectId,obj->variantType); */
371640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
371740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
371840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
371940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						ok = yaffs_WriteCheckpointTnodes(obj);
372040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
372140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
372240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
372340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
372440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 }
372540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
372640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 /* Dump end of list */
372740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	memset(&cp,0xFF,sizeof(yaffs_CheckpointObject));
372840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	cp.structType = sizeof(cp);
372940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
373040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
373140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
373240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
373340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok ? 1 : 0;
373440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
373540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
373640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
373740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
373840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *obj;
373940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckpointObject cp;
374040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok = 1;
374140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int done = 0;
374240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *hardList = NULL;
374340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
374440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while(ok && !done) {
374540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
374640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(cp.structType != sizeof(cp)) {
374740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* printf("structure parsing failed\n"); */
374840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ok = 0;
374940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
375040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
375140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(ok && cp.objectId == ~0)
375240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			done = 1;
375340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else if(ok){
375440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_CHECKPOINT,(TSTR("Read object %d parent %d type %d" TENDSTR),
375540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				cp.objectId,cp.parentId,cp.variantType));
375640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
375740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if(obj) {
375840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_CheckpointObjectToObject(obj,&cp);
375940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
376040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					ok = yaffs_ReadCheckpointTnodes(obj);
376140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
376240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					obj->hardLinks.next =
376340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    (struct list_head *)
376440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    hardList;
376540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					hardList = obj;
376640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
376740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
376840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
376940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
377040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
377140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
377240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
377340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_HardlinkFixup(dev,hardList);
377440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
377540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok ? 1 : 0;
377640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
377740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
377840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteCheckpointData(yaffs_Device *dev)
377940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
378040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
378140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok;
378240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
378340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = yaffs_CheckpointOpen(dev,1);
378440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
378540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
378640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_WriteCheckpointValidityMarker(dev,1);
378740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
378840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_WriteCheckpointDevice(dev);
378940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
379040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_WriteCheckpointObjects(dev);
379140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
379240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_WriteCheckpointValidityMarker(dev,0);
379340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
379440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!yaffs_CheckpointClose(dev))
379540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 ok = 0;
379640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
379740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
379840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    	dev->isCheckpointed = 1;
379940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 else
380040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 	dev->isCheckpointed = 0;
380140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
380240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return dev->isCheckpointed;
380340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
380440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
380540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ReadCheckpointData(yaffs_Device *dev)
380640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
380740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int ok;
380840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
380940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ok = yaffs_CheckpointOpen(dev,0); /* open for read */
381040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
381140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
381240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_ReadCheckpointValidityMarker(dev,1);
381340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
381440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_ReadCheckpointDevice(dev);
381540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
381640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_ReadCheckpointObjects(dev);
381740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
381840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = yaffs_ReadCheckpointValidityMarker(dev,0);
381940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
382040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
382140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
382240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!yaffs_CheckpointClose(dev))
382340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ok = 0;
382440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
382540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(ok)
382640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    	dev->isCheckpointed = 1;
382740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 else
382840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 	dev->isCheckpointed = 0;
382940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
383040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return ok ? 1 : 0;
383140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
383240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
383340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
383440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
383540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
383640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(dev->isCheckpointed ||
383740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   dev->blocksInCheckpoint > 0){
383840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->isCheckpointed = 0;
383940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_CheckpointInvalidateStream(dev);
384040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(dev->superBlock && dev->markSuperBlockDirty)
384140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->markSuperBlockDirty(dev->superBlock);
384240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
384340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
384440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
384540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
384640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckpointSave(yaffs_Device *dev)
384740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
384840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
384940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
385040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!dev->isCheckpointed)
385140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_WriteCheckpointData(dev);
385240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
385340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
385440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
385540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return dev->isCheckpointed;
385640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
385740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
385840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckpointRestore(yaffs_Device *dev)
385940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
386040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retval;
386140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
386240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
386340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	retval = yaffs_ReadCheckpointData(dev);
386440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
386540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
386640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
386740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retval;
386840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
386940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
387040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*--------------------- File read/write ------------------------
387140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Read and write have very similar structures.
387240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * In general the read/write has three parts to it
387340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * An incomplete chunk to start with (if the read/write is not chunk-aligned)
387440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Some complete chunks
387540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * An incomplete chunk to end off with
387640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
387740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Curve-balls: the first chunk might also be the last chunk.
387840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
387940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
388040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
388140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   int nBytes)
388240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
388340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
388440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunk;
388540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int start;
388640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nToCopy;
388740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int n = nBytes;
388840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nDone = 0;
388940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ChunkCache *cache;
389040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
389140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev;
389240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
389340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev = in->myDev;
389440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
389540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (n > 0) {
389640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		//chunk = offset / dev->nDataBytesPerChunk + 1;
389740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		//start = offset % dev->nDataBytesPerChunk;
389840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_AddrToChunk(dev,offset,&chunk,&start);
389940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		chunk++;
390040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
390140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* OK now check for the curveball where the start and end are in
390240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * the same chunk.
390340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
390440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if ((start + n) < dev->nDataBytesPerChunk) {
390540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy = n;
390640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
390740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy = dev->nDataBytesPerChunk - start;
390840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
390940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
391040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		cache = yaffs_FindChunkCache(in, chunk);
391140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
391240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* If the chunk is already in the cache or it is less than a whole chunk
391340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * then use the cache (if there is caching)
391440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * else bypass the cache.
391540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
391640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (cache || nToCopy != dev->nDataBytesPerChunk) {
391740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->nShortOpCaches > 0) {
391840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
391940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* If we can't find the data in the cache, then load it up. */
392040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
392140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!cache) {
392240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache = yaffs_GrabChunkCache(in->myDev);
392340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->object = in;
392440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->chunkId = chunk;
392540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->dirty = 0;
392640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->locked = 0;
392740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_ReadChunkDataFromObject(in, chunk,
392840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      cache->
392940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      data);
393040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->nBytes = 0;
393140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
393240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
393340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_UseChunkCache(dev, cache, 0);
393440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
393540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				cache->locked = 1;
393640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
393740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
393840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yfsd_UnlockYAFFS(TRUE);
393940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
394040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				memcpy(buffer, &cache->data[start], nToCopy);
394140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
394240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
394340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yfsd_LockYAFFS(TRUE);
394440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
394540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				cache->locked = 0;
394640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
394740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* Read into the local buffer then copy..*/
394840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
394940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				__u8 *localBuffer =
395040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_GetTempBuffer(dev, __LINE__);
395140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ReadChunkDataFromObject(in, chunk,
395240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							      localBuffer);
395340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
395440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yfsd_UnlockYAFFS(TRUE);
395540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
395640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				memcpy(buffer, &localBuffer[start], nToCopy);
395740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
395840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
395940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yfsd_LockYAFFS(TRUE);
396040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
396140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ReleaseTempBuffer(dev, localBuffer,
396240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							__LINE__);
396340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
396440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
396540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
396640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
396740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			__u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
396840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
396940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Under WinCE can't do direct transfer. Need to use a local buffer.
397040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * This is because we otherwise screw up WinCE's memory mapper
397140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
397240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
397340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
397440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
397540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yfsd_UnlockYAFFS(TRUE);
397640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
397740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
397840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
397940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
398040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yfsd_LockYAFFS(TRUE);
398140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
398240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
398340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
398440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
398540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* A full chunk. Read directly into the supplied buffer. */
398640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ReadChunkDataFromObject(in, chunk, buffer);
398740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
398840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
398940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
399040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		n -= nToCopy;
399140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		offset += nToCopy;
399240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		buffer += nToCopy;
399340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nDone += nToCopy;
399440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
399540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
399640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
399740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nDone;
399840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
399940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
400040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
400140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  int nBytes, int writeThrough)
400240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
400340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
400440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunk;
400540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int start;
400640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nToCopy;
400740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int n = nBytes;
400840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nDone = 0;
400940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nToWriteBack;
401040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int startOfWrite = offset;
401140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkWritten = 0;
401240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBytesRead;
401340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
401440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev;
401540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
401640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev = in->myDev;
401740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
401840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (n > 0 && chunkWritten >= 0) {
401940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		//chunk = offset / dev->nDataBytesPerChunk + 1;
402040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		//start = offset % dev->nDataBytesPerChunk;
402140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_AddrToChunk(dev,offset,&chunk,&start);
402240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		chunk++;
402340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
402440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* OK now check for the curveball where the start and end are in
402540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * the same chunk.
402640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
402740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
402840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if ((start + n) < dev->nDataBytesPerChunk) {
402940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy = n;
403040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
403140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Now folks, to calculate how many bytes to write back....
403240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * If we're overwriting and not writing to then end of file then
403340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * we need to write back as much as was there before.
403440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
403540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
403640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nBytesRead =
403740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    in->variant.fileVariant.fileSize -
403840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    ((chunk - 1) * dev->nDataBytesPerChunk);
403940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
404040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (nBytesRead > dev->nDataBytesPerChunk) {
404140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				nBytesRead = dev->nDataBytesPerChunk;
404240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
404340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
404440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToWriteBack =
404540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (nBytesRead >
404640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     (start + n)) ? nBytesRead : (start + n);
404740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
404840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
404940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy = dev->nDataBytesPerChunk - start;
405040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToWriteBack = dev->nDataBytesPerChunk;
405140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
405240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
405340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (nToCopy != dev->nDataBytesPerChunk) {
405440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* An incomplete start or end chunk (or maybe both start and end chunk) */
405540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->nShortOpCaches > 0) {
405640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ChunkCache *cache;
405740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* If we can't find the data in the cache, then load the cache */
405840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				cache = yaffs_FindChunkCache(in, chunk);
405940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
406040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!cache
406140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    && yaffs_CheckSpaceForAllocation(in->
406240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								     myDev)) {
406340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache = yaffs_GrabChunkCache(in->myDev);
406440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->object = in;
406540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->chunkId = chunk;
406640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->dirty = 0;
406740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->locked = 0;
406840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_ReadChunkDataFromObject(in, chunk,
406940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      cache->
407040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      data);
407140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
407240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				else if(cache &&
407340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				        !cache->dirty &&
407440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					!yaffs_CheckSpaceForAllocation(in->myDev)){
407540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Drop the cache if it was a read cache item and
407640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * no space check has been made for it.
407740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
407840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 cache = NULL;
407940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
408040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
408140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (cache) {
408240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_UseChunkCache(dev, cache, 1);
408340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->locked = 1;
408440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
408540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yfsd_UnlockYAFFS(TRUE);
408640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
408740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
408840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					memcpy(&cache->data[start], buffer,
408940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       nToCopy);
409040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
409140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
409240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yfsd_LockYAFFS(TRUE);
409340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
409440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->locked = 0;
409540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					cache->nBytes = nToWriteBack;
409640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
409740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (writeThrough) {
409840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						chunkWritten =
409940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    yaffs_WriteChunkDataToObject
410040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    (cache->object,
410140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     cache->chunkId,
410240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     cache->data, cache->nBytes,
410340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     1);
410440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						cache->dirty = 0;
410540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
410640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
410740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else {
410840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					chunkWritten = -1;	/* fail the write */
410940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
411040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
411140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* An incomplete start or end chunk (or maybe both start and end chunk)
411240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Read into the local buffer then copy, then copy over and write back.
411340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
411440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
411540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				__u8 *localBuffer =
411640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_GetTempBuffer(dev, __LINE__);
411740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
411840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ReadChunkDataFromObject(in, chunk,
411940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							      localBuffer);
412040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
412140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
412240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yfsd_UnlockYAFFS(TRUE);
412340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
412440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
412540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				memcpy(&localBuffer[start], buffer, nToCopy);
412640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
412740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
412840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yfsd_LockYAFFS(TRUE);
412940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
413040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				chunkWritten =
413140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_WriteChunkDataToObject(in, chunk,
413240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								 localBuffer,
413340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								 nToWriteBack,
413440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								 0);
413540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
413640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ReleaseTempBuffer(dev, localBuffer,
413740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							__LINE__);
413840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
413940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
414040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
414140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
414240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
414340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
414440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Under WinCE can't do direct transfer. Need to use a local buffer.
414540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * This is because we otherwise screw up WinCE's memory mapper
414640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
414740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			__u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
414840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
414940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yfsd_UnlockYAFFS(TRUE);
415040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
415140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
415240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
415340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yfsd_LockYAFFS(TRUE);
415440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
415540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			chunkWritten =
415640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
415740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 dev->nDataBytesPerChunk,
415840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 0);
415940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
416040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
416140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* A full chunk. Write directly from the supplied buffer. */
416240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			chunkWritten =
416340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_WriteChunkDataToObject(in, chunk, buffer,
416440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 dev->nDataBytesPerChunk,
416540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 0);
416640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
416740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Since we've overwritten the cached data, we better invalidate it. */
416840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_InvalidateChunkCache(in, chunk);
416940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
417040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
417140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (chunkWritten >= 0) {
417240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			n -= nToCopy;
417340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			offset += nToCopy;
417440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			buffer += nToCopy;
417540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nDone += nToCopy;
417640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
417740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
417840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
417940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
418040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Update file object */
418140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
418240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize) {
418340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->variant.fileVariant.fileSize = (startOfWrite + nDone);
418440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
418540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
418640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	in->dirty = 1;
418740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
418840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nDone;
418940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
419040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
419140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
419240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* ---------------------- File resizing stuff ------------------ */
419340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
419440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_PruneResizedChunks(yaffs_Object * in, int newSize)
419540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
419640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
419740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
419840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int oldFileSize = in->variant.fileVariant.fileSize;
419940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
420040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int lastDel = 1 + (oldFileSize - 1) / dev->nDataBytesPerChunk;
420140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
420240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int startDel = 1 + (newSize + dev->nDataBytesPerChunk - 1) /
420340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    dev->nDataBytesPerChunk;
420440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
420540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkId;
420640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
420740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Delete backwards so that we don't end up with holes if
420840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * power is lost part-way through the operation.
420940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
421040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = lastDel; i >= startDel; i--) {
421140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* NB this could be optimised somewhat,
421240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * eg. could retrieve the tags and write them without
421340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * using yaffs_DeleteChunk
421440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
421540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
421640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		chunkId = yaffs_FindAndDeleteChunkInFile(in, i, NULL);
421740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (chunkId > 0) {
421840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (chunkId <
421940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (dev->internalStartBlock * dev->nChunksPerBlock)
422040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    || chunkId >=
422140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    ((dev->internalEndBlock +
422240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      1) * dev->nChunksPerBlock)) {
422340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ALWAYS,
422440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR("Found daft chunkId %d for %d" TENDSTR),
422540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   chunkId, i));
422640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
422740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				in->nDataChunks--;
422840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DeleteChunk(dev, chunkId, 1, __LINE__);
422940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
423040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
423140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
423240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
423340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
423440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
423540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)
423640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
423740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
423840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int oldFileSize = in->variant.fileVariant.fileSize;
423940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int newSizeOfPartialChunk;
424040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int newFullChunks;
424140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
424240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
424340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
424440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk);
424540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
424640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_FlushFilesChunkCache(in);
424740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InvalidateWholeChunkCache(in);
424840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
424940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckGarbageCollection(dev);
425040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
425140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
425240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_GetFileSize(in);
425340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
425440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
425540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (newSize == oldFileSize) {
425640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return oldFileSize;
425740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
425840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
425940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (newSize < oldFileSize) {
426040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
426140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_PruneResizedChunks(in, newSize);
426240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
426340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (newSizeOfPartialChunk != 0) {
426440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			int lastChunk = 1 + newFullChunks;
426540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
426640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			__u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
426740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
426840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Got to read and rewrite the last chunk with its new size and zero pad */
426940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ReadChunkDataFromObject(in, lastChunk,
427040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						      localBuffer);
427140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
427240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			memset(localBuffer + newSizeOfPartialChunk, 0,
427340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			       dev->nDataBytesPerChunk - newSizeOfPartialChunk);
427440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
427540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_WriteChunkDataToObject(in, lastChunk, localBuffer,
427640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     newSizeOfPartialChunk, 1);
427740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
427840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
427940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
428040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
428140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->variant.fileVariant.fileSize = newSize;
428240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
428340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_PruneFileStructure(dev, &in->variant.fileVariant);
428440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
428540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Write a new object header.
428640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * show we've shrunk the file, if need be
428740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Do this only if the file is not in the deleted directories.
428840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
428940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
429040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    in->parent->objectId != YAFFS_OBJECTID_DELETED) {
429140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_UpdateObjectHeader(in, NULL, 0,
429240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 (newSize < oldFileSize) ? 1 : 0, 0);
429340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
429440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
429540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return newSize;
429640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
429740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
429840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectloff_t yaffs_GetFileSize(yaffs_Object * obj)
429940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
430040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj = yaffs_GetEquivalentObject(obj);
430140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
430240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	switch (obj->variantType) {
430340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_FILE:
430440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return obj->variant.fileVariant.fileSize;
430540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_SYMLINK:
430640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_strlen(obj->variant.symLinkVariant.alias);
430740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	default:
430840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
430940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
431040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
431140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
431240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
431340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
431440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_FlushFile(yaffs_Object * in, int updateTime)
431540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
431640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal;
431740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in->dirty) {
431840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_FlushFilesChunkCache(in);
431940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (updateTime) {
432040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
432140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yfsd_WinFileTimeNow(in->win_mtime);
432240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
432340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
432440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->yst_mtime = Y_CURRENT_TIME;
432540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
432640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
432740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
432840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
432940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal =
433040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >=
433140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     0) ? YAFFS_OK : YAFFS_FAIL;
433240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
433340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal = YAFFS_OK;
433440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
433540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
433640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retVal;
433740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
433840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
433940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
434040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_DoGenericObjectDeletion(yaffs_Object * in)
434140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
434240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
434340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* First off, invalidate the file's data in the cache, without flushing. */
434440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InvalidateWholeChunkCache(in);
434540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
434640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
434740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Move to the unlinked directory so we have a record that it was deleted. */
434840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ChangeObjectName(in, in->myDev->deletedDir, NULL, 0, 0);
434940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
435040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
435140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
435240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_RemoveObjectFromDirectory(in);
435340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
435440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	in->chunkId = -1;
435540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
435640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_FreeObject(in);
435740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
435840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
435940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
436040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
436140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* yaffs_DeleteFile deletes the whole file data
436240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * and the inode associated with the file.
436340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * It does not delete the links associated with the file.
436440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
436540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_UnlinkFile(yaffs_Object * in)
436640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
436740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
436840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal;
436940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int immediateDeletion = 0;
437040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
437140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (1) {
437240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef __KERNEL__
437340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (!in->myInode) {
437440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			immediateDeletion = 1;
437540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
437640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
437740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
437840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (in->inUse <= 0) {
437940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			immediateDeletion = 1;
438040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
438140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
438240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
438340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (immediateDeletion) {
438440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retVal =
438540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_ChangeObjectName(in, in->myDev->deletedDir,
438640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   NULL, 0, 0);
438740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_TRACING,
438840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
438940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			   in->objectId));
439040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->deleted = 1;
439140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->myDev->nDeletedFiles++;
439240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (0 && in->myDev->isYaffs2) {
439340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_ResizeFile(in, 0);
439440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
439540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_SoftDeleteFile(in);
439640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
439740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retVal =
439840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
439940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   NULL, 0, 0);
440040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
440140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
440240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
440340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retVal;
440440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
440540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
440640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_DeleteFile(yaffs_Object * in)
440740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
440840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal = YAFFS_OK;
440940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
441040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (in->nDataChunks > 0) {
441140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Use soft deletion if there is data in the file */
441240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (!in->unlinked) {
441340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retVal = yaffs_UnlinkFile(in);
441440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
441540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
441640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->deleted = 1;
441740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			in->myDev->nDeletedFiles++;
441840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_SoftDeleteFile(in);
441940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
442040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return in->deleted ? YAFFS_OK : YAFFS_FAIL;
442140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
442240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* The file has no data chunks so we toss it immediately */
442340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
442440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->variant.fileVariant.top = NULL;
442540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DoGenericObjectDeletion(in);
442640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
442740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
442840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
442940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
443040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
443140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_DeleteDirectory(yaffs_Object * in)
443240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
443340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* First check that the directory is empty. */
443440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (list_empty(&in->variant.directoryVariant.children)) {
443540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_DoGenericObjectDeletion(in);
443640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
443740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
443840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_FAIL;
443940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
444040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
444140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
444240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_DeleteSymLink(yaffs_Object * in)
444340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
444440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YFREE(in->variant.symLinkVariant.alias);
444540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
444640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_DoGenericObjectDeletion(in);
444740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
444840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
444940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_DeleteHardLink(yaffs_Object * in)
445040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
445140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* remove this hardlink from the list assocaited with the equivalent
445240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * object
445340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
445440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_del(&in->hardLinks);
445540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_DoGenericObjectDeletion(in);
445640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
445740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
445840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_DestroyObject(yaffs_Object * obj)
445940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
446040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	switch (obj->variantType) {
446140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_FILE:
446240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeleteFile(obj);
446340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
446440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_DIRECTORY:
446540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeleteDirectory(obj);
446640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
446740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_SYMLINK:
446840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeleteSymLink(obj);
446940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
447040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_HARDLINK:
447140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeleteHardLink(obj);
447240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
447340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_SPECIAL:
447440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DoGenericObjectDeletion(obj);
447540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
447640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_UNKNOWN:
447740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;		/* should not happen. */
447840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
447940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
448040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
448140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_UnlinkWorker(yaffs_Object * obj)
448240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
448340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
448440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
448540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_DeleteHardLink(obj);
448640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else if (!list_empty(&obj->hardLinks)) {
448740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Curve ball: We're unlinking an object that has a hardlink.
448840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 *
448940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * This problem arises because we are not strictly following
449040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * The Linux link/inode model.
449140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 *
449240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * We can't really delete the object.
449340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * Instead, we do the following:
449440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * - Select a hardlink.
449540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * - Unhook it from the hard links
449640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * - Unhook it from its parent directory (so that the rename can work)
449740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * - Rename the object to the hardlink's name.
449840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * - Delete the hardlink
449940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
450040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
450140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_Object *hl;
450240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int retVal;
450340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
450440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
450540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
450640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
450740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list_del_init(&hl->hardLinks);
450840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list_del_init(&hl->siblings);
450940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
451040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
451140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
451240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
451340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
451440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (retVal == YAFFS_OK) {
451540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retVal = yaffs_DoGenericObjectDeletion(hl);
451640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
451740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return retVal;
451840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
451940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
452040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		switch (obj->variantType) {
452140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_FILE:
452240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return yaffs_UnlinkFile(obj);
452340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
452440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_DIRECTORY:
452540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return yaffs_DeleteDirectory(obj);
452640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
452740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SYMLINK:
452840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return yaffs_DeleteSymLink(obj);
452940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
453040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_SPECIAL:
453140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return yaffs_DoGenericObjectDeletion(obj);
453240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
453340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_HARDLINK:
453440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_OBJECT_TYPE_UNKNOWN:
453540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		default:
453640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return YAFFS_FAIL;
453740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
453840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
453940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
454040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
454140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
454240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_UnlinkObject( yaffs_Object *obj)
454340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
454440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
454540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj && obj->unlinkAllowed) {
454640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_UnlinkWorker(obj);
454740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
454840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
454940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_FAIL;
455040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
455140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
455240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_Unlink(yaffs_Object * dir, const YCHAR * name)
455340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
455440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *obj;
455540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
455640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj = yaffs_FindObjectByName(dir, name);
455740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_UnlinkObject(obj);
455840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
455940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
456040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*----------------------- Initialisation Scanning ---------------------- */
456140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
456240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId,
456340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       int backwardScanning)
456440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
456540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *obj;
456640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
456740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!backwardScanning) {
456840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Handle YAFFS1 forward scanning case
456940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * For YAFFS1 we always do the deletion
457040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
457140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
457240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
457340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Handle YAFFS2 case (backward scanning)
457440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * If the shadowed object exists then ignore.
457540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
457640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (yaffs_FindObjectByNumber(dev, objId)) {
457740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return;
457840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
457940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
458040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
458140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Let's create it (if it does not exist) assuming it is a file so that it can do shrinking etc.
458240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * We put it in unlinked dir to be cleaned up after the scanning
458340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
458440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj =
458540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_FindOrCreateObjectByNumber(dev, objId,
458640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     YAFFS_OBJECT_TYPE_FILE);
458740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_AddObjectToDirectory(dev->unlinkedDir, obj);
458840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->variant.fileVariant.shrinkSize = 0;
458940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->valid = 1;		/* So that we don't read any other info for this file */
459040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
459140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
459240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
459340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct {
459440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int seq;
459540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int block;
459640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} yaffs_BlockIndex;
459740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
459840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
459940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList)
460040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
460140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *hl;
460240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *in;
460340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
460440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while (hardList) {
460540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		hl = hardList;
460640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		hardList = (yaffs_Object *) (hardList->hardLinks.next);
460740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
460840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in = yaffs_FindObjectByNumber(dev,
460940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					      hl->variant.hardLinkVariant.
461040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					      equivalentObjectId);
461140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
461240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (in) {
461340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Add the hardlink pointers */
461440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			hl->variant.hardLinkVariant.equivalentObject = in;
461540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			list_add(&hl->hardLinks, &in->hardLinks);
461640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
461740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Todo Need to report/handle this better.
461840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * Got a problem... hardlink to a non-existant object
461940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
462040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			hl->variant.hardLinkVariant.equivalentObject = NULL;
462140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			INIT_LIST_HEAD(&hl->hardLinks);
462240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
462340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
462440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
462540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
462640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
462740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
462840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
462940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
463040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
463140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
463240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
463340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int ybicmp(const void *a, const void *b){
463440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    register int aseq = ((yaffs_BlockIndex *)a)->seq;
463540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    register int bseq = ((yaffs_BlockIndex *)b)->seq;
463640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    register int ablock = ((yaffs_BlockIndex *)a)->block;
463740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    register int bblock = ((yaffs_BlockIndex *)b)->block;
463840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    if( aseq == bseq )
463940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project        return ablock - bblock;
464040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    else
464140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project        return aseq - bseq;
464240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
464340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
464440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
464540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_Scan(yaffs_Device * dev)
464640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
464740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
464840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blk;
464940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blockIterator;
465040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int startIterator;
465140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int endIterator;
465240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocksToScan = 0;
465340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int result;
465440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
465540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunk;
465640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int c;
465740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int deleted;
465840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockState state;
465940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *hardList = NULL;
466040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *hl;
466140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
466240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int sequenceNumber;
466340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ObjectHeader *oh;
466440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *in;
466540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *parent;
466640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
466740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
466840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *chunkData;
466940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
467040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockIndex *blockIndex = NULL;
467140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
467240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isYaffs2) {
467340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_SCAN,
467440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
467540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
467640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
467740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
467840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	//TODO  Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
467940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
468040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_SCAN,
468140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR),
468240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   dev->internalStartBlock, dev->internalEndBlock));
468340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
468440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	chunkData = yaffs_GetTempBuffer(dev, __LINE__);
468540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
468640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
468740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
468840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isYaffs2) {
468940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
469040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
469140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
469240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Scan all the blocks to determine their state */
469340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
469440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi = yaffs_GetBlockInfo(dev, blk);
469540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ClearChunkBits(dev, blk);
469640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->pagesInUse = 0;
469740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->softDeletions = 0;
469840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
469940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
470040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
470140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->blockState = state;
470240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->sequenceNumber = sequenceNumber;
470340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
470440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_SCAN_DEBUG,
470540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
470640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   state, sequenceNumber));
470740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
470840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (state == YAFFS_BLOCK_STATE_DEAD) {
470940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_BAD_BLOCKS,
471040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("block %d is bad" TENDSTR), blk));
471140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (state == YAFFS_BLOCK_STATE_EMPTY) {
471240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_SCAN_DEBUG,
471340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("Block empty " TENDSTR)));
471440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->nErasedBlocks++;
471540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->nFreeChunks += dev->nChunksPerBlock;
471640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
471740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
471840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Determine the highest sequence number */
471940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->isYaffs2 &&
472040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
472140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
472240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
472340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				blockIndex[nBlocksToScan].seq = sequenceNumber;
472440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				blockIndex[nBlocksToScan].block = blk;
472540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
472640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				nBlocksToScan++;
472740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
472840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (sequenceNumber >= dev->sequenceNumber) {
472940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->sequenceNumber = sequenceNumber;
473040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
473140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (dev->isYaffs2) {
473240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* TODO: Nasty sequence number! */
473340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_SCAN,
473440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
473540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("Block scanning block %d has bad sequence number %d"
473640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), blk, sequenceNumber));
473740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
473840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
473940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
474040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
474140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
474240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Sort the blocks
474340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Dungy old bubble sort for now...
474440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
474540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isYaffs2) {
474640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_BlockIndex temp;
474740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int i;
474840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int j;
474940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
475040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < nBlocksToScan; i++)
475140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (j = i + 1; j < nBlocksToScan; j++)
475240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (blockIndex[i].seq > blockIndex[j].seq) {
475340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					temp = blockIndex[j];
475440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					blockIndex[j] = blockIndex[i];
475540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					blockIndex[i] = temp;
475640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
475740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
475840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
475940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now scan the blocks looking at the data. */
476040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isYaffs2) {
476140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		startIterator = 0;
476240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		endIterator = nBlocksToScan - 1;
476340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_SCAN_DEBUG,
476440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
476540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
476640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		startIterator = dev->internalStartBlock;
476740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		endIterator = dev->internalEndBlock;
476840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
476940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
477040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* For each block.... */
477140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (blockIterator = startIterator; blockIterator <= endIterator;
477240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     blockIterator++) {
477340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
477440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->isYaffs2) {
477540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* get the block to scan in the correct order */
477640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			blk = blockIndex[blockIterator].block;
477740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
477840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			blk = blockIterator;
477940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
478040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
478140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi = yaffs_GetBlockInfo(dev, blk);
478240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		state = bi->blockState;
478340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
478440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		deleted = 0;
478540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
478640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* For each chunk in each block that needs scanning....*/
478740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (c = 0; c < dev->nChunksPerBlock &&
478840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) {
478940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Read the tags and decide what to do */
479040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			chunk = blk * dev->nChunksPerBlock + c;
479140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
479240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
479340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							&tags);
479440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
479540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Let's have a good look at this chunk... */
479640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
479740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!dev->isYaffs2 && tags.chunkDeleted) {
479840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* YAFFS1 only...
479940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * A deleted chunk
480040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
480140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				deleted++;
480240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->nFreeChunks++;
480340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/*T((" %d %d deleted\n",blk,c)); */
480440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (!tags.chunkUsed) {
480540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* An unassigned chunk in the block
480640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * This means that either the block is empty or
480740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * this is the one being allocated from
480840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
480940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
481040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (c == 0) {
481140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* We're looking at the first chunk in the block so the block is unused */
481240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					state = YAFFS_BLOCK_STATE_EMPTY;
481340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->nErasedBlocks++;
481440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else {
481540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* this is the block being allocated from */
481640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					T(YAFFS_TRACE_SCAN,
481740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  (TSTR
481840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   (" Allocating from %d %d" TENDSTR),
481940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   blk, c));
482040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					state = YAFFS_BLOCK_STATE_ALLOCATING;
482140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->allocationBlock = blk;
482240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->allocationPage = c;
482340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->allocationBlockFinder = blk;
482440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Set it to here to encourage the allocator to go forth from here. */
482540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
482640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Yaffs2 sanity check:
482740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * This should be the one with the highest sequence number
482840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
482940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (dev->isYaffs2
483040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    && (dev->sequenceNumber !=
483140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						bi->sequenceNumber)) {
483240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						T(YAFFS_TRACE_ALWAYS,
483340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  (TSTR
483440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   ("yaffs: Allocation block %d was not highest sequence id:"
483540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    " block seq = %d, dev seq = %d"
483640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
483740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
483840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
483940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
484040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->nFreeChunks += (dev->nChunksPerBlock - c);
484140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (tags.chunkId > 0) {
484240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* chunkId > 0 so it is a data chunk... */
484340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				unsigned int endpos;
484440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
484540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_SetChunkBit(dev, blk, c);
484640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				bi->pagesInUse++;
484740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
484840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				in = yaffs_FindOrCreateObjectByNumber(dev,
484940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      tags.
485040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      objectId,
485140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      YAFFS_OBJECT_TYPE_FILE);
485240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* PutChunkIntoFile checks for a clash (two data chunks with
485340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * the same chunkId).
485440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
485540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,
485640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						       1);
485740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				endpos =
485840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (tags.chunkId - 1) * dev->nDataBytesPerChunk +
485940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    tags.byteCount;
486040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (in->variantType == YAFFS_OBJECT_TYPE_FILE
486140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    && in->variant.fileVariant.scannedFileSize <
486240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    endpos) {
486340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->variant.fileVariant.
486440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    scannedFileSize = endpos;
486540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (!dev->useHeaderFileSize) {
486640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variant.fileVariant.
486740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    fileSize =
486840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    in->variant.fileVariant.
486940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    scannedFileSize;
487040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
487140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
487240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
487340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId));   */
487440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
487540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* chunkId == 0, so it is an ObjectHeader.
487640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Thus, we read in the object header and make the object
487740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
487840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_SetChunkBit(dev, blk, c);
487940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				bi->pagesInUse++;
488040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
488140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk,
488240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								chunkData,
488340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								NULL);
488440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
488540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				oh = (yaffs_ObjectHeader *) chunkData;
488640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
488740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				in = yaffs_FindObjectByNumber(dev,
488840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							      tags.objectId);
488940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (in && in->variantType != oh->type) {
489040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* This should not happen, but somehow
489140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * Wev'e ended up with an objectId that has been reused but not yet
489240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * deleted, and worse still it has changed type. Delete the old object.
489340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
489440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
489540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_DestroyObject(in);
489640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
489740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in = 0;
489840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
489940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
490040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				in = yaffs_FindOrCreateObjectByNumber(dev,
490140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      tags.
490240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      objectId,
490340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      oh->type);
490440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
490540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (oh->shadowsObject > 0) {
490640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_HandleShadowedObject(dev,
490740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   oh->
490840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   shadowsObject,
490940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								   0);
491040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
491140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
491240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (in->valid) {
491340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* We have already filled this one. We have a duplicate and need to resolve it. */
491440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
491540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					unsigned existingSerial = in->serial;
491640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					unsigned newSerial = tags.serialNumber;
491740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
491840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (dev->isYaffs2 ||
491940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    ((existingSerial + 1) & 3) ==
492040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    newSerial) {
492140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Use new one - destroy the exisiting one */
492240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_DeleteChunk(dev,
492340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								  in->chunkId,
492440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								  1, __LINE__);
492540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->valid = 0;
492640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					} else {
492740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Use existing - destroy this one. */
492840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_DeleteChunk(dev, chunk, 1,
492940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								  __LINE__);
493040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
493140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
493240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
493340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!in->valid &&
493440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (tags.objectId == YAFFS_OBJECTID_ROOT ||
493540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) {
493640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* We only load some info, don't fiddle with directory structure */
493740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->valid = 1;
493840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->variantType = oh->type;
493940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
494040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_mode = oh->yst_mode;
494140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
494240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_atime[0] = oh->win_atime[0];
494340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_ctime[0] = oh->win_ctime[0];
494440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_mtime[0] = oh->win_mtime[0];
494540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_atime[1] = oh->win_atime[1];
494640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_ctime[1] = oh->win_ctime[1];
494740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_mtime[1] = oh->win_mtime[1];
494840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
494940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_uid = oh->yst_uid;
495040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_gid = oh->yst_gid;
495140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_atime = oh->yst_atime;
495240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_mtime = oh->yst_mtime;
495340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_ctime = oh->yst_ctime;
495440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_rdev = oh->yst_rdev;
495540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
495640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->chunkId = chunk;
495740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
495840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else if (!in->valid) {
495940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* we need to load this info */
496040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
496140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->valid = 1;
496240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->variantType = oh->type;
496340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
496440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_mode = oh->yst_mode;
496540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
496640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_atime[0] = oh->win_atime[0];
496740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_ctime[0] = oh->win_ctime[0];
496840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_mtime[0] = oh->win_mtime[0];
496940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_atime[1] = oh->win_atime[1];
497040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_ctime[1] = oh->win_ctime[1];
497140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->win_mtime[1] = oh->win_mtime[1];
497240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
497340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_uid = oh->yst_uid;
497440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_gid = oh->yst_gid;
497540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_atime = oh->yst_atime;
497640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_mtime = oh->yst_mtime;
497740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_ctime = oh->yst_ctime;
497840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->yst_rdev = oh->yst_rdev;
497940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
498040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->chunkId = chunk;
498140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
498240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_SetObjectName(in, oh->name);
498340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->dirty = 0;
498440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
498540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* directory stuff...
498640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * hook up to parent
498740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
498840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
498940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					parent =
499040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    yaffs_FindOrCreateObjectByNumber
499140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    (dev, oh->parentObjectId,
499240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     YAFFS_OBJECT_TYPE_DIRECTORY);
499340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (parent->variantType ==
499440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    YAFFS_OBJECT_TYPE_UNKNOWN) {
499540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Set up as a directory */
499640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						parent->variantType =
499740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    YAFFS_OBJECT_TYPE_DIRECTORY;
499840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						INIT_LIST_HEAD(&parent->variant.
499940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							       directoryVariant.
500040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							       children);
500140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					} else if (parent->variantType !=
500240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   YAFFS_OBJECT_TYPE_DIRECTORY)
500340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					{
500440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Hoosterman, another problem....
500540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 * We're trying to use a non-directory as a directory
500640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 */
500740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
500840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						T(YAFFS_TRACE_ERROR,
500940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  (TSTR
501040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   ("yaffs tragedy: attempting to use non-directory as"
501140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    " a directory in scan. Put in lost+found."
501240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    TENDSTR)));
501340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						parent = dev->lostNFoundDir;
501440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
501540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
501640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_AddObjectToDirectory(parent, in);
501740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
501840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (0 && (parent == dev->deletedDir ||
501940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  parent == dev->unlinkedDir)) {
502040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->deleted = 1;	/* If it is unlinked at start up then it wants deleting */
502140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						dev->nDeletedFiles++;
502240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
502340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Note re hardlinks.
502440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * Since we might scan a hardlink before its equivalent object is scanned
502540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * we put them all in a list.
502640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * After scanning is complete, we should have all the objects, so we run through this
502740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * list and fix up all the chains.
502840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
502940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
503040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					switch (in->variantType) {
503140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_UNKNOWN:
503240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Todo got a problem */
503340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
503440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_FILE:
503540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (dev->isYaffs2
503640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    && oh->isShrink) {
503740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							/* Prune back the shrunken chunks */
503840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							yaffs_PruneResizedChunks
503940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    (in, oh->fileSize);
504040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							/* Mark the block as having a shrinkHeader */
504140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							bi->hasShrinkHeader = 1;
504240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
504340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
504440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (dev->useHeaderFileSize)
504540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
504640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							in->variant.fileVariant.
504740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    fileSize =
504840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    oh->fileSize;
504940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
505040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
505140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_HARDLINK:
505240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variant.hardLinkVariant.
505340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    equivalentObjectId =
505440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    oh->equivalentObjectId;
505540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->hardLinks.next =
505640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    (struct list_head *)
505740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    hardList;
505840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						hardList = in;
505940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
506040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_DIRECTORY:
506140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Do nothing */
506240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
506340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_SPECIAL:
506440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Do nothing */
506540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
506640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_SYMLINK:
506740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variant.symLinkVariant.
506840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    alias =
506940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    yaffs_CloneString(oh->alias);
507040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
507140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
507240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
507340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (parent == dev->deletedDir) {
507440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_DestroyObject(in);
507540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						bi->hasShrinkHeader = 1;
507640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
507740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
507840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
507940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
508040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
508140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
508240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* If we got this far while scanning, then the block is fully allocated.*/
508340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			state = YAFFS_BLOCK_STATE_FULL;
508440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
508540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
508640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->blockState = state;
508740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
508840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Now let's see if it was dirty */
508940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (bi->pagesInUse == 0 &&
509040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    !bi->hasShrinkHeader &&
509140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    bi->blockState == YAFFS_BLOCK_STATE_FULL) {
509240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_BlockBecameDirty(dev, blk);
509340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
509440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
509540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
509640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
509740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (blockIndex) {
509840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(blockIndex);
509940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
510040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
510140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
510240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Ok, we've done all the scanning.
510340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Fix up the hard link chains.
510440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * We should now have scanned all the objects, now it's time to add these
510540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * hardlinks.
510640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
510740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
510840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_HardlinkFixup(dev,hardList);
510940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
511040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Handle the unlinked files. Since they were left in an unlinked state we should
511140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * just delete them.
511240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
511340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
511440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		struct list_head *i;
511540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		struct list_head *n;
511640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
511740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_Object *l;
511840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Soft delete all the unlinked files */
511940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list_for_each_safe(i, n,
512040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   &dev->unlinkedDir->variant.directoryVariant.
512140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   children) {
512240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (i) {
512340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				l = list_entry(i, yaffs_Object, siblings);
512440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DestroyObject(l);
512540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
512640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
512740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
512840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
512940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
513040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
513140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
513240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
513340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
513440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
513540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
513640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
513740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
513840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *chunkData;
513940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ObjectHeader *oh;
514040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = in->myDev;
514140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
514240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int result;
514340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
514440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(in->lazyLoaded){
514540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->lazyLoaded = 0;
514640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		chunkData = yaffs_GetTempBuffer(dev, __LINE__);
514740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
514840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
514940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		oh = (yaffs_ObjectHeader *) chunkData;
515040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
515140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_mode = oh->yst_mode;
515240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
515340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_atime[0] = oh->win_atime[0];
515440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_ctime[0] = oh->win_ctime[0];
515540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_mtime[0] = oh->win_mtime[0];
515640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_atime[1] = oh->win_atime[1];
515740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_ctime[1] = oh->win_ctime[1];
515840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->win_mtime[1] = oh->win_mtime[1];
515940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
516040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_uid = oh->yst_uid;
516140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_gid = oh->yst_gid;
516240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_atime = oh->yst_atime;
516340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_mtime = oh->yst_mtime;
516440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_ctime = oh->yst_ctime;
516540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		in->yst_rdev = oh->yst_rdev;
516640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
516740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
516840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_SetObjectName(in, oh->name);
516940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
517040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
517140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 in->variant.symLinkVariant.alias =
517240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    yaffs_CloneString(oh->alias);
517340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
517440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
517540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
517640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
517740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
517840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ScanBackwards(yaffs_Device * dev)
517940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
518040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
518140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blk;
518240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blockIterator;
518340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int startIterator;
518440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int endIterator;
518540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocksToScan = 0;
518640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
518740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunk;
518840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int result;
518940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int c;
519040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int deleted;
519140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockState state;
519240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *hardList = NULL;
519340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *bi;
519440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int sequenceNumber;
519540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ObjectHeader *oh;
519640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *in;
519740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *parent;
519840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
519940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int itsUnlinked;
520040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *chunkData;
520140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
520240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int fileSize;
520340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int isShrink;
520440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int foundChunksInBlock;
520540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int equivalentObjectId;
520640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
520740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
520840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockIndex *blockIndex = NULL;
520940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int altBlockIndex = 0;
521040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
521140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->isYaffs2) {
521240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_SCAN,
521340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR)));
521440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
521540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
521640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
521740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_SCAN,
521840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR
521940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   ("yaffs_ScanBackwards starts  intstartblk %d intendblk %d..."
522040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    TENDSTR), dev->internalStartBlock, dev->internalEndBlock));
522140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
522240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
522340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
522440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
522540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
522640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
522740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!blockIndex) {
522840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
522940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		altBlockIndex = 1;
523040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
523140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
523240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!blockIndex) {
523340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_SCAN,
523440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
523540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
523640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
523740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
523840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	chunkData = yaffs_GetTempBuffer(dev, __LINE__);
523940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
524040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Scan all the blocks to determine their state */
524140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
524240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi = yaffs_GetBlockInfo(dev, blk);
524340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ClearChunkBits(dev, blk);
524440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->pagesInUse = 0;
524540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->softDeletions = 0;
524640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
524740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
524840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
524940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->blockState = state;
525040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->sequenceNumber = sequenceNumber;
525140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
525240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
525340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
525440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
525540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_SCAN_DEBUG,
525640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
525740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   state, sequenceNumber));
525840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
525940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
526040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(state == YAFFS_BLOCK_STATE_CHECKPOINT){
526140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* todo .. fix free space ? */
526240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
526340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (state == YAFFS_BLOCK_STATE_DEAD) {
526440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_BAD_BLOCKS,
526540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("block %d is bad" TENDSTR), blk));
526640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (state == YAFFS_BLOCK_STATE_EMPTY) {
526740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_SCAN_DEBUG,
526840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("Block empty " TENDSTR)));
526940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->nErasedBlocks++;
527040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->nFreeChunks += dev->nChunksPerBlock;
527140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
527240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
527340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Determine the highest sequence number */
527440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->isYaffs2 &&
527540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
527640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
527740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
527840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				blockIndex[nBlocksToScan].seq = sequenceNumber;
527940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				blockIndex[nBlocksToScan].block = blk;
528040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
528140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				nBlocksToScan++;
528240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
528340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (sequenceNumber >= dev->sequenceNumber) {
528440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->sequenceNumber = sequenceNumber;
528540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
528640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (dev->isYaffs2) {
528740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* TODO: Nasty sequence number! */
528840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_SCAN,
528940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
529040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("Block scanning block %d has bad sequence number %d"
529140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), blk, sequenceNumber));
529240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
529340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
529440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
529540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
529640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
529740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_SCAN,
529840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	(TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan));
529940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
530040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
530140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
530240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YYIELD();
530340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
530440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Sort the blocks */
530540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifndef CONFIG_YAFFS_USE_OWN_SORT
530640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
530740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Use qsort now. */
530840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
530940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
531040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
531140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
531240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 	/* Dungy old bubble sort... */
531340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
531440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_BlockIndex temp;
531540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int i;
531640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int j;
531740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
531840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < nBlocksToScan; i++)
531940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (j = i + 1; j < nBlocksToScan; j++)
532040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (blockIndex[i].seq > blockIndex[j].seq) {
532140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					temp = blockIndex[j];
532240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					blockIndex[j] = blockIndex[i];
532340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					blockIndex[i] = temp;
532440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
532540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
532640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
532740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
532840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YYIELD();
532940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
533040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    	T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR)));
533140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
533240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now scan the blocks looking at the data. */
533340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	startIterator = 0;
533440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	endIterator = nBlocksToScan - 1;
533540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_SCAN_DEBUG,
533640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
533740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
533840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* For each block.... backwards */
533940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (blockIterator = endIterator; blockIterator >= startIterator;
534040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     blockIterator--) {
534140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	        /* Cooperative multitasking! This loop can run for so
534240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   long that watchdog timers expire. */
534340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	        YYIELD();
534440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
534540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* get the block to scan in the correct order */
534640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blk = blockIndex[blockIterator].block;
534740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
534840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi = yaffs_GetBlockInfo(dev, blk);
534940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		state = bi->blockState;
535040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
535140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		deleted = 0;
535240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
535340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* For each chunk in each block that needs scanning.... */
535440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		foundChunksInBlock = 0;
535540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (c = dev->nChunksPerBlock - 1; c >= 0 &&
535640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		     (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
535740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		      state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
535840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Scan backwards...
535940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * Read the tags and decide what to do
536040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
536140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			chunk = blk * dev->nChunksPerBlock + c;
536240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
536340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
536440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							&tags);
536540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
536640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Let's have a good look at this chunk... */
536740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
536840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (!tags.chunkUsed) {
536940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* An unassigned chunk in the block.
537040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * If there are used chunks after this one, then
537140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * it is a chunk that was skipped due to failing the erased
537240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * check. Just skip it so that it can be deleted.
537340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * But, more typically, We get here when this is an unallocated
537440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * chunk and his means that either the block is empty or
537540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * this is the one being allocated from
537640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
537740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
537840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if(foundChunksInBlock)
537940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				{
538040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* This is a chunk that was skipped due to failing the erased check */
538140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
538240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else if (c == 0) {
538340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* We're looking at the first chunk in the block so the block is unused */
538440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					state = YAFFS_BLOCK_STATE_EMPTY;
538540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->nErasedBlocks++;
538640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else {
538740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* this is the block being allocated from */
538840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (state ==
538940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
539040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						T(YAFFS_TRACE_SCAN,
539140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  (TSTR
539240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   (" Allocating from %d %d"
539340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    TENDSTR), blk, c));
539440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
539540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					state = YAFFS_BLOCK_STATE_ALLOCATING;
539640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->allocationBlock = blk;
539740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->allocationPage = c;
539840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					dev->allocationBlockFinder = blk;
539940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Set it to here to encourage the allocator to
540040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 *  go forth from here.
540140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
540240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
540340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Yaffs2 sanity check:
540440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * This should be the one with the highest sequence number
540540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
540640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (dev->isYaffs2
540740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    && (dev->sequenceNumber !=
540840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						bi->sequenceNumber)) {
540940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						T(YAFFS_TRACE_ALWAYS,
541040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  (TSTR
541140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   ("yaffs: Allocation block %d was not highest sequence "
541240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    "id: block seq = %d, dev seq = %d"
541340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    TENDSTR), blk,
541440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   bi->sequenceNumber,
541540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   dev->sequenceNumber));
541640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
541740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
541840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
541940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->nFreeChunks++;
542040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (tags.chunkId > 0) {
542140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* chunkId > 0 so it is a data chunk... */
542240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				unsigned int endpos;
542340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				__u32 chunkBase =
542440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (tags.chunkId - 1) * dev->nDataBytesPerChunk;
542540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
542640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				foundChunksInBlock = 1;
542740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
542840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
542940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_SetChunkBit(dev, blk, c);
543040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				bi->pagesInUse++;
543140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
543240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				in = yaffs_FindOrCreateObjectByNumber(dev,
543340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      tags.
543440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      objectId,
543540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      YAFFS_OBJECT_TYPE_FILE);
543640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (in->variantType == YAFFS_OBJECT_TYPE_FILE
543740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    && chunkBase <
543840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    in->variant.fileVariant.shrinkSize) {
543940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* This has not been invalidated by a resize */
544040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_PutChunkIntoFile(in, tags.chunkId,
544140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							       chunk, -1);
544240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
544340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* File size is calculated by looking at the data chunks if we have not
544440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * seen an object header yet. Stop this practice once we find an object header.
544540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
544640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					endpos =
544740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    (tags.chunkId -
544840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     1) * dev->nDataBytesPerChunk +
544940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    tags.byteCount;
545040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
545140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (!in->valid &&	/* have not got an object header yet */
545240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    in->variant.fileVariant.
545340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    scannedFileSize < endpos) {
545440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variant.fileVariant.
545540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    scannedFileSize = endpos;
545640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variant.fileVariant.
545740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    fileSize =
545840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    in->variant.fileVariant.
545940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    scannedFileSize;
546040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
546140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
546240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else {
546340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* This chunk has been invalidated by a resize, so delete */
546440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
546540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
546640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
546740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else {
546840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* chunkId == 0, so it is an ObjectHeader.
546940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Thus, we read in the object header and make the object
547040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
547140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				foundChunksInBlock = 1;
547240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
547340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_SetChunkBit(dev, blk, c);
547440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				bi->pagesInUse++;
547540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
547640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				oh = NULL;
547740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				in = NULL;
547840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
547940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (tags.extraHeaderInfoAvailable) {
548040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in = yaffs_FindOrCreateObjectByNumber
548140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    (dev, tags.objectId,
548240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     tags.extraObjectType);
548340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
548440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
548540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!in ||
548640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
548740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    !in->valid ||
548840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
548940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    tags.extraShadows ||
549040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (!in->valid &&
549140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (tags.objectId == YAFFS_OBJECTID_ROOT ||
549240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))
549340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    ) {
549440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
549540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* If we don't have  valid info then we need to read the chunk
549640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * TODO In future we can probably defer reading the chunk and
549740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * living with invalid data until needed.
549840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
549940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
550040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					result = yaffs_ReadChunkWithTagsFromNAND(dev,
550140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									chunk,
550240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									chunkData,
550340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									NULL);
550440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
550540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					oh = (yaffs_ObjectHeader *) chunkData;
550640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
550740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (!in)
550840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
550940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
551040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
551140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
551240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!in) {
551340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* TODO Hoosterman we have a problem! */
551440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					T(YAFFS_TRACE_ERROR,
551540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  (TSTR
551640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   ("yaffs tragedy: Could not make object for object  %d  "
551740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    "at chunk %d during scan"
551840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    TENDSTR), tags.objectId, chunk));
551940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
552040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
552140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
552240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (in->valid) {
552340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* We have already filled this one.
552440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * We have a duplicate that will be discarded, but
552540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * we first have to suck out resize info if it is a file.
552640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
552740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
552840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
552940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     ((oh &&
553040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       oh-> type == YAFFS_OBJECT_TYPE_FILE)||
553140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					      (tags.extraHeaderInfoAvailable  &&
553240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					       tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
553340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    ) {
553440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						__u32 thisSize =
553540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    (oh) ? oh->fileSize : tags.
553640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    extraFileLength;
553740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						__u32 parentObjectId =
553840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    (oh) ? oh->
553940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    parentObjectId : tags.
554040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    extraParentObjectId;
554140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						unsigned isShrink =
554240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    (oh) ? oh->isShrink : tags.
554340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    extraIsShrinkHeader;
554440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
554540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* If it is deleted (unlinked at start also means deleted)
554640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 * we treat the file size as being zeroed at this point.
554740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 */
554840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (parentObjectId ==
554940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    YAFFS_OBJECTID_DELETED
555040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    || parentObjectId ==
555140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    YAFFS_OBJECTID_UNLINKED) {
555240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							thisSize = 0;
555340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							isShrink = 1;
555440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
555540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
555640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (isShrink &&
555740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    in->variant.fileVariant.
555840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    shrinkSize > thisSize) {
555940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							in->variant.fileVariant.
556040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    shrinkSize =
556140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    thisSize;
556240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
556340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
556440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (isShrink) {
556540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							bi->hasShrinkHeader = 1;
556640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
556740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
556840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
556940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Use existing - destroy this one. */
557040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
557140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
557240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
557340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
557440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (!in->valid &&
557540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    (tags.objectId == YAFFS_OBJECTID_ROOT ||
557640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     tags.objectId ==
557740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     YAFFS_OBJECTID_LOSTNFOUND)) {
557840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* We only load some info, don't fiddle with directory structure */
557940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->valid = 1;
558040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
558140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if(oh) {
558240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variantType = oh->type;
558340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
558440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_mode = oh->yst_mode;
558540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
558640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_atime[0] = oh->win_atime[0];
558740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_ctime[0] = oh->win_ctime[0];
558840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_mtime[0] = oh->win_mtime[0];
558940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_atime[1] = oh->win_atime[1];
559040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_ctime[1] = oh->win_ctime[1];
559140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_mtime[1] = oh->win_mtime[1];
559240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
559340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_uid = oh->yst_uid;
559440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_gid = oh->yst_gid;
559540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_atime = oh->yst_atime;
559640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_mtime = oh->yst_mtime;
559740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_ctime = oh->yst_ctime;
559840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_rdev = oh->yst_rdev;
559940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
560040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
560140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					} else {
560240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variantType = tags.extraObjectType;
560340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->lazyLoaded = 1;
560440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
560540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
560640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->chunkId = chunk;
560740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
560840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				} else if (!in->valid) {
560940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* we need to load this info */
561040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
561140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->valid = 1;
561240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->chunkId = chunk;
561340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
561440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if(oh) {
561540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variantType = oh->type;
561640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
561740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_mode = oh->yst_mode;
561840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_WINCE
561940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_atime[0] = oh->win_atime[0];
562040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_ctime[0] = oh->win_ctime[0];
562140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_mtime[0] = oh->win_mtime[0];
562240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_atime[1] = oh->win_atime[1];
562340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_ctime[1] = oh->win_ctime[1];
562440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->win_mtime[1] = oh->win_mtime[1];
562540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
562640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_uid = oh->yst_uid;
562740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_gid = oh->yst_gid;
562840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_atime = oh->yst_atime;
562940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_mtime = oh->yst_mtime;
563040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_ctime = oh->yst_ctime;
563140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->yst_rdev = oh->yst_rdev;
563240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
563340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
563440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (oh->shadowsObject > 0)
563540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							yaffs_HandleShadowedObject(dev,
563640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									   oh->
563740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									   shadowsObject,
563840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project									   1);
563940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
564040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
564140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						yaffs_SetObjectName(in, oh->name);
564240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						parent =
564340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    yaffs_FindOrCreateObjectByNumber
564440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    		(dev, oh->parentObjectId,
564540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     		 YAFFS_OBJECT_TYPE_DIRECTORY);
564640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
564740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 fileSize = oh->fileSize;
564840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 						 isShrink = oh->isShrink;
564940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 equivalentObjectId = oh->equivalentObjectId;
565040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
565140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
565240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					else {
565340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->variantType = tags.extraObjectType;
565440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						parent =
565540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    yaffs_FindOrCreateObjectByNumber
565640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    		(dev, tags.extraParentObjectId,
565740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					     		 YAFFS_OBJECT_TYPE_DIRECTORY);
565840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 fileSize = tags.extraFileLength;
565940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 isShrink = tags.extraIsShrinkHeader;
566040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 equivalentObjectId = tags.extraEquivalentObjectId;
566140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						in->lazyLoaded = 1;
566240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
566340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
566440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					in->dirty = 0;
566540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
566640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* directory stuff...
566740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * hook up to parent
566840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
566940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
567040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (parent->variantType ==
567140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    YAFFS_OBJECT_TYPE_UNKNOWN) {
567240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Set up as a directory */
567340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						parent->variantType =
567440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    YAFFS_OBJECT_TYPE_DIRECTORY;
567540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						INIT_LIST_HEAD(&parent->variant.
567640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							       directoryVariant.
567740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							       children);
567840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					} else if (parent->variantType !=
567940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   YAFFS_OBJECT_TYPE_DIRECTORY)
568040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					{
568140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Hoosterman, another problem....
568240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 * We're trying to use a non-directory as a directory
568340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						 */
568440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
568540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						T(YAFFS_TRACE_ERROR,
568640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  (TSTR
568740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   ("yaffs tragedy: attempting to use non-directory as"
568840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    " a directory in scan. Put in lost+found."
568940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    TENDSTR)));
569040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						parent = dev->lostNFoundDir;
569140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
569240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
569340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					yaffs_AddObjectToDirectory(parent, in);
569440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
569540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					itsUnlinked = (parent == dev->deletedDir) ||
569640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						      (parent == dev->unlinkedDir);
569740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
569840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					if (isShrink) {
569940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Mark the block as having a shrinkHeader */
570040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						bi->hasShrinkHeader = 1;
570140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
570240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
570340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					/* Note re hardlinks.
570440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * Since we might scan a hardlink before its equivalent object is scanned
570540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * we put them all in a list.
570640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * After scanning is complete, we should have all the objects, so we run
570740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 * through this list and fix up all the chains.
570840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					 */
570940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
571040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					switch (in->variantType) {
571140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_UNKNOWN:
571240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Todo got a problem */
571340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
571440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_FILE:
571540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
571640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (in->variant.fileVariant.
571740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    scannedFileSize < fileSize) {
571840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							/* This covers the case where the file size is greater
571940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 * than where the data is
572040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 * This will happen if the file is resized to be larger
572140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 * than its current data extents.
572240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							 */
572340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							in->variant.fileVariant.fileSize = fileSize;
572440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							in->variant.fileVariant.scannedFileSize =
572540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							    in->variant.fileVariant.fileSize;
572640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
572740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
572840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if (isShrink &&
572940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    in->variant.fileVariant.shrinkSize > fileSize) {
573040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							in->variant.fileVariant.shrinkSize = fileSize;
573140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
573240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
573340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
573440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_HARDLINK:
573540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if(!itsUnlinked) {
573640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  in->variant.hardLinkVariant.equivalentObjectId =
573740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    equivalentObjectId;
573840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  in->hardLinks.next =
573940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    (struct list_head *) hardList;
574040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						  hardList = in;
574140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						}
574240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
574340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_DIRECTORY:
574440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Do nothing */
574540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
574640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_SPECIAL:
574740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						/* Do nothing */
574840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
574940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					case YAFFS_OBJECT_TYPE_SYMLINK:
575040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						if(oh)
575140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   in->variant.symLinkVariant.alias =
575240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    yaffs_CloneString(oh->
575340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project								      alias);
575440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						break;
575540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					}
575640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
575740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
575840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
575940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
576040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
576140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
576240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* If we got this far while scanning, then the block is fully allocated. */
576340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			state = YAFFS_BLOCK_STATE_FULL;
576440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
576540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
576640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		bi->blockState = state;
576740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
576840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Now let's see if it was dirty */
576940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (bi->pagesInUse == 0 &&
577040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    !bi->hasShrinkHeader &&
577140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    bi->blockState == YAFFS_BLOCK_STATE_FULL) {
577240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_BlockBecameDirty(dev, blk);
577340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
577440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
577540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
577640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
577740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (altBlockIndex)
577840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE_ALT(blockIndex);
577940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
578040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(blockIndex);
578140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
578240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Ok, we've done all the scanning.
578340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Fix up the hard link chains.
578440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * We should now have scanned all the objects, now it's time to add these
578540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * hardlinks.
578640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
578740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_HardlinkFixup(dev,hardList);
578840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
578940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
579040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/*
579140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*  Sort out state of unlinked and deleted objects.
579240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*/
579340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
579440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		struct list_head *i;
579540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		struct list_head *n;
579640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
579740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_Object *l;
579840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
579940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Soft delete all the unlinked files */
580040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list_for_each_safe(i, n,
580140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   &dev->unlinkedDir->variant.directoryVariant.
580240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   children) {
580340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (i) {
580440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				l = list_entry(i, yaffs_Object, siblings);
580540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DestroyObject(l);
580640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
580740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
580840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
580940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Soft delete all the deletedDir files */
581040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		list_for_each_safe(i, n,
581140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   &dev->deletedDir->variant.directoryVariant.
581240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   children) {
581340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (i) {
581440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				l = list_entry(i, yaffs_Object, siblings);
581540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_DestroyObject(l);
581640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
581740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
581840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
581940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
582040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
582140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
582240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
582340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
582440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
582540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
582640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
582740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
582840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*------------------------------  Directory Functions ----------------------------- */
582940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
583040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
583140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
583240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Device *dev = obj->myDev;
583340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
583440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(dev && dev->removeObjectCallback)
583540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->removeObjectCallback(obj);
583640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
583740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_del_init(&obj->siblings);
583840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->parent = NULL;
583940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
584040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
584140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
584240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_AddObjectToDirectory(yaffs_Object * directory,
584340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       yaffs_Object * obj)
584440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
584540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
584640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!directory) {
584740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
584840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
584940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("tragedy: Trying to add an object to a null pointer directory"
585040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    TENDSTR)));
585140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
585240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
585340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
585440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
585540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
585640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("tragedy: Trying to add an object to a non-directory"
585740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    TENDSTR)));
585840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
585940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
586040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
586140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->siblings.prev == NULL) {
586240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Not initialised */
586340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		INIT_LIST_HEAD(&obj->siblings);
586440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
586540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else if (!list_empty(&obj->siblings)) {
586640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* If it is holed up somewhere else, un hook it */
586740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_RemoveObjectFromDirectory(obj);
586840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
586940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now add it */
587040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_add(&obj->siblings, &directory->variant.directoryVariant.children);
587140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj->parent = directory;
587240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
587340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (directory == obj->myDev->unlinkedDir
587440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    || directory == obj->myDev->deletedDir) {
587540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->unlinked = 1;
587640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->myDev->nUnlinkedFiles++;
587740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->renameAllowed = 0;
587840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
587940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
588040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
588140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
588240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const YCHAR * name)
588340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
588440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int sum;
588540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
588640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct list_head *i;
588740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
588840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
588940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *l;
589040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
589140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!name) {
589240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return NULL;
589340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
589440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
589540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!directory) {
589640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
589740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
589840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("tragedy: yaffs_FindObjectByName: null pointer directory"
589940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    TENDSTR)));
590040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
590140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
590240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
590340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
590440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
590540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
590640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
590740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
590840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
590940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sum = yaffs_CalcNameSum(name);
591040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
591140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_for_each(i, &directory->variant.directoryVariant.children) {
591240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (i) {
591340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			l = list_entry(i, yaffs_Object, siblings);
591440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
591540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_CheckObjectDetailsLoaded(l);
591640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
591740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Special case for lost-n-found */
591840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
591940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
592040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					return l;
592140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
592240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)
592340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			{
592440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* LostnFound cunk called Objxxx
592540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 * Do a real check
592640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				 */
592740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_GetObjectName(l, buffer,
592840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    YAFFS_MAX_NAME_LENGTH);
592940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (yaffs_strcmp(name, buffer) == 0) {
593040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					return l;
593140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
593240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
593340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
593440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
593540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
593640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
593740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return NULL;
593840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
593940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
594040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
594140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if 0
594240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
594340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   int (*fn) (yaffs_Object *))
594440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
594540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct list_head *i;
594640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Object *l;
594740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
594840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!theDir) {
594940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
595040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
595140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("tragedy: yaffs_FindObjectByName: null pointer directory"
595240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    TENDSTR)));
595340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
595440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
595540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
595640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
595740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
595840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
595940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YBUG();
596040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
596140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
596240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_for_each(i, &theDir->variant.directoryVariant.children) {
596340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (i) {
596440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			l = list_entry(i, yaffs_Object, siblings);
596540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (l && !fn(l)) {
596640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				return YAFFS_FAIL;
596740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
596840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
596940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
597040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
597140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
597240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
597340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
597440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
597540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
597640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* GetEquivalentObject dereferences any hard links to get to the
597740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * actual object.
597840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
597940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
598040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectyaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj)
598140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
598240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
598340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* We want the object id of the equivalent object, not this one */
598440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj = obj->variant.hardLinkVariant.equivalentObject;
598540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
598640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return obj;
598740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
598840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
598940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
599040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
599140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
599240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	memset(name, 0, buffSize * sizeof(YCHAR));
599340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
599440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckObjectDetailsLoaded(obj);
599540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
599640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
599740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
599840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else if (obj->chunkId <= 0) {
599940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YCHAR locName[20];
600040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* make up a name */
600140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
600240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			      obj->objectId);
600340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_strncpy(name, locName, buffSize - 1);
600440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
600540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
600640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
600740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if (obj->shortName[0]) {
600840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_strcpy(name, obj->shortName);
600940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
601040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
601140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else {
601240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int result;
601340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		__u8 *buffer = yaffs_GetTempBuffer(obj->myDev, __LINE__);
601440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
601540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *) buffer;
601640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
601740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
601840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
601940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (obj->chunkId >= 0) {
602040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
602140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							obj->chunkId, buffer,
602240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project							NULL);
602340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
602440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_strncpy(name, oh->name, buffSize - 1);
602540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
602640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ReleaseTempBuffer(obj->myDev, buffer, __LINE__);
602740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
602840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
602940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_strlen(name);
603040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
603140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
603240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_GetObjectFileLength(yaffs_Object * obj)
603340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
603440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
603540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Dereference any hard linking */
603640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj = yaffs_GetEquivalentObject(obj);
603740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
603840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
603940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return obj->variant.fileVariant.fileSize;
604040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
604140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
604240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_strlen(obj->variant.symLinkVariant.alias);
604340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
604440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Only a directory should drop through to here */
604540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return obj->myDev->nDataBytesPerChunk;
604640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
604740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
604840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
604940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_GetObjectLinkCount(yaffs_Object * obj)
605040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
605140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int count = 0;
605240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct list_head *i;
605340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
605440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!obj->unlinked) {
605540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		count++;	/* the object itself */
605640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
605740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	list_for_each(i, &obj->hardLinks) {
605840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		count++;	/* add the hard links; */
605940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
606040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return count;
606140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
606240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
606340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
606440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_GetObjectInode(yaffs_Object * obj)
606540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
606640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj = yaffs_GetEquivalentObject(obj);
606740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
606840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return obj->objectId;
606940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
607040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
607140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectunsigned yaffs_GetObjectType(yaffs_Object * obj)
607240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
607340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj = yaffs_GetEquivalentObject(obj);
607440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
607540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	switch (obj->variantType) {
607640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_FILE:
607740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return DT_REG;
607840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
607940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_DIRECTORY:
608040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return DT_DIR;
608140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
608240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_SYMLINK:
608340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return DT_LNK;
608440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
608540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_HARDLINK:
608640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return DT_REG;
608740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
608840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	case YAFFS_OBJECT_TYPE_SPECIAL:
608940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (S_ISFIFO(obj->yst_mode))
609040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return DT_FIFO;
609140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (S_ISCHR(obj->yst_mode))
609240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return DT_CHR;
609340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (S_ISBLK(obj->yst_mode))
609440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return DT_BLK;
609540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (S_ISSOCK(obj->yst_mode))
609640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return DT_SOCK;
609740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	default:
609840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return DT_REG;
609940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		break;
610040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
610140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
610240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
610340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source ProjectYCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj)
610440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
610540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	obj = yaffs_GetEquivalentObject(obj);
610640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
610740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_CloneString(obj->variant.symLinkVariant.alias);
610840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
610940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return yaffs_CloneString(_Y(""));
611040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
611140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
611240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
611340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifndef CONFIG_YAFFS_WINCE
611440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
611540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr)
611640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
611740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned int valid = attr->ia_valid;
611840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
611940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (valid & ATTR_MODE)
612040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->yst_mode = attr->ia_mode;
612140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (valid & ATTR_UID)
612240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->yst_uid = attr->ia_uid;
612340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (valid & ATTR_GID)
612440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->yst_gid = attr->ia_gid;
612540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
612640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (valid & ATTR_ATIME)
612740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
612840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (valid & ATTR_CTIME)
612940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
613040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (valid & ATTR_MTIME)
613140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
613240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
613340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (valid & ATTR_SIZE)
613440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ResizeFile(obj, attr->ia_size);
613540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
613640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0);
613740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
613840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
613940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
614040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
614140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr)
614240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
614340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned int valid = 0;
614440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
614540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	attr->ia_mode = obj->yst_mode;
614640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	valid |= ATTR_MODE;
614740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	attr->ia_uid = obj->yst_uid;
614840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	valid |= ATTR_UID;
614940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	attr->ia_gid = obj->yst_gid;
615040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	valid |= ATTR_GID;
615140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
615240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
615340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	valid |= ATTR_ATIME;
615440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
615540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	valid |= ATTR_CTIME;
615640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
615740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	valid |= ATTR_MTIME;
615840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
615940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	attr->ia_size = yaffs_GetFileSize(obj);
616040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	valid |= ATTR_SIZE;
616140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
616240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	attr->ia_valid = valid;
616340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
616440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
616540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
616640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
616740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
616840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
616940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
617040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if 0
617140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_DumpObject(yaffs_Object * obj)
617240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
617340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	YCHAR name[257];
617440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
617540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_GetObjectName(obj, name, 256);
617640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
617740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_ALWAYS,
617840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR
617940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
618040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    " chunk %d type %d size %d\n"
618140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
618240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
618340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
618440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
618540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
618640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
618740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
618840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
618940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*---------------------------- Initialisation code -------------------------------------- */
619040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
619140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckDevFunctions(const yaffs_Device * dev)
619240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
619340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
619440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Common functions, gotta have */
619540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->eraseBlockInNAND || !dev->initialiseNAND)
619640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
619740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
619840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_YAFFS2
619940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
620040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Can use the "with tags" style interface for yaffs1 or yaffs2 */
620140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->writeChunkWithTagsToNAND &&
620240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    dev->readChunkWithTagsFromNAND &&
620340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    !dev->writeChunkToNAND &&
620440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    !dev->readChunkFromNAND &&
620540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    dev->markNANDBlockBad && dev->queryNANDBlock)
620640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 1;
620740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
620840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
620940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Can use the "spare" style interface for yaffs1 */
621040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->isYaffs2 &&
621140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    !dev->writeChunkWithTagsToNAND &&
621240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    !dev->readChunkWithTagsFromNAND &&
621340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    dev->writeChunkToNAND &&
621440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    dev->readChunkFromNAND &&
621540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    !dev->markNANDBlockBad && !dev->queryNANDBlock)
621640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 1;
621740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
621840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;		/* bad */
621940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
622040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
622140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
622240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CreateInitialDirectories(yaffs_Device *dev)
622340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
622440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Initialise the unlinked, deleted, root and lost and found directories */
622540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
622640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->lostNFoundDir = dev->rootDir =  NULL;
622740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->unlinkedDir = dev->deletedDir = NULL;
622840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
622940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->unlinkedDir =
623040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
623140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->deletedDir =
623240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
623340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
623440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->rootDir =
623540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_ROOT,
623640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      YAFFS_ROOT_MODE | S_IFDIR);
623740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->lostNFoundDir =
623840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,
623940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      YAFFS_LOSTNFOUND_MODE | S_IFDIR);
624040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);
624140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
624240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
624340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_GutsInitialise(yaffs_Device * dev)
624440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
624540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned x;
624640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int bits;
624740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
624840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR)));
624940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
625040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Check stuff that must be set */
625140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
625240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev) {
625340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Need a device" TENDSTR)));
625440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
625540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
625640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
625740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->internalStartBlock = dev->startBlock;
625840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->internalEndBlock = dev->endBlock;
625940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->blockOffset = 0;
626040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->chunkOffset = 0;
626140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nFreeChunks = 0;
626240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
626340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->startBlock == 0) {
626440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->internalStartBlock = dev->startBlock + 1;
626540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->internalEndBlock = dev->endBlock + 1;
626640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->blockOffset = 1;
626740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkOffset = dev->nChunksPerBlock;
626840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
626940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
627040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Check geometry parameters. */
627140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
627240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
627340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
627440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     dev->nChunksPerBlock < 2 ||
627540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     dev->nReservedBlocks < 2 ||
627640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     dev->internalStartBlock <= 0 ||
627740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     dev->internalEndBlock <= 0 ||
627840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)	// otherwise it is too small
627940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    ) {
628040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
628140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
628240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
628340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
628440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
628540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
628640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
628740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (yaffs_InitialiseNAND(dev) != YAFFS_OK) {
628840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
628940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
629040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
629140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
629240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
629340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Got the right mix of functions? */
629440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!yaffs_CheckDevFunctions(dev)) {
629540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Function missing */
629640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
629740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR
629840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   ("yaffs: device function(s) missing or wrong\n" TENDSTR)));
629940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
630040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
630140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
630240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
630340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* This is really a compilation check. */
630440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!yaffs_CheckStructures()) {
630540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
630640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs_CheckStructures failed\n" TENDSTR)));
630740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
630840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
630940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
631040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isMounted) {
631140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
631240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs: device already mounted\n" TENDSTR)));
631340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
631440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
631540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
631640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Finished with most checks. One or two more checks happen later on too. */
631740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
631840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->isMounted = 1;
631940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
632040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
632140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
632240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* OK now calculate a few things for the device */
632340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
632440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/*
632540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 *  Calculate all the chunk size manipulation numbers:
632640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
632740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 /* Start off assuming it is a power of 2 */
632840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
632940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 dev->chunkMask = (1<<dev->chunkShift) - 1;
633040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
633140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
633240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 	/* Yes it is a power of 2, disable crumbs */
633340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->crumbMask = 0;
633440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->crumbShift = 0;
633540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->crumbsPerChunk = 0;
633640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 } else {
633740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 	/* Not a power of 2, use crumbs instead */
633840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
633940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->crumbMask = (1<<dev->crumbShift)-1;
634040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
634140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkShift = 0;
634240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkMask = 0;
634340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
634440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
634540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
634640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/*
634740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Calculate chunkGroupBits.
634840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * We need to find the next power of 2 > than internalEndBlock
634940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
635040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
635140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	x = dev->nChunksPerBlock * (dev->internalEndBlock + 1);
635240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
635340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	bits = ShiftsGE(x);
635440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
635540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Set up tnode width if wide tnodes are enabled. */
635640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!dev->wideTnodesDisabled){
635740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* bits must be even so that we end up with 32-bit words */
635840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(bits & 1)
635940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bits++;
636040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(bits < 16)
636140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->tnodeWidth = 16;
636240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else
636340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->tnodeWidth = bits;
636440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
636540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
636640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->tnodeWidth = 16;
636740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
636840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->tnodeMask = (1<<dev->tnodeWidth)-1;
636940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
637040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
637140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * so if the bitwidth of the
637240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * chunk range we're using is greater than 16 we need
637340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * to figure out chunk shift and chunkGroupSize
637440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
637540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
637640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (bits <= dev->tnodeWidth)
637740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkGroupBits = 0;
637840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
637940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->chunkGroupBits = bits - dev->tnodeWidth;
638040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
638140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
638240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->chunkGroupSize = 1 << dev->chunkGroupBits;
638340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
638440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nChunksPerBlock < dev->chunkGroupSize) {
638540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* We have a problem because the soft delete won't work if
638640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * the chunk group size > chunks per block.
638740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 * This can be remedied by using larger "virtual blocks".
638840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 */
638940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
639040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("yaffs: chunk group too large\n" TENDSTR)));
639140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
639240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
639340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
639440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
639540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* OK, we've finished verifying the device, lets continue with initialisation */
639640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
639740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* More device initialisation */
639840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->garbageCollections = 0;
639940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->passiveGarbageCollections = 0;
640040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->currentDirtyChecker = 0;
640140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->bufferedBlock = -1;
640240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->doingBufferedBlockRewrite = 0;
640340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nDeletedFiles = 0;
640440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nBackgroundDeletions = 0;
640540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nUnlinkedFiles = 0;
640640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->eccFixed = 0;
640740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->eccUnfixed = 0;
640840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->tagsEccFixed = 0;
640940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->tagsEccUnfixed = 0;
641040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nErasureFailures = 0;
641140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nErasedBlocks = 0;
641240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->isDoingGC = 0;
641340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
641440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
641540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Initialise temporary buffers and caches. */
641640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
641740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int i;
641840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
641940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->tempBuffer[i].line = 0;	/* not in use */
642040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->tempBuffer[i].buffer =
642140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    YMALLOC_DMA(dev->nDataBytesPerChunk);
642240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
642340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
642440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
642540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->nShortOpCaches > 0) {
642640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int i;
642740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
642840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
642940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
643040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
643140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
643240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->srCache =
643340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    YMALLOC(dev->nShortOpCaches * sizeof(yaffs_ChunkCache));
643440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
643540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < dev->nShortOpCaches; i++) {
643640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->srCache[i].object = NULL;
643740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->srCache[i].lastUse = 0;
643840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->srCache[i].dirty = 0;
643940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->srCache[i].data = YMALLOC_DMA(dev->nDataBytesPerChunk);
644040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
644140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->srLastUse = 0;
644240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
644340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
644440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->cacheHits = 0;
644540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
644640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
644740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
644840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isYaffs2) {
644940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->useHeaderFileSize = 1;
645040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
645140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
645240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InitialiseBlocks(dev);
645340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InitialiseTnodes(dev);
645440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_InitialiseObjects(dev);
645540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
645640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CreateInitialDirectories(dev);
645740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
645840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
645940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now scan the flash. */
646040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isYaffs2) {
646140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(yaffs_CheckpointRestore(dev)) {
646240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ALWAYS,
646340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			  (TSTR("yaffs: restored from checkpoint" TENDSTR)));
646440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
646540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
646640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Clean up the mess caused by an aborted checkpoint load
646740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 * and scan backwards.
646840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			 */
646940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_DeinitialiseBlocks(dev);
647040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_DeinitialiseTnodes(dev);
647140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_DeinitialiseObjects(dev);
647240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_InitialiseBlocks(dev);
647340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_InitialiseTnodes(dev);
647440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_InitialiseObjects(dev);
647540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_CreateInitialDirectories(dev);
647640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
647740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ScanBackwards(dev);
647840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
647940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}else
648040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_Scan(dev);
648140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
648240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Zero out stats */
648340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nPageReads = 0;
648440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nPageWrites = 0;
648540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nBlockErasures = 0;
648640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nGCCopies = 0;
648740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nRetriedWrites = 0;
648840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
648940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nRetiredBlocks = 0;
649040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
649140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_VerifyFreeChunks(dev);
649240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
649340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_TRACING,
649440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
649540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
649640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
649740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
649840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
649940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_Deinitialise(yaffs_Device * dev)
650040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
650140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (dev->isMounted) {
650240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int i;
650340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
650440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeinitialiseBlocks(dev);
650540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeinitialiseTnodes(dev);
650640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_DeinitialiseObjects(dev);
650740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (dev->nShortOpCaches > 0) {
650840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
650940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for (i = 0; i < dev->nShortOpCaches; i++) {
651040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				YFREE(dev->srCache[i].data);
651140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
651240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
651340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			YFREE(dev->srCache);
651440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
651540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
651640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(dev->gcCleanupList);
651740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
651840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
651940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			YFREE(dev->tempBuffer[i].buffer);
652040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
652140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
652240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->isMounted = 0;
652340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
652440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
652540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
652640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
652740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CountFreeChunks(yaffs_Device * dev)
652840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
652940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nFree;
653040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int b;
653140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
653240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_BlockInfo *blk;
653340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
653440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock;
653540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	     b++) {
653640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blk = yaffs_GetBlockInfo(dev, b);
653740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
653840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		switch (blk->blockState) {
653940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_BLOCK_STATE_EMPTY:
654040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_BLOCK_STATE_ALLOCATING:
654140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_BLOCK_STATE_COLLECTING:
654240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		case YAFFS_BLOCK_STATE_FULL:
654340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nFree +=
654440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (dev->nChunksPerBlock - blk->pagesInUse +
654540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     blk->softDeletions);
654640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
654740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		default:
654840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			break;
654940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
655040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
655140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
655240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
655340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nFree;
655440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
655540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
655640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_GetNumberOfFreeChunks(yaffs_Device * dev)
655740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
655840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* This is what we report to the outside world */
655940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
656040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nFree;
656140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nDirtyCacheChunks;
656240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blocksForCheckpoint;
656340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
656440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if 1
656540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nFree = dev->nFreeChunks;
656640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
656740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nFree = yaffs_CountFreeChunks(dev);
656840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
656940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
657040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nFree += dev->nDeletedFiles;
657140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
657240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now count the number of dirty chunks in the cache and subtract those */
657340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
657440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
657540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		int i;
657640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) {
657740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (dev->srCache[i].dirty)
657840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				nDirtyCacheChunks++;
657940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
658040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
658140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
658240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nFree -= nDirtyCacheChunks;
658340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
658440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
658540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
658640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Now we figure out how much to reserve for the checkpoint and report that... */
658740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
658840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(blocksForCheckpoint < 0)
658940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blocksForCheckpoint = 0;
659040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
659140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nFree -= (blocksForCheckpoint * dev->nChunksPerBlock);
659240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
659340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (nFree < 0)
659440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nFree = 0;
659540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
659640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nFree;
659740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
659840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
659940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
660040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_freeVerificationFailures;
660140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
660240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_VerifyFreeChunks(yaffs_Device * dev)
660340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
660440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int counted = yaffs_CountFreeChunks(dev);
660540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
660640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int difference = dev->nFreeChunks - counted;
660740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
660840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (difference) {
660940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,
661040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("Freechunks verification failure %d %d %d" TENDSTR),
661140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   dev->nFreeChunks, counted, difference));
661240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_freeVerificationFailures++;
661340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
661440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
661540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
661640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*---------------------------------------- YAFFS test code ----------------------*/
661740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
661840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define yaffs_CheckStruct(structure,syze, name) \
661940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project           if(sizeof(structure) != syze) \
662040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	       { \
662140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	         T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
662240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 name,syze,sizeof(structure))); \
662340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	         return YAFFS_FAIL; \
662440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
662540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
662640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckStructures(void)
662740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
662840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
662940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
663040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
663140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
663240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
663340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
663440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
663540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
663640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    return YAFFS_OK;
663740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
6638