X-Git-Url: https://yaffs.net/gitweb/?a=blobdiff_plain;f=yaffs_fs.c;h=63d31645cfa89e55cb1c3a3fcd622d251356b461;hb=8577cce7f27885b7b57fb1e60880d7d2765e0e6a;hp=8b11f4034c4896c54d6099d8256027c77b521f86;hpb=b4a902328423692f296c9118bf6bfaa057ccc72c;p=yaffs2.git diff --git a/yaffs_fs.c b/yaffs_fs.c index 8b11f40..63d3164 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -32,10 +32,15 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.96 2010-02-25 22:41:46 charles Exp $"; + "$Id: yaffs_fs.c,v 1.98 2010-03-10 01:22:19 charles Exp $"; extern const char *yaffs_guts_c_version; #include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)) +#define YAFFS_COMPILE_BACKGROUND +#endif + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) #include #endif @@ -52,6 +57,12 @@ extern const char *yaffs_guts_c_version; #include #include +#ifdef YAFFS_COMPILE_BACKGROUND +#include +#include +#endif + + #include "asm/div64.h" @@ -1779,7 +1790,7 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf) -static void yaffs_flush_sb_inodes(struct super_block *sb) +static void yaffs_FlushInodes(struct super_block *sb) { struct inode *iptr; yaffs_Object *obj; @@ -1793,28 +1804,120 @@ static void yaffs_flush_sb_inodes(struct super_block *sb) } } -static int yaffs_do_sync_fs(struct super_block *sb) + +static void yaffs_FlushSuperBlock(struct super_block *sb, int do_checkpoint) +{ + yaffs_Device *dev = yaffs_SuperToDevice(sb); + if(!dev) + return; + + yaffs_FlushInodes(sb); + yaffs_UpdateDirtyDirectories(dev); + yaffs_FlushEntireDeviceCache(dev); + if(do_checkpoint) + yaffs_CheckpointSave(dev); +} + +static int yaffs_do_sync_fs(struct super_block *sb, int do_checkpoint) { yaffs_Device *dev = yaffs_SuperToDevice(sb); - T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ("yaffs_do_sync_fs\n")); + T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, + ("yaffs_do_sync_fs: %s %s\n", + sb->s_dirt ? "dirty" : "clean", + do_checkpoint ? "with checkpoint" : "no checkpoint")); if (sb->s_dirt) { yaffs_GrossLock(dev); + yaffs_FlushSuperBlock(sb,do_checkpoint); + yaffs_GrossUnlock(dev); - if (dev) { - yaffs_FlushEntireDeviceCache(dev); - yaffs_flush_sb_inodes(sb); - yaffs_CheckpointSave(dev); - } + sb->s_dirt = 0; + } + return 0; +} +/* + * yaffs background thread functions . + * yaffs_BackgroundThread() the thread function + * yaffs_BackgroundStart() launches the background thread. + * yaffs_BackgroundStop() cleans up the background thread. + * + * NB: + * The thread should only run after the yaffs is initialised + * The thread should be stopped before yaffs is unmounted. + * The thread should not do any writing while the fs is in read only. + */ + +#ifdef YAFFS_COMPILE_BACKGROUND +static int yaffs_BackgroundThread(void *data) +{ + yaffs_Device *dev = (yaffs_Device *)data; + struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev); + + T(YAFFS_TRACE_BACKGROUND, + ("yaffs_background starting for dev %p\n", + (void *)dev)); + + while(context->bgRunning){ + T(YAFFS_TRACE_BACKGROUND, + ("yaffs_background\n")); + + if(kthread_should_stop()) + break; + yaffs_GrossLock(dev); + yaffs_UpdateDirtyDirectories(dev); yaffs_GrossUnlock(dev); + msleep(500); + } + return 0; +} - sb->s_dirt = 0; +static int yaffs_BackgroundStart(yaffs_Device *dev) +{ + int retval = 0; + + struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev); + + context->bgRunning = 1; + + context->bgThread = kthread_run(yaffs_BackgroundThread,(void *)dev,"yaffs_%x",(unsigned)dev); + + if(IS_ERR(context->bgThread)){ + retval = PTR_ERR(context->bgThread); + context->bgThread = NULL; + context->bgRunning = 0; } + return retval; +} + +static void yaffs_BackgroundStop(yaffs_Device *dev) +{ + struct yaffs_LinuxContext *ctxt = yaffs_DeviceToContext(dev); + + ctxt->bgRunning = 0; + + if( ctxt->bgThread){ + kthread_stop(ctxt->bgThread); + ctxt->bgThread = NULL; + } +} +#else +static int yaffs_BackgroundThread(void *data) +{ + return 0; +} + +static int yaffs_BackgroundStart(yaffs_Device *dev) +{ return 0; } +static void yaffs_BackgroundStop(yaffs_Device *dev) +{ +} +#endif + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) static void yaffs_write_super(struct super_block *sb) @@ -1824,8 +1927,8 @@ static int yaffs_write_super(struct super_block *sb) { T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ("yaffs_write_super\n")); - if (yaffs_auto_checkpoint >= 2) - yaffs_do_sync_fs(sb); + yaffs_do_sync_fs(sb, yaffs_auto_checkpoint >= 2); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) return 0; #endif @@ -1840,8 +1943,7 @@ static int yaffs_sync_fs(struct super_block *sb) { T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ("yaffs_sync_fs\n")); - if (yaffs_auto_checkpoint >= 1) - yaffs_do_sync_fs(sb); + yaffs_do_sync_fs(sb,yaffs_auto_checkpoint >= 1); return 0; } @@ -1921,9 +2023,7 @@ static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) yaffs_GrossLock(dev); - yaffs_FlushEntireDeviceCache(dev); - - yaffs_CheckpointSave(dev); + yaffs_FlushSuperBlock(sb,1); if (mtd->sync) mtd->sync(mtd); @@ -1946,13 +2046,13 @@ static void yaffs_put_super(struct super_block *sb) yaffs_GrossLock(dev); - yaffs_FlushEntireDeviceCache(dev); - - yaffs_CheckpointSave(dev); + yaffs_FlushSuperBlock(sb,1); if (yaffs_DeviceToContext(dev)->putSuperFunc) yaffs_DeviceToContext(dev)->putSuperFunc(sb); + yaffs_BackgroundStop(dev); + yaffs_Deinitialise(dev); yaffs_GrossUnlock(dev); @@ -2295,6 +2395,12 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, #ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC param->noTagsECC = 1; #endif + +#ifdef CONFIG_YAFFS_DISABLE_BACKGROUND +#else + param->deferDirectoryUpdate = 1; +#endif + if(options.tags_ecc_overridden) param->noTagsECC = !options.tags_ecc_on; @@ -2385,6 +2491,13 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, T(YAFFS_TRACE_OS, ("yaffs_read_super: guts initialised %s\n", (err == YAFFS_OK) ? "OK" : "FAILED")); + + if(err == YAFFS_OK) + yaffs_BackgroundStart(dev); + + if(!context->bgThread) + param->deferDirectoryUpdate = 0; + /* Release lock before yaffs_get_inode() */ yaffs_GrossUnlock(dev); @@ -2653,6 +2766,8 @@ static struct { {"tracing", YAFFS_TRACE_TRACING}, {"sync", YAFFS_TRACE_SYNC}, + {"background", YAFFS_TRACE_BACKGROUND}, + {"verify", YAFFS_TRACE_VERIFY}, {"verify_nand", YAFFS_TRACE_VERIFY_NAND}, {"verify_full", YAFFS_TRACE_VERIFY_FULL},