YMStreamRef __YMPlexerCreateStreamWithID(__ym_plexer_t *p, YMPlexerStreamID streamID, bool isLocal, YMStringRef userNameToRelease) { __ym_plexer_stream_user_info_t *userInfo = (__ym_plexer_stream_user_info_t *)YMALLOC(sizeof(__ym_plexer_stream_user_info_t)); userInfo->plexer = YMRetain(p); userInfo->streamID = streamID; userInfo->isLocallyOriginated = isLocal; userInfo->lastServiceTime = (struct timeval *)YMALLOC(sizeof(struct timeval)); if ( 0 != gettimeofday(userInfo->lastServiceTime, NULL) ) { ymlog("warning: error setting initial service time for s%llu: %d (%s)",streamID,errno,strerror(errno)); YMGetTheBeginningOfPosixTimeForCurrentPlatform(userInfo->lastServiceTime); } YMStringRef memberName = YMStringCreateWithFormat("%s-%s-s%llu-%s",p->master?"m":"s",isLocal?">":"<",streamID,YMSTR(userNameToRelease),NULL); userInfo->lock = YMLockCreateWithOptionsAndName(YMInternalLockType, memberName); userInfo->bytesAvailable = 0; userInfo->userClosed = false; userInfo->rawWritten = 0; userInfo->muxerWritten = 0; userInfo->rawRead = 0; userInfo->muxerRead = 0; YMStreamRef theStream = _YMStreamCreate(memberName, (ym_stream_user_info_t *)userInfo, __ym_plexer_free_stream_info); YMRelease(memberName); _YMStreamSetDataAvailableCallback(theStream, __ym_plexer_stream_data_available_proc, p); YMRelease(userNameToRelease); return theStream; }
static int CheckInit(yaffs_Device *dev) { static int initialised = 0; int i; int fail = 0; int nAllocated = 0; if(initialised) { return YAFFS_OK; } initialised = 1; ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); ramdisk.block = YMALLOC(sizeof(yflash_Block *) * ramdisk.nBlocks); if(!ramdisk.block) return 0; for(i=0; i <ramdisk.nBlocks; i++) { ramdisk.block[i] = NULL; } for(i=0; i <ramdisk.nBlocks && !fail; i++) { if((ramdisk.block[i] = YMALLOC(sizeof(yflash_Block))) == 0) { fail = 1; } else { yflash_EraseBlockInNAND(dev,i); nAllocated++; } } if(fail) { for(i = 0; i < nAllocated; i++) { YFREE(ramdisk.block[i]); } YFREE(ramdisk.block); T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", nAllocated/64,ramdisk.nBlocks * YAFFS_BYTES_PER_BLOCK)); return 0; } return 1; }
YMPlexerRef YMPlexerCreate(YMStringRef name, YMSecurityProviderRef provider, bool master) { __YMRegisterSigpipe(); __ym_plexer_t *p = (__ym_plexer_t *)_YMAlloc(_YMPlexerTypeID,sizeof(__ym_plexer_t)); p->name = YMStringCreateWithFormat("%s:%s",master?"s":"c",name?YMSTR(name):"*",NULL); p->provider = YMRetain(provider); p->active = false; p->master = master; p->stopped = false; p->myStreamsEven = false; p->localStreamsByID = YMDictionaryCreate(); YMStringRef aString = YMStringCreateWithFormat("%s-local",YMSTR(p->name), NULL); p->localAccessLock = YMLockCreateWithOptionsAndName(YMInternalLockType,aString); YMRelease(aString); p->localPlexBufferSize = YMPlexerDefaultBufferSize; p->localPlexBuffer = YMALLOC(p->localPlexBufferSize); p->remoteStreamsByID = YMDictionaryCreate(); aString = YMStringCreateWithFormat("%s-remote",YMSTR(p->name),NULL); p->remoteAccessLock = YMLockCreateWithOptionsAndName(YMInternalLockType,aString); YMRelease(aString); p->remotePlexBufferSize = YMPlexerDefaultBufferSize; p->remotePlexBuffer = YMALLOC(p->remotePlexBufferSize); aString = YMStringCreateWithFormat("%s-down",YMSTR(p->name),NULL); p->localServiceThread = YMThreadCreate(aString, __ym_plexer_service_downstream_proc, (void *)YMRetain(p)); YMRelease(aString); aString = YMStringCreateWithFormat("%s-up",YMSTR(p->name),NULL); p->remoteServiceThread = YMThreadCreate(aString, __ym_plexer_service_upstream_proc, (void *)YMRetain(p)); YMRelease(aString); aString = YMStringCreateWithFormat("%s-event",YMSTR(p->name),NULL); p->eventDeliveryThread = YMThreadDispatchCreate(aString); YMRelease(aString); aString = YMStringCreateWithFormat("%s-interrupt",YMSTR(p->name),NULL); p->interruptionLock = YMLockCreateWithOptionsAndName(YMInternalLockType,aString); YMRelease(aString); aString = YMStringCreateWithFormat("%s-down-signal",YMSTR(p->name),NULL); p->downstreamReadySemaphore = YMSemaphoreCreateWithName(aString,0); YMRelease(aString); p->interruptedFunc = NULL; p->newIncomingFunc = NULL; p->closingFunc = NULL; p->callbackContext = NULL; return p; }
static int yaffs_create_free_objs(yaffs_dev_t *dev, int n_obj) { yaffs_Allocator *allocator = dev->allocator; int i; yaffs_obj_t *newObjects; yaffs_obj_tList *list; if(!allocator){ YBUG(); return YAFFS_FAIL; } if (n_obj < 1) return YAFFS_OK; /* make these things */ newObjects = YMALLOC(n_obj * sizeof(yaffs_obj_t)); list = YMALLOC(sizeof(yaffs_obj_tList)); if (!newObjects || !list) { if (newObjects){ YFREE(newObjects); newObjects = NULL; } if (list){ YFREE(list); list = NULL; } T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Could not allocate more objects" TENDSTR))); return YAFFS_FAIL; } /* Hook them into the free list */ for (i = 0; i < n_obj - 1; i++) { newObjects[i].siblings.next = (struct ylist_head *)(&newObjects[i + 1]); } newObjects[n_obj - 1].siblings.next = (void *)allocator->freeObjects; allocator->freeObjects = newObjects; allocator->nFreeObjects += n_obj; allocator->n_objCreated += n_obj; /* Now add this bunch of Objects to a list for freeing up. */ list->objects = newObjects; list->next = allocator->allocatedObjectList; allocator->allocatedObjectList = list; return YAFFS_OK; }
int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting) { /* Got the functions we need? */ if (!dev->writeChunkWithTagsToNAND || !dev->readChunkWithTagsFromNAND || !dev->eraseBlockInNAND || !dev->markNANDBlockBad) return 0; if(forWriting && !yaffs_CheckpointSpaceOk(dev)) return 0; if(!dev->checkpointBuffer) dev->checkpointBuffer = YMALLOC(dev->nBytesPerChunk); if(!dev->checkpointBuffer) return 0; dev->checkpointPageSequence = 0; dev->checkpointOpenForWrite = forWriting; dev->checkpointByteCount = 0; dev->checkpointCurrentBlock = -1; dev->checkpointCurrentChunk = -1; dev->checkpointNextBlock = dev->startBlock; /* Erase all the blocks in the checkpoint area */ if(forWriting){ memset(dev->checkpointBuffer,0,dev->nBytesPerChunk); dev->checkpointByteOffset = 0; return yaffs_CheckpointErase(dev); } else { int i; /* Set to a value that will kick off a read */ dev->checkpointByteOffset = dev->nBytesPerChunk; /* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully) * going to be way more than we need */ dev->checkpointMaxBlocks = (dev->endBlock - dev->startBlock)/16 + 2; dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks); for(i = 0; i < dev->checkpointMaxBlocks; i++) dev->checkpointBlockList[i] = -1; } return 1; }
/* Process a SETDB command. */ yerr_t command_setdb(tcp_thread_t *thread, ydynabin_t *buff) { unsigned char *pdbname_len, dbname_len; char *dbname = NULL; void *ptr; yerr_t result = YENOERR; YLOG_ADD(YLOG_DEBUG, "SETDB command"); // read dbname length if (connection_read_data(thread, buff, sizeof(dbname_len)) != YENOERR) goto error; pdbname_len = ydynabin_forward(buff, sizeof(dbname_len)); dbname_len = *pdbname_len; YFREE(thread->dbname); if (dbname_len > 0) { // read dbname if (connection_read_data(thread, buff, (size_t)dbname_len) != YENOERR) goto error; ptr = ydynabin_forward(buff, (size_t)dbname_len); if ((dbname = YMALLOC((size_t)dbname_len + 1)) == NULL) goto error; memcpy(dbname, ptr, (size_t)dbname_len); thread->dbname = dbname; } // send the response to the client YLOG_ADD(YLOG_DEBUG, "SETDB command OK"); CONNECTION_SEND_OK(thread); return (result); error: YLOG_ADD(YLOG_WARN, "SETDB error"); CONNECTION_SEND_ERROR(thread, RESP_ERR_SERVER); return (YEIO); }
YMStringRef YMStringCreateWithCString(const char *cString) { size_t length = strlen(cString); char *copy = YMALLOC(length + 1); strncpy(copy, cString, length + 1); return __YMStringCreate(copy, length); }
/*-----------------*/ YDECK *Ydeck_init( ) { YDECKPTR deckPtr ; deckPtr = (YDECKPTR) YMALLOC( 1, YDECK ); deckPtr->top= &deckEndS; /* init to point to sentinal */ deckPtr->bottom= &deckEndS; /* init to point to sentinal */ deckPtr->current= &deckEndS; /* init to point to sentinal */ deckPtr->size=0; return(deckPtr); } /* end Ydeck_init */
int yaffs2_checkpt_open(yaffs_dev_t *dev, int writing) { dev->checkpt_open_write = writing; /* Got the functions we need? */ if (!dev->param.write_chunk_tags_fn || !dev->param.read_chunk_tags_fn || !dev->param.erase_fn || !dev->param.bad_block_fn) return 0; if (writing && !yaffs2_checkpt_space_ok(dev)) return 0; if (!dev->checkpt_buffer) dev->checkpt_buffer = YMALLOC_DMA(dev->param.total_bytes_per_chunk); if (!dev->checkpt_buffer) return 0; dev->checkpt_page_seq = 0; dev->checkpt_byte_count = 0; dev->checkpt_sum = 0; dev->checkpt_xor = 0; dev->checkpt_cur_block = -1; dev->checkpt_cur_chunk = -1; dev->checkpt_next_block = dev->internal_start_block; /* Erase all the blocks in the checkpoint area */ if (writing) { memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk); dev->checkpt_byte_offs = 0; return yaffs_checkpt_erase(dev); } else { int i; /* Set to a value that will kick off a read */ dev->checkpt_byte_offs = dev->data_bytes_per_chunk; /* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully) * going to be way more than we need */ dev->blocks_in_checkpt = 0; dev->checkpt_max_blocks = (dev->internal_end_block - dev->internal_start_block)/16 + 2; dev->checkpt_block_list = YMALLOC(sizeof(int) * dev->checkpt_max_blocks); if(!dev->checkpt_block_list) return 0; for (i = 0; i < dev->checkpt_max_blocks; i++) dev->checkpt_block_list[i] = -1; } return 1; }
/* * yht_new() * Creates a new hash table. */ yhashtable_t *yht_new(yht_size_t size, yht_function_t destroy_func, void *destroy_data) { yhashtable_t *hash; hash = (yhashtable_t*)YMALLOC(sizeof(yhashtable_t)); hash->buckets = (yht_bucket_t*)YCALLOC(size, sizeof(yht_bucket_t)); hash->size = size; hash->used = 0; hash->items = NULL; hash->next_offset = 0; hash->destroy_func = destroy_func; hash->destroy_data = destroy_data; return (hash); }
void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev) { yaffs_Allocator *allocator; if(!dev->allocator){ allocator = YMALLOC(sizeof(yaffs_Allocator)); if(allocator){ dev->allocator = allocator; yaffs_InitialiseRawTnodes(dev); yaffs_InitialiseRawObjects(dev); } } else YBUG(); }
void yaffs_init_raw_tnodes_and_objs(yaffs_dev_t *dev) { yaffs_Allocator *allocator; if(!dev->allocator){ allocator = YMALLOC(sizeof(yaffs_Allocator)); if(allocator){ dev->allocator = allocator; yaffs_init_raw_tnodes(dev); yaffs_init_raw_objs(dev); } } else YBUG(); }
YMStringRef YMStringCreateByAppendingString(YMStringRef base, YMStringRef append) { const char* cBase = YMStringGetCString(base); const char *cAppend = YMStringGetCString(append); size_t baseLen = strlen(cBase); size_t appendLen = strlen(cAppend); size_t newStringLen = baseLen + appendLen + 1; char *newString = (char *)YMALLOC(newStringLen); memcpy(newString, cBase, baseLen); memcpy(newString + baseLen, cAppend, appendLen); newString[newStringLen - 1] = '\0'; return __YMStringCreate(newString, baseLen + appendLen); }
void __YMPlexerDispatchFunctionWithName(__ym_plexer_t *p, YMStreamRef stream, YMThreadRef targetThread, ym_dispatch_user_func function, YMStringRef nameToRelease) { _ym_plexer_and_stream_t *notifyDef = (_ym_plexer_and_stream_t *)YMALLOC(sizeof(_ym_plexer_and_stream_t)); notifyDef->p = (__ym_plexer_t *)YMRetain(p); notifyDef->s = stream ? YMRetain(stream) : NULL; ym_thread_dispatch_user_t dispatch = { function, NULL, true, notifyDef, nameToRelease }; //#define YMPLEXER_NO_EVENT_QUEUE // for debugging #ifdef YMPLEXER_NO_EVENT_QUEUE __unused const void *silence = targetThread; function(&dispatch); free(notifyDef); #else YMThreadDispatchDispatch(targetThread, dispatch); #endif YMRelease(nameToRelease); }
YMStringRef YMStringCreateWithFormat(const char *format,...) { va_list formatArgs2,formatArgs; va_start(formatArgs2,format); va_copy(formatArgs,formatArgs2); int length = vsnprintf(NULL, 0, format, formatArgs2) + 1; char *newStr = NULL; if ( length == 0 ) newStr = ""; else if ( length < 0 ) ymerr("snprintf failed on format: %s", format); else { newStr = (char *)YMALLOC(length); vsnprintf(newStr, length, format, formatArgs); va_end(formatArgs); } va_end(formatArgs2); return __YMStringCreate(newStr, length - 1); }
struct yaffs_DeviceStruct *ynandsim_CreateRamSim(const YCHAR *name, __u32 devId, __u32 nBlocks, __u32 startBlock, __u32 endBlock) { SimData *sim; ynandif_Geometry *g; ynandsim_InitDevice(); sim = ynandsim_AllocSimData(devId, nBlocks, startBlock, endBlock); g = YMALLOC(sizeof(ynandif_Geometry)); if(!sim || !g){ if(g) YFREE(g); return NULL; } if((endBlock == 0) || (endBlock >= (startBlock + sim->nBlocks))) endBlock = (startBlock + sim->nBlocks) - 1; memset(g,0,sizeof(ynandif_Geometry)); g->startBlock = startBlock; g->endBlock = endBlock; g->dataSize = DATA_SIZE; g->spareSize= SPARE_SIZE; g->pagesPerBlock = PAGES_PER_BLOCK; g->hasECC = 1; g->inbandTags = 0; g->useYaffs2 = 1; g->initialise = ynandsim_Initialise; g->deinitialise = ynandsim_Deinitialise; g->readChunk = ynandsim_ReadChunk, g->writeChunk = ynandsim_WriteChunk, g->eraseBlock = ynandsim_EraseBlock, g->checkBlockOk = ynandsim_CheckBlockOk, g->markBlockBad = ynandsim_MarkBlockBad, g->privateData = (void *)sim; return yaffs_AddDeviceFromGeometry(name,g); }
bool YMmDNSServiceSetTXTRecord( YMmDNSServiceRef s_, YMmDNSTxtRecordKeyPair *keyPairs[], size_t nPairs ) { __ym_mdns_service_t *s = (__ym_mdns_service_t *)s_; if ( keyPairs == NULL || nPairs == 0 ) return false; size_t idx; TXTRecordRef *txtRecord = (TXTRecordRef *)YMALLOC(sizeof(TXTRecordRef)); TXTRecordCreate(txtRecord, 0, NULL); for ( idx = 0; idx < nPairs; idx++ ) { YMmDNSTxtRecordKeyPair **_keyPairs = (YMmDNSTxtRecordKeyPair **)keyPairs; const char *key = YMSTR(_keyPairs[idx]->key); const uint8_t *value = _keyPairs[idx]->value; uint8_t valueLen = _keyPairs[idx]->valueLen; TXTRecordSetValue(txtRecord, key, valueLen, value); } s->txtRecord = (uint8_t *)txtRecord; return true; }
static int CheckInit(void) { static int initialised = 0; int i,j; int fail = 0; int nBlocks; int nAllocated = 0; if(initialised) { return YAFFS_OK; } ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks(); ned.block = YMALLOC(sizeof(nandemul_Block*) * nBlocks ); if(!ned.block) return YAFFS_FAIL; for(i=fail=0; i <nBlocks; i++) { nandemul_Block *blk; if(!(blk = ned.block[i] = YMALLOC(sizeof(nandemul_Block)))) { fail = 1; } else { for(j = 0; j < PAGES_PER_BLOCK; j++) { if((blk->page[j] = YMALLOC(sizeof(nandemul_Page))) == 0) { fail = 1; } } nandemul_ReallyEraseBlock(i); ned.block[i]->damaged = 0; nAllocated++; } } if(fail) { //Todo thump pages for(i = 0; i < nAllocated; i++) { YFREE(ned.block[i]); } YFREE(ned.block); T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", nAllocated/64,sizeInMB)); return 0; } ned.nBlocks = nBlocks; initialised = 1; return 1; }
int yaffs1_scan(yaffs_dev_t *dev) { yaffs_ext_tags tags; int blk; int result; int chunk; int c; int deleted; yaffs_block_state_t state; yaffs_obj_t *hard_list = NULL; yaffs_block_info_t *bi; __u32 seq_number; yaffs_obj_header *oh; yaffs_obj_t *in; yaffs_obj_t *parent; int alloc_failed = 0; struct yaffs_shadow_fixer_s *shadow_fixers = NULL; __u8 *chunk_data; T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_scan starts intstartblk %d intendblk %d..." TENDSTR), dev->internal_start_block, dev->internal_end_block)); chunk_data = yaffs_get_temp_buffer(dev, __LINE__); dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER; /* Scan all the blocks to determine their state */ bi = dev->block_info; for (blk = dev->internal_start_block; blk <= dev->internal_end_block; blk++) { yaffs_clear_chunk_bits(dev, blk); bi->pages_in_use = 0; bi->soft_del_pages = 0; yaffs_query_init_block_state(dev, blk, &state, &seq_number); bi->block_state = state; bi->seq_number = seq_number; if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK) bi->block_state = state = YAFFS_BLOCK_STATE_DEAD; T(YAFFS_TRACE_SCAN_DEBUG, (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, state, seq_number)); if (state == YAFFS_BLOCK_STATE_DEAD) { T(YAFFS_TRACE_BAD_BLOCKS, (TSTR("block %d is bad" TENDSTR), blk)); } else if (state == YAFFS_BLOCK_STATE_EMPTY) { T(YAFFS_TRACE_SCAN_DEBUG, (TSTR("Block empty " TENDSTR))); dev->n_erased_blocks++; dev->n_free_chunks += dev->param.chunks_per_block; } bi++; } /* For each block.... */ for (blk= dev->internal_start_block; !alloc_failed && blk <= dev->internal_end_block; blk++) { YYIELD(); bi = yaffs_get_block_info(dev, blk); state = bi->block_state; deleted = 0; /* For each chunk in each block that needs scanning....*/ for (c = 0; !alloc_failed && c < dev->param.chunks_per_block && state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) { /* Read the tags and decide what to do */ chunk = blk * dev->param.chunks_per_block + c; result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags); /* Let's have a good look at this chunk... */ if (tags.ecc_result == YAFFS_ECC_RESULT_UNFIXED || tags.is_deleted) { /* YAFFS1 only... * A deleted chunk */ deleted++; dev->n_free_chunks++; /*T((" %d %d deleted\n",blk,c)); */ } else if (!tags.chunk_used) { /* An unassigned chunk in the block * This means that either the block is empty or * this is the one being allocated from */ if (c == 0) { /* We're looking at the first chunk in the block so the block is unused */ state = YAFFS_BLOCK_STATE_EMPTY; dev->n_erased_blocks++; } else { /* this is the block being allocated from */ T(YAFFS_TRACE_SCAN, (TSTR (" Allocating from %d %d" TENDSTR), blk, c)); state = YAFFS_BLOCK_STATE_ALLOCATING; dev->alloc_block = blk; dev->alloc_page = c; dev->alloc_block_finder = blk; /* Set block finder here to encourage the allocator to go forth from here. */ } dev->n_free_chunks += (dev->param.chunks_per_block - c); } else if (tags.chunk_id > 0) { /* chunk_id > 0 so it is a data chunk... */ unsigned int endpos; yaffs_set_chunk_bit(dev, blk, c); bi->pages_in_use++; in = yaffs_find_or_create_by_number(dev, tags. obj_id, YAFFS_OBJECT_TYPE_FILE); /* PutChunkIntoFile checks for a clash (two data chunks with * the same chunk_id). */ if (!in) alloc_failed = 1; if (in) { if (!yaffs_put_chunk_in_file(in, tags.chunk_id, chunk, 1)) alloc_failed = 1; } endpos = (tags.chunk_id - 1) * dev->data_bytes_per_chunk + tags.n_bytes; if (in && in->variant_type == YAFFS_OBJECT_TYPE_FILE && in->variant.file_variant.scanned_size < endpos) { in->variant.file_variant. scanned_size = endpos; if (!dev->param.use_header_file_size) { in->variant.file_variant. file_size = in->variant.file_variant. scanned_size; } } /* T((" %d %d data %d %d\n",blk,c,tags.obj_id,tags.chunk_id)); */ } else { /* chunk_id == 0, so it is an ObjectHeader. * Thus, we read in the object header and make the object */ yaffs_set_chunk_bit(dev, blk, c); bi->pages_in_use++; result = yaffs_rd_chunk_tags_nand(dev, chunk, chunk_data, NULL); oh = (yaffs_obj_header *) chunk_data; in = yaffs_find_by_number(dev, tags.obj_id); if (in && in->variant_type != oh->type) { /* This should not happen, but somehow * Wev'e ended up with an obj_id that has been reused but not yet * deleted, and worse still it has changed type. Delete the old object. */ yaffs_del_obj(in); in = 0; } in = yaffs_find_or_create_by_number(dev, tags. obj_id, oh->type); if (!in) alloc_failed = 1; if (in && oh->shadows_obj > 0) { struct yaffs_shadow_fixer_s *fixer; fixer = YMALLOC(sizeof(struct yaffs_shadow_fixer_s)); if (fixer) { fixer->next = shadow_fixers; shadow_fixers = fixer; fixer->obj_id = tags.obj_id; fixer->shadowed_id = oh->shadows_obj; T(YAFFS_TRACE_SCAN, (TSTR (" Shadow fixer: %d shadows %d" TENDSTR), fixer->obj_id, fixer->shadowed_id)); } } if (in && in->valid) { /* We have already filled this one. We have a duplicate and need to resolve it. */ unsigned existing_serial = in->serial; unsigned new_serial = tags.serial_number; if (((existing_serial + 1) & 3) == new_serial) { /* Use new one - destroy the exisiting one */ yaffs_chunk_del(dev, in->hdr_chunk, 1, __LINE__); in->valid = 0; } else { /* Use existing - destroy this one. */ yaffs_chunk_del(dev, chunk, 1, __LINE__); } } if (in && !in->valid && (tags.obj_id == YAFFS_OBJECTID_ROOT || tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND)) { /* We only load some info, don't fiddle with directory structure */ in->valid = 1; in->variant_type = oh->type; in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE in->win_atime[0] = oh->win_atime[0]; in->win_ctime[0] = oh->win_ctime[0]; in->win_mtime[0] = oh->win_mtime[0]; in->win_atime[1] = oh->win_atime[1]; in->win_ctime[1] = oh->win_ctime[1]; in->win_mtime[1] = oh->win_mtime[1]; #else in->yst_uid = oh->yst_uid; in->yst_gid = oh->yst_gid; in->yst_atime = oh->yst_atime; in->yst_mtime = oh->yst_mtime; in->yst_ctime = oh->yst_ctime; in->yst_rdev = oh->yst_rdev; #endif in->hdr_chunk = chunk; in->serial = tags.serial_number; } else if (in && !in->valid) { /* we need to load this info */ in->valid = 1; in->variant_type = oh->type; in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE in->win_atime[0] = oh->win_atime[0]; in->win_ctime[0] = oh->win_ctime[0]; in->win_mtime[0] = oh->win_mtime[0]; in->win_atime[1] = oh->win_atime[1]; in->win_ctime[1] = oh->win_ctime[1]; in->win_mtime[1] = oh->win_mtime[1]; #else in->yst_uid = oh->yst_uid; in->yst_gid = oh->yst_gid; in->yst_atime = oh->yst_atime; in->yst_mtime = oh->yst_mtime; in->yst_ctime = oh->yst_ctime; in->yst_rdev = oh->yst_rdev; #endif in->hdr_chunk = chunk; in->serial = tags.serial_number; yaffs_set_obj_name_from_oh(in, oh); in->dirty = 0; /* directory stuff... * hook up to parent */ parent = yaffs_find_or_create_by_number (dev, oh->parent_obj_id, YAFFS_OBJECT_TYPE_DIRECTORY); if (!parent) alloc_failed = 1; if (parent && parent->variant_type == YAFFS_OBJECT_TYPE_UNKNOWN) { /* Set up as a directory */ parent->variant_type = YAFFS_OBJECT_TYPE_DIRECTORY; YINIT_LIST_HEAD(&parent->variant. dir_variant. children); } else if (!parent || parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { /* Hoosterman, another problem.... * We're trying to use a non-directory as a directory */ T(YAFFS_TRACE_ERROR, (TSTR ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR))); parent = dev->lost_n_found; } yaffs_add_obj_to_dir(parent, in); if (0 && (parent == dev->del_dir || parent == dev->unlinked_dir)) { in->deleted = 1; /* If it is unlinked at start up then it wants deleting */ dev->n_deleted_files++; } /* Note re hardlinks. * Since we might scan a hardlink before its equivalent object is scanned * we put them all in a list. * After scanning is complete, we should have all the objects, so we run through this * list and fix up all the chains. */ switch (in->variant_type) { case YAFFS_OBJECT_TYPE_UNKNOWN: /* Todo got a problem */ break; case YAFFS_OBJECT_TYPE_FILE: if (dev->param.use_header_file_size) in->variant.file_variant. file_size = oh->file_size; break; case YAFFS_OBJECT_TYPE_HARDLINK: in->variant.hardlink_variant. equiv_id = oh->equiv_id; in->hard_links.next = (struct ylist_head *) hard_list; hard_list = in; break; case YAFFS_OBJECT_TYPE_DIRECTORY: /* Do nothing */ break; case YAFFS_OBJECT_TYPE_SPECIAL: /* Do nothing */ break; case YAFFS_OBJECT_TYPE_SYMLINK: in->variant.symlink_variant.alias = yaffs_clone_str(oh->alias); if (!in->variant.symlink_variant.alias) alloc_failed = 1; break; } } } } if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { /* If we got this far while scanning, then the block is fully allocated.*/ state = YAFFS_BLOCK_STATE_FULL; } if (state == YAFFS_BLOCK_STATE_ALLOCATING) { /* If the block was partially allocated then treat it as fully allocated.*/ state = YAFFS_BLOCK_STATE_FULL; dev->alloc_block = -1; } bi->block_state = state; /* Now let's see if it was dirty */ if (bi->pages_in_use == 0 && !bi->has_shrink_hdr && bi->block_state == YAFFS_BLOCK_STATE_FULL) { yaffs_block_became_dirty(dev, blk); } } /* Ok, we've done all the scanning. * Fix up the hard link chains. * We should now have scanned all the objects, now it's time to add these * hardlinks. */ yaffs_link_fixup(dev, hard_list); /* Fix up any shadowed objects */ { struct yaffs_shadow_fixer_s *fixer; yaffs_obj_t *obj; while (shadow_fixers) { fixer = shadow_fixers; shadow_fixers = fixer->next; /* Complete the rename transaction by deleting the shadowed object * then setting the object header to unshadowed. */ obj = yaffs_find_by_number(dev, fixer->shadowed_id); if (obj) yaffs_del_obj(obj); obj = yaffs_find_by_number(dev, fixer->obj_id); if (obj) yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); YFREE(fixer); } } yaffs_release_temp_buffer(dev, chunk_data, __LINE__); if (alloc_failed) return YAFFS_FAIL; T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_scan ends" TENDSTR))); return YAFFS_OK; }
yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev) { dev = dev; return (yaffs_Object *) YMALLOC(sizeof(yaffs_Object)); }
/* * _yht_add * Add an element to a hash table, using a string or an integer key. */ static void _yht_add(yhashtable_t *hashtable, yht_hash_value_t hash_value, char *key, void *data) { float load_factor; yht_hash_value_t modulo_value; yht_bucket_t *bucket; yht_element_t *element; yht_list_t *item; /* resize the table if its load factor would excess the limit */ load_factor = (float)(hashtable->used + 1) / hashtable->size; if (load_factor > YHT_MAX_LOAD_FACTOR) yht_resize(hashtable, (hashtable->size * 2)); /* compute the key's hash value */ if (key != NULL) hash_value = yht_hash(key); modulo_value = hash_value % hashtable->size; /* checking the bucket */ bucket = &(hashtable->buckets[modulo_value]); if (bucket->nbr_elements == 0) { /* create the first element */ element = (yht_element_t*)YMALLOC(sizeof(yht_element_t)); item = (yht_list_t*)YMALLOC(sizeof(yht_list_t)); element->previous = element->next = element; /* add the element to the bucket */ bucket->elements = element; } else { /* there is already some elements in the bucket, checking if the element exists and must be updated */ size_t offset; for (offset = 0, element = bucket->elements; offset < bucket->nbr_elements; offset++, element = element->next) { if (element->hash_value == hash_value && ((key == NULL && element->key == NULL) || (key != NULL && element->key != NULL && !strcmp(key, element->key)))) { /* an existing element was found */ /* removing old data */ if (hashtable->destroy_func != NULL) hashtable->destroy_func(element->hash_value, element->key, element->data, hashtable->destroy_data); /* updating the element */ element->key = key; element->data = data; return; } } /* no element was already existing with this key */ element = (yht_element_t*)YMALLOC(sizeof(yht_element_t)); item = (yht_list_t*)YMALLOC(sizeof(yht_list_t)); /* add the element to the bucket */ element->next = bucket->elements; element->previous = bucket->elements->previous; bucket->elements->previous->next = element; bucket->elements->previous = element; } /* filling the element and the item */ element->hash_value = hash_value; element->key = key; element->data = data; element->item = item; item->element = element; /* update the bucket */ bucket->nbr_elements++; /* update the hash table */ hashtable->used++; /* add the item to the list */ if (hashtable->items == NULL) { hashtable->items = item; item->next = item->previous = item; }else { item->next = hashtable->items; item->previous = hashtable->items->previous; hashtable->items->previous->next = item; hashtable->items->previous = item; } }
void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev) { yaffs_Allocator *allocator; unsigned mount_id = yaffs_DeviceToLC(dev)->mount_id; T(YAFFS_TRACE_ALLOCATE,(TSTR("Initialising yaffs allocator\n"))); if(dev->allocator) YBUG(); else if(mount_id >= 10){ T(YAFFS_TRACE_ALWAYS,(TSTR("Bad mount_id %u\n"),mount_id)); } else { allocator = YMALLOC(sizeof(yaffs_Allocator)); memset(allocator,0,sizeof(yaffs_Allocator)); dev->allocator = allocator; if(!dev->allocator){ T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs allocator creation failed\n"))); YBUG(); return; } sprintf(allocator->tnode_name,"yaffs_t_%u",mount_id); sprintf(allocator->object_name,"yaffs_o_%u",mount_id); allocator->tnode_cache = kmem_cache_create(allocator->tnode_name, dev->tnodeSize, 0, 0, fake_ctor_list[mount_id]); if(allocator->tnode_cache) T(YAFFS_TRACE_ALLOCATE, (TSTR("tnode cache \"%s\" %p\n"), allocator->tnode_name,allocator->tnode_cache)); else { T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs cache creation failed\n"))); YBUG(); } allocator->object_cache = kmem_cache_create(allocator->object_name, sizeof(yaffs_Object), 0, 0, fake_ctor_list[mount_id]); if(allocator->object_cache) T(YAFFS_TRACE_ALLOCATE, (TSTR("object cache \"%s\" %p\n"), allocator->object_name,allocator->object_cache)); else { T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs cache creation failed\n"))); YBUG(); } } }
int yaffs_StartUp(void) { struct mtd_info *mtd = &nand_info[0]; int yaffsVersion = 2; int nBlocks; yaffs_Device *flashDev = calloc(1, sizeof(yaffs_Device)); yaffsfs_config[0].dev = flashDev; /* store the mtd device for later use */ flashDev->genericDevice = mtd; // Stuff to configure YAFFS // Stuff to initialise anything special (eg lock semaphore). yaffsfs_LocalInitialisation(); // Set up devices /* XXX U-BOOT XXX */ #if 0 // /ram ramDev.nBytesPerChunk = 512; ramDev.nChunksPerBlock = 32; ramDev.nReservedBlocks = 2; // Set this smaller for RAM ramDev.startBlock = 1; // Can't use block 0 ramDev.endBlock = 127; // Last block in 2MB. ramDev.useNANDECC = 1; ramDev.nShortOpCaches = 0; // Disable caching on this device. ramDev.genericDevice = (void *) 0; // Used to identify the device in fstat. ramDev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND; ramDev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND; ramDev.eraseBlockInNAND = yramdisk_EraseBlockInNAND; ramDev.initialiseNAND = yramdisk_InitialiseNAND; // /boot bootDev.nBytesPerChunk = 612; bootDev.nChunksPerBlock = 32; bootDev.nReservedBlocks = 5; bootDev.startBlock = 1; // Can't use block 0 bootDev.endBlock = 127; // Last block in 2MB. bootDev.useNANDECC = 0; // use YAFFS's ECC bootDev.nShortOpCaches = 10; // Use caches bootDev.genericDevice = (void *) 1; // Used to identify the device in fstat. bootDev.writeChunkToNAND = yflash_WriteChunkToNAND; bootDev.readChunkFromNAND = yflash_ReadChunkFromNAND; bootDev.eraseBlockInNAND = yflash_EraseBlockInNAND; bootDev.initialiseNAND = yflash_InitialiseNAND; #endif // /flash flashDev->nReservedBlocks = 5; // flashDev->nShortOpCaches = (options.no_cache) ? 0 : 10; flashDev->nShortOpCaches = 10; // Use caches flashDev->useNANDECC = 0; // do not use YAFFS's ECC if (yaffsVersion == 2) { flashDev->writeChunkWithTagsToNAND = nandmtd2_WriteChunkWithTagsToNAND; flashDev->readChunkWithTagsFromNAND = nandmtd2_ReadChunkWithTagsFromNAND; flashDev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad; flashDev->queryNANDBlock = nandmtd2_QueryNANDBlock; flashDev->spareBuffer = YMALLOC(mtd->oobsize); flashDev->isYaffs2 = 1; #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) flashDev->nDataBytesPerChunk = mtd->writesize; flashDev->nChunksPerBlock = mtd->erasesize / mtd->writesize; #else flashDev->nDataBytesPerChunk = mtd->oobblock; flashDev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; #endif nBlocks = mtd->size / mtd->erasesize; flashDev->nCheckpointReservedBlocks = 10; flashDev->startBlock = 0; flashDev->endBlock = nBlocks - 1; } else { flashDev->writeChunkToNAND = nandmtd_WriteChunkToNAND; flashDev->readChunkFromNAND = nandmtd_ReadChunkFromNAND; flashDev->isYaffs2 = 0; nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); flashDev->startBlock = 320; flashDev->endBlock = nBlocks - 1; flashDev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; flashDev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; } /* ... and common functions */ flashDev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; flashDev->initialiseNAND = nandmtd_InitialiseNAND; yaffs_initialise(yaffsfs_config); return 0; }
/* Process a DEL command. */ yerr_t command_del(tcp_thread_t *thread, ybool_t sync, ybool_t compress, ybool_t serialized, ydynabin_t *buff) { uint16_t *pkey_len, key_len; void *ptr, *key = NULL; writer_msg_t *msg = NULL; char answer; YLOG_ADD(YLOG_DEBUG, "DEL command"); // read key length if (connection_read_data(thread, buff, sizeof(key_len)) != YENOERR) goto error; pkey_len = ydynabin_forward(buff, sizeof(key_len)); key_len = ntohs(*pkey_len); // read key if (connection_read_data(thread, buff, (size_t)key_len) != YENOERR) goto error; ptr = ydynabin_forward(buff, (size_t)key_len); if ((key = YMALLOC((size_t)key_len)) == NULL) goto error; memcpy(key, ptr, (size_t)key_len); if (!sync) { // send the response connection_send_response(thread, RESP_OK, YFALSE, YFALSE, NULL, 0); } // creation of the message if ((msg = YMALLOC(sizeof(writer_msg_t))) == NULL) goto error; msg->type = WRITE_DEL; ybin_set(&msg->name, key, key_len); if (!sync) { msg->dbname = thread->dbname ? strdup(thread->dbname) : NULL; // send the message to the writer thread if (nn_send(thread->write_sock, &msg, sizeof(msg), 0) < 0) { YLOG_ADD(YLOG_WARN, "Unable to send message to writer thread."); goto error; } return (YENOERR); } // synchronized if (database_del(thread->finedb->database, thread->transaction, thread->dbname, msg->name) == YENOERR) { YLOG_ADD(YLOG_DEBUG, "Deletion done on database."); answer = 1; } else { YLOG_ADD(YLOG_WARN, "Unable to delete data on database."); answer = 0; } YFREE(key); YFREE(msg); YLOG_ADD(YLOG_DEBUG, "DEL command %s", (answer ? "OK" : "failed")); if (!sync) return (YENOERR); return (connection_send_response(thread, (answer ? RESP_OK : RESP_ERR_BAD_NAME), YFALSE, YFALSE, NULL, 0)); error: YLOG_ADD(YLOG_WARN, "PUT error"); YFREE(key); YFREE(msg); CONNECTION_SEND_ERROR(thread, RESP_ERR_SERVER); return (YEIO); }
yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev) { return (yaffs_Tnode *)YMALLOC(dev->tnodeSize); }
/* List the keys stored in database. */ void command_list(cli_t *cli, char *pt) { char *buffer, c; size_t sz, offset, length, rc; LTRIM(pt); // create sending buffer sz = 1; if (cli->dbname) sz += 1 + strlen(cli->dbname); buffer = YMALLOC(sz); // set the code byte buffer[0] = PROTO_LIST; if (cli->dbname) buffer[0] = REQUEST_ADD_DBNAME(buffer[0]); // dbname offset = 1; if (cli->dbname) { length = strlen(cli->dbname); buffer[offset] = (char)length; offset++; memcpy(&buffer[offset], cli->dbname, length); offset += length; } { size_t n; for (n = 0; n < sz; n++) printf("%02x ", buffer[n]); printf("\n"); } // send data rc = write(cli->fd, buffer, sz); YFREE(buffer); if (rc != sz) { printf("%c[Connection error%c[0m\n", 27, 27); return; } // get response if (read(cli->fd, &c, 1) != 1) { printf("%c[Connection error%c[0m\n", 27, 27); return; } if (RESPONSE_CODE(c) != RESP_OK) { printf("%c[2mERROR: %s%c[0m\n", 27, (RESPONSE_CODE(c) == RESP_PROTO ? "protocol" : (RESPONSE_CODE(c) == RESP_SERVER_ERR ? "server" : (RESPONSE_CODE(c) == RESP_NO_DATA ? "no data" : "unknown"))), 27); return; } printf("%c[2mOK%c[0m\n", 27, 27); for (; ; ) { uint16_t ln = 0, lh; if (read(cli->fd, &ln, 2) < 2) break; lh = ntohs(ln); buffer = YMALLOC(lh + 1); if (read(cli->fd, buffer, lh) != lh) { printf("%c[Connection error%c[0m\n", 27, 27); YFREE(buffer); return; } printf("%c[2m%s%c[0m\n", 27, buffer, 27); YFREE(buffer); } }
yaffs_tnode_t *yaffs_alloc_raw_tnode(yaffs_dev_t *dev) { return (yaffs_tnode_t *)YMALLOC(dev->tnode_size); }
static int yaffs_create_tnodes(yaffs_dev_t *dev, int n_tnodes) { yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator; int i; yaffs_tnode_t *newTnodes; __u8 *mem; yaffs_tnode_t *curr; yaffs_tnode_t *next; yaffs_tnodelist_t *tnl; if(!allocator){ YBUG(); return YAFFS_FAIL; } if (n_tnodes < 1) return YAFFS_OK; /* make these things */ newTnodes = YMALLOC(n_tnodes * dev->tnode_size); mem = (__u8 *)newTnodes; if (!newTnodes) { T(YAFFS_TRACE_ERROR, (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); return YAFFS_FAIL; } /* New hookup for wide tnodes */ for (i = 0; i < n_tnodes - 1; i++) { curr = (yaffs_tnode_t *) &mem[i * dev->tnode_size]; next = (yaffs_tnode_t *) &mem[(i+1) * dev->tnode_size]; curr->internal[0] = next; } curr = (yaffs_tnode_t *) &mem[(n_tnodes - 1) * dev->tnode_size]; curr->internal[0] = allocator->freeTnodes; allocator->freeTnodes = (yaffs_tnode_t *)mem; allocator->nFreeTnodes += n_tnodes; allocator->n_tnodesCreated += n_tnodes; /* Now add this bunch of tnodes to a list for freeing up. * NB If we can't add this to the management list it isn't fatal * but it just means we can't free this bunch of tnodes later. */ tnl = YMALLOC(sizeof(yaffs_tnodelist_t)); if (!tnl) { T(YAFFS_TRACE_ERROR, (TSTR ("yaffs: Could not add tnodes to management list" TENDSTR))); return YAFFS_FAIL; } else { tnl->tnodes = newTnodes; tnl->next = allocator->allocatedTnodeList; allocator->allocatedTnodeList = tnl; } T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR))); return YAFFS_OK; }
int yaffs1_Scan(yaffs_Device *dev) { yaffs_ExtendedTags tags; int blk; int blockIterator; int startIterator; int endIterator; int result; int chunk; int c; int deleted; yaffs_BlockState state; yaffs_Object *hardList = NULL; yaffs_BlockInfo *bi; __u32 sequenceNumber; yaffs_ObjectHeader *oh; yaffs_Object *in; yaffs_Object *parent; int alloc_failed = 0; struct yaffs_ShadowFixerStruct *shadowFixerList = NULL; __u8 *chunkData; T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_Scan starts intstartblk %d intendblk %d..." TENDSTR), dev->internalStartBlock, dev->internalEndBlock)); chunkData = yaffs_GetTempBuffer(dev, __LINE__); dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; /* Scan all the blocks to determine their state */ bi = dev->blockInfo; for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) { yaffs_ClearChunkBits(dev, blk); bi->pagesInUse = 0; bi->softDeletions = 0; yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber); bi->blockState = state; bi->sequenceNumber = sequenceNumber; if (bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK) bi->blockState = state = YAFFS_BLOCK_STATE_DEAD; T(YAFFS_TRACE_SCAN_DEBUG, (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, state, sequenceNumber)); if (state == YAFFS_BLOCK_STATE_DEAD) { T(YAFFS_TRACE_BAD_BLOCKS, (TSTR("block %d is bad" TENDSTR), blk)); } else if (state == YAFFS_BLOCK_STATE_EMPTY) { T(YAFFS_TRACE_SCAN_DEBUG, (TSTR("Block empty " TENDSTR))); dev->nErasedBlocks++; dev->nFreeChunks += dev->param.nChunksPerBlock; } bi++; } startIterator = dev->internalStartBlock; endIterator = dev->internalEndBlock; /* For each block.... */ for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator; blockIterator++) { YYIELD(); YYIELD(); blk = blockIterator; bi = yaffs_GetBlockInfo(dev, blk); state = bi->blockState; deleted = 0; /* For each chunk in each block that needs scanning....*/ for (c = 0; !alloc_failed && c < dev->param.nChunksPerBlock && state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) { /* Read the tags and decide what to do */ chunk = blk * dev->param.nChunksPerBlock + c; result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL, &tags); /* Let's have a good look at this chunk... */ if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) { /* YAFFS1 only... * A deleted chunk */ deleted++; dev->nFreeChunks++; /*T((" %d %d deleted\n",blk,c)); */ } else if (!tags.chunkUsed) { /* An unassigned chunk in the block * This means that either the block is empty or * this is the one being allocated from */ if (c == 0) { /* We're looking at the first chunk in the block so the block is unused */ state = YAFFS_BLOCK_STATE_EMPTY; dev->nErasedBlocks++; } else { /* this is the block being allocated from */ T(YAFFS_TRACE_SCAN, (TSTR (" Allocating from %d %d" TENDSTR), blk, c)); state = YAFFS_BLOCK_STATE_ALLOCATING; dev->allocationBlock = blk; dev->allocationPage = c; dev->allocationBlockFinder = blk; /* Set block finder here to encourage the allocator to go forth from here. */ } dev->nFreeChunks += (dev->param.nChunksPerBlock - c); } else if (tags.chunkId > 0) { /* chunkId > 0 so it is a data chunk... */ unsigned int endpos; yaffs_SetChunkBit(dev, blk, c); bi->pagesInUse++; in = yaffs_FindOrCreateObjectByNumber(dev, tags. objectId, YAFFS_OBJECT_TYPE_FILE); /* PutChunkIntoFile checks for a clash (two data chunks with * the same chunkId). */ if (!in) alloc_failed = 1; if (in) { if (!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, 1)) alloc_failed = 1; } endpos = (tags.chunkId - 1) * dev->nDataBytesPerChunk + tags.byteCount; if (in && in->variantType == YAFFS_OBJECT_TYPE_FILE && in->variant.fileVariant.scannedFileSize < endpos) { in->variant.fileVariant. scannedFileSize = endpos; if (!dev->param.useHeaderFileSize) { in->variant.fileVariant. fileSize = in->variant.fileVariant. scannedFileSize; } } /* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); */ } else { /* chunkId == 0, so it is an ObjectHeader. * Thus, we read in the object header and make the object */ yaffs_SetChunkBit(dev, blk, c); bi->pagesInUse++; result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, chunkData, NULL); oh = (yaffs_ObjectHeader *) chunkData; in = yaffs_FindObjectByNumber(dev, tags.objectId); if (in && in->variantType != oh->type) { /* This should not happen, but somehow * Wev'e ended up with an objectId that has been reused but not yet * deleted, and worse still it has changed type. Delete the old object. */ yaffs_DeleteObject(in); in = 0; } in = yaffs_FindOrCreateObjectByNumber(dev, tags. objectId, oh->type); if (!in) alloc_failed = 1; if (in && oh->shadowsObject > 0) { struct yaffs_ShadowFixerStruct *fixer; fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct)); if (fixer) { fixer->next = shadowFixerList; shadowFixerList = fixer; fixer->objectId = tags.objectId; fixer->shadowedId = oh->shadowsObject; } } if (in && in->valid) { /* We have already filled this one. We have a duplicate and need to resolve it. */ unsigned existingSerial = in->serial; unsigned newSerial = tags.serialNumber; if (((existingSerial + 1) & 3) == newSerial) { /* Use new one - destroy the exisiting one */ yaffs_DeleteChunk(dev, in->hdrChunk, 1, __LINE__); in->valid = 0; } else { /* Use existing - destroy this one. */ yaffs_DeleteChunk(dev, chunk, 1, __LINE__); } } if (in && !in->valid && (tags.objectId == YAFFS_OBJECTID_ROOT || tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) { /* We only load some info, don't fiddle with directory structure */ in->valid = 1; in->variantType = oh->type; in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE in->win_atime[0] = oh->win_atime[0]; in->win_ctime[0] = oh->win_ctime[0]; in->win_mtime[0] = oh->win_mtime[0]; in->win_atime[1] = oh->win_atime[1]; in->win_ctime[1] = oh->win_ctime[1]; in->win_mtime[1] = oh->win_mtime[1]; #else in->yst_uid = oh->yst_uid; in->yst_gid = oh->yst_gid; in->yst_atime = oh->yst_atime; in->yst_mtime = oh->yst_mtime; in->yst_ctime = oh->yst_ctime; in->yst_rdev = oh->yst_rdev; #endif in->hdrChunk = chunk; in->serial = tags.serialNumber; } else if (in && !in->valid) { /* we need to load this info */ in->valid = 1; in->variantType = oh->type; in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE in->win_atime[0] = oh->win_atime[0]; in->win_ctime[0] = oh->win_ctime[0]; in->win_mtime[0] = oh->win_mtime[0]; in->win_atime[1] = oh->win_atime[1]; in->win_ctime[1] = oh->win_ctime[1]; in->win_mtime[1] = oh->win_mtime[1]; #else in->yst_uid = oh->yst_uid; in->yst_gid = oh->yst_gid; in->yst_atime = oh->yst_atime; in->yst_mtime = oh->yst_mtime; in->yst_ctime = oh->yst_ctime; in->yst_rdev = oh->yst_rdev; #endif in->hdrChunk = chunk; in->serial = tags.serialNumber; yaffs_SetObjectNameFromOH(in, oh); in->dirty = 0; /* directory stuff... * hook up to parent */ parent = yaffs_FindOrCreateObjectByNumber (dev, oh->parentObjectId, YAFFS_OBJECT_TYPE_DIRECTORY); if (!parent) alloc_failed = 1; if (parent && parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN) { /* Set up as a directory */ parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY; YINIT_LIST_HEAD(&parent->variant. directoryVariant. children); } else if (!parent || parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { /* Hoosterman, another problem.... * We're trying to use a non-directory as a directory */ T(YAFFS_TRACE_ERROR, (TSTR ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR))); parent = dev->lostNFoundDir; } yaffs_AddObjectToDirectory(parent, in); if (0 && (parent == dev->deletedDir || parent == dev->unlinkedDir)) { in->deleted = 1; /* If it is unlinked at start up then it wants deleting */ dev->nDeletedFiles++; } /* Note re hardlinks. * Since we might scan a hardlink before its equivalent object is scanned * we put them all in a list. * After scanning is complete, we should have all the objects, so we run through this * list and fix up all the chains. */ switch (in->variantType) { case YAFFS_OBJECT_TYPE_UNKNOWN: /* Todo got a problem */ break; case YAFFS_OBJECT_TYPE_FILE: if (dev->param.useHeaderFileSize) in->variant.fileVariant. fileSize = oh->fileSize; break; case YAFFS_OBJECT_TYPE_HARDLINK: in->variant.hardLinkVariant. equivalentObjectId = oh->equivalentObjectId; in->hardLinks.next = (struct ylist_head *) hardList; hardList = in; break; case YAFFS_OBJECT_TYPE_DIRECTORY: /* Do nothing */ break; case YAFFS_OBJECT_TYPE_SPECIAL: /* Do nothing */ break; case YAFFS_OBJECT_TYPE_SYMLINK: in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias); if (!in->variant.symLinkVariant.alias) alloc_failed = 1; break; } } } } if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { /* If we got this far while scanning, then the block is fully allocated.*/ state = YAFFS_BLOCK_STATE_FULL; } if (state == YAFFS_BLOCK_STATE_ALLOCATING) { /* If the block was partially allocated then treat it as fully allocated.*/ state = YAFFS_BLOCK_STATE_FULL; dev->allocationBlock = -1; } bi->blockState = state; /* Now let's see if it was dirty */ if (bi->pagesInUse == 0 && !bi->hasShrinkHeader && bi->blockState == YAFFS_BLOCK_STATE_FULL) { yaffs_BlockBecameDirty(dev, blk); } } /* Ok, we've done all the scanning. * Fix up the hard link chains. * We should now have scanned all the objects, now it's time to add these * hardlinks. */ yaffs_HardlinkFixup(dev, hardList); /* Fix up any shadowed objects */ { struct yaffs_ShadowFixerStruct *fixer; yaffs_Object *obj; while (shadowFixerList) { fixer = shadowFixerList; shadowFixerList = fixer->next; /* Complete the rename transaction by deleting the shadowed object * then setting the object header to unshadowed. */ obj = yaffs_FindObjectByNumber(dev, fixer->shadowedId); if (obj) yaffs_DeleteObject(obj); obj = yaffs_FindObjectByNumber(dev, fixer->objectId); if (obj) yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0, NULL); YFREE(fixer); } } yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); if (alloc_failed) return YAFFS_FAIL; T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_Scan ends" TENDSTR))); return YAFFS_OK; }
yaffs_obj_t *yaffs_alloc_raw_obj(yaffs_dev_t *dev) { dev = dev; return (yaffs_obj_t *) YMALLOC(sizeof(yaffs_obj_t)); }