+ unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
+ unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
+ int do_checkpoint;
+
+ T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
+ (TSTR("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" : "" ));
+
+ 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);
+ sb->s_dirt = 0;
+ if(oneshot_checkpoint)
+ yaffs_auto_checkpoint &= ~4;
+ }
+ yaffs_GrossUnlock(dev);
+
+ 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
+
+void yaffs_background_waker(unsigned long data)
+{
+ wake_up_process((struct task_struct *)data);
+}
+
+static int yaffs_BackgroundThread(void *data)
+{
+ yaffs_Device *dev = (yaffs_Device *)data;
+ struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev);
+ unsigned long now = jiffies;
+ unsigned long next_dir_update = now;
+ unsigned long next_gc = now;
+ unsigned long expires;
+ unsigned int urgency;
+
+ int gcResult;
+ struct timer_list timer;
+
+ T(YAFFS_TRACE_BACKGROUND,
+ (TSTR("yaffs_background starting for dev %p\n"),
+ (void *)dev));
+
+ set_freezable();
+
+ while(context->bgRunning){
+ T(YAFFS_TRACE_BACKGROUND,
+ (TSTR("yaffs_background\n")));
+
+ if(kthread_should_stop())
+ break;
+
+ if(try_to_freeze())
+ continue;