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