summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
36dc48e)
Slight changes to urgency thresholds
Fix problem where background gc was interfering with sync resulting in
checkpoints being lost.
Add more tracing for background gc.
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
{
unsigned erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev);
{
unsigned erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev);
+ unsigned scatteredFree = 0; /* Free chunks not in an erased block */
+
+ if(erasedChunks < dev->nFreeChunks)
+ scatteredFree = (dev->nFreeChunks - erasedChunks);
if(!context->bgRunning)
return 0;
if(!context->bgRunning)
return 0;
+ else if(scatteredFree < (dev->param.nChunksPerBlock * 2))
+ return 0;
else if(erasedChunks > dev->nFreeChunks/2)
return 0;
else if(erasedChunks > dev->nFreeChunks/4)
else if(erasedChunks > dev->nFreeChunks/2)
return 0;
else if(erasedChunks > dev->nFreeChunks/4)
yaffs_Device *dev = yaffs_SuperToDevice(sb);
unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
yaffs_Device *dev = yaffs_SuperToDevice(sb);
unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
+ unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
+ int do_checkpoint;
- if(!oneshot_checkpoint &&
- yaffs_bg_gc_urgency(dev) > 0)
- request_checkpoint = 0;
-
- T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
- ("yaffs_do_sync_fs: %s %s%s\n",
+ T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
+ ("yaffs_do_sync_fs: gc-urgency %d %s %s%s\n",
+ gc_urgent,
sb->s_dirt ? "dirty" : "clean",
request_checkpoint ? "checkpoint requested" : "no checkpoint",
oneshot_checkpoint ? " one-shot" : "" ));
sb->s_dirt ? "dirty" : "clean",
request_checkpoint ? "checkpoint requested" : "no checkpoint",
oneshot_checkpoint ? " one-shot" : "" ));
- if (sb->s_dirt || oneshot_checkpoint) {
- yaffs_GrossLock(dev);
- yaffs_FlushSuperBlock(sb, request_checkpoint || oneshot_checkpoint);
- yaffs_GrossUnlock(dev);
+ yaffs_GrossLock(dev);
+ do_checkpoint = ((request_checkpoint && !gc_urgent) ||
+ oneshot_checkpoint) &&
+ !dev->isCheckpointed;
+ if (sb->s_dirt || do_checkpoint) {
+ yaffs_FlushSuperBlock(sb, !dev->isCheckpointed && do_checkpoint);
if(oneshot_checkpoint)
yaffs_auto_checkpoint &= ~4;
}
if(oneshot_checkpoint)
yaffs_auto_checkpoint &= ~4;
}
+ yaffs_GrossUnlock(dev);
- if(time_after(now, next_dir_update) &&
- !dev->isCheckpointed){
+ if(time_after(now, next_dir_update)){
yaffs_UpdateDirtyDirectories(dev);
next_dir_update = now + HZ;
}
yaffs_UpdateDirtyDirectories(dev);
next_dir_update = now + HZ;
}
- if(time_after(now,next_gc) &&
- ! dev->isCheckpointed){
- gcResult = yaffs_BackgroundGarbageCollect(dev);
- urgency = yaffs_bg_gc_urgency(dev);
- if(urgency > 1)
- next_gc = now + HZ/50+1;
- else if(urgency > 0)
- next_gc = now + HZ/20+1;
- else
- next_gc = now + HZ * 2;
+ if(time_after(now,next_gc)){
+ if(!dev->isCheckpointed){
+ urgency = yaffs_bg_gc_urgency(dev);
+ gcResult = yaffs_BackgroundGarbageCollect(dev, urgency);
+ if(urgency > 1)
+ next_gc = now + HZ/20+1;
+ else if(urgency > 0)
+ next_gc = now + HZ/10+1;
+ else
+ next_gc = now + HZ * 2;
+ } else /*
+ * gc not running so set to next_dir_update
+ * to cut down on wake ups
+ */
+ next_gc = next_dir_update;
}
yaffs_GrossUnlock(dev);
#if 1
}
yaffs_GrossUnlock(dev);
#if 1
{
unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
{
unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
- T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
+ T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
("yaffs_write_super%s\n",
request_checkpoint ? " checkpt" : ""));
("yaffs_write_super%s\n",
request_checkpoint ? " checkpt" : ""));
buf += sprintf(buf, "nPageReads......... %u\n", dev->nPageReads);
buf += sprintf(buf, "nBlockErasures..... %u\n", dev->nBlockErasures);
buf += sprintf(buf, "nGCCopies.......... %u\n", dev->nGCCopies);
buf += sprintf(buf, "nPageReads......... %u\n", dev->nPageReads);
buf += sprintf(buf, "nBlockErasures..... %u\n", dev->nBlockErasures);
buf += sprintf(buf, "nGCCopies.......... %u\n", dev->nGCCopies);
- buf += sprintf(buf, "garbageCollections. %u\n", dev->garbageCollections);
- buf += sprintf(buf, "passiveGCs......... %u\n", dev->passiveGarbageCollections);
+ buf += sprintf(buf, "allGCs............. %u\n", dev->allGCs);
+ buf += sprintf(buf, "passiveGCs......... %u\n", dev->passiveGCs);
+ buf += sprintf(buf, "oldestDirtyGCs..... %u\n", dev->oldestDirtyGCs);
+ buf += sprintf(buf, "backgroundGCs...... %u\n", dev->backgroundGCs);
buf += sprintf(buf, "nRetriedWrites..... %u\n", dev->nRetriedWrites);
buf += sprintf(buf, "nRetireBlocks...... %u\n", dev->nRetiredBlocks);
buf += sprintf(buf, "eccFixed........... %u\n", dev->eccFixed);
buf += sprintf(buf, "nRetriedWrites..... %u\n", dev->nRetriedWrites);
buf += sprintf(buf, "nRetireBlocks...... %u\n", dev->nRetiredBlocks);
buf += sprintf(buf, "eccFixed........... %u\n", dev->eccFixed);
nTnodes = dev->nTnodesCreated - dev->nFreeTnodes;
nTnodes = dev->nTnodesCreated - dev->nFreeTnodes;
- buf += sprintf(buf,"%d, %d, %d, %d, %d\n",
+ buf += sprintf(buf,"%d, %d, %d, %u, %u, %d, %d\n",
n, dev->nFreeChunks, erasedChunks,
n, dev->nFreeChunks, erasedChunks,
+ dev->backgroundGCs, dev->oldestDirtyGCs,
nObjects, nTnodes);
}
up(&yaffs_context_lock);
nObjects, nTnodes);
}
up(&yaffs_context_lock);
selected = dev->gcDirtiest;
}
selected = dev->gcDirtiest;
}
- if(!selected && dev->param.isYaffs2 && dev->gcNotDone >= ( background ? 10 : 20)){
+ /*
+ * If nothing has been selected for a while, try selecting the oldest dirty
+ * because that's gumming up the works.
+ */
+
+ if(!selected && dev->param.isYaffs2 &&
+ dev->gcNotDone >= ( background ? 10 : 20)){
yaffs_FindOldestDirtySequence(dev);
if(dev->oldestDirtyBlock > 0) {
selected = dev->oldestDirtyBlock;
dev->gcDirtiest = selected;
yaffs_FindOldestDirtySequence(dev);
if(dev->oldestDirtyBlock > 0) {
selected = dev->oldestDirtyBlock;
dev->gcDirtiest = selected;
bi = yaffs_GetBlockInfo(dev, selected);
dev->gcPagesInUse = bi->pagesInUse - bi->softDeletions;
} else
bi = yaffs_GetBlockInfo(dev, selected);
dev->gcPagesInUse = bi->pagesInUse - bi->softDeletions;
} else
dev->param.nChunksPerBlock - dev->gcPagesInUse,
prioritised));
dev->param.nChunksPerBlock - dev->gcPagesInUse,
prioritised));
+ if(background)
+ dev->backgroundGCs++;
dev->gcDirtiest = 0;
dev->gcPagesInUse = 0;
dev->gcNotDone = 0;
dev->gcDirtiest = 0;
dev->gcPagesInUse = 0;
dev->gcNotDone = 0;
}
if (dev->gcBlock > 0) {
}
if (dev->gcBlock > 0) {
- dev->garbageCollections++;
- dev->passiveGarbageCollections++;
* Garbage collects. Intended to be called from a background thread.
* Returns non-zero if at least half the free chunks are erased.
*/
* Garbage collects. Intended to be called from a background thread.
* Returns non-zero if at least half the free chunks are erased.
*/
-int yaffs_BackgroundGarbageCollect(yaffs_Device *dev)
+int yaffs_BackgroundGarbageCollect(yaffs_Device *dev, unsigned urgency)
{
int erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
{
int erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
- T(YAFFS_TRACE_BACKGROUND, (TSTR("Background gc" TENDSTR)));
+ T(YAFFS_TRACE_BACKGROUND, (TSTR("Background gc %u" TENDSTR),urgency));
yaffs_CheckGarbageCollection(dev, 1);
return erasedChunks > dev->nFreeChunks/2;
yaffs_CheckGarbageCollection(dev, 1);
return erasedChunks > dev->nFreeChunks/2;
/* OK, we've finished verifying the device, lets continue with initialisation */
/* More device initialisation */
/* OK, we've finished verifying the device, lets continue with initialisation */
/* More device initialisation */
- dev->garbageCollections = 0;
- dev->passiveGarbageCollections = 0;
+ dev->allGCs = 0;
+ dev->passiveGCs = 0;
+ dev->oldestDirtyGCs = 0;
+ dev->backgroundGCs = 0;
dev->gcBlockFinder = 0;
dev->bufferedBlock = -1;
dev->doingBufferedBlockRewrite = 0;
dev->gcBlockFinder = 0;
dev->bufferedBlock = -1;
dev->doingBufferedBlockRewrite = 0;
__u32 nBlockErasures;
__u32 nErasureFailures;
__u32 nGCCopies;
__u32 nBlockErasures;
__u32 nErasureFailures;
__u32 nGCCopies;
- __u32 garbageCollections;
- __u32 passiveGarbageCollections;
+ __u32 allGCs;
+ __u32 passiveGCs;
+ __u32 oldestDirtyGCs;
+ __u32 backgroundGCs;
__u32 nRetriedWrites;
__u32 nRetiredBlocks;
__u32 eccFixed;
__u32 nRetriedWrites;
__u32 nRetiredBlocks;
__u32 eccFixed;
void yaffs_UpdateDirtyDirectories(yaffs_Device *dev);
void yaffs_UpdateDirtyDirectories(yaffs_Device *dev);
-int yaffs_BackgroundGarbageCollect(yaffs_Device *dev);
+int yaffs_BackgroundGarbageCollect(yaffs_Device *dev, unsigned urgency);
/* Debug dump */
int yaffs_DumpObject(yaffs_Object *obj);
/* Debug dump */
int yaffs_DumpObject(yaffs_Object *obj);