- 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_gross_lock(dev);
- do_checkpoint = ((request_checkpoint && !gc_urgent) ||
- oneshot_checkpoint) &&
- !dev->is_checkpointed;
-
- if (sb->s_dirt || do_checkpoint) {
- yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
- sb->s_dirt = 0;
- if(oneshot_checkpoint)
- yaffs_auto_checkpoint &= ~4;
- }
- yaffs_gross_unlock(dev);
-
- return 0;
-}
-
-/*
- * yaffs background thread functions .
- * yaffs_bg_thread_fn() the thread function
- * yaffs_bg_start() launches the background thread.
- * yaffs_bg_stop() 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_bg_thread_fn(void *data)
-{
- struct yaffs_dev *dev = (struct yaffs_dev *)data;
- struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
- unsigned long now = jiffies;
- unsigned long next_dir_update = now;
- unsigned long next_gc = now;
- unsigned long expires;
- unsigned int urgency;
-
- int gc_result;
- struct timer_list timer;
-
- T(YAFFS_TRACE_BACKGROUND,
- (TSTR("yaffs_background starting for dev %p\n"),
- (void *)dev));
-
-#ifdef YAFFS_COMPILE_FREEZER
- set_freezable();
-#endif
- while(context->bg_running){
- T(YAFFS_TRACE_BACKGROUND,
- (TSTR("yaffs_background\n")));
-
- if(kthread_should_stop())
- break;
-
-#ifdef YAFFS_COMPILE_FREEZER
- if(try_to_freeze())
- continue;
-#endif
- yaffs_gross_lock(dev);
-
- now = jiffies;
-
- if(time_after(now, next_dir_update) && yaffs_bg_enable){
- yaffs_update_dirty_dirs(dev);
- next_dir_update = now + HZ;
- }
-
- if(time_after(now,next_gc) && yaffs_bg_enable){
- if(!dev->is_checkpointed){
- urgency = yaffs_bg_gc_urgency(dev);
- gc_result = yaffs_bg_gc(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_gross_unlock(dev);
-#if 1
- expires = next_dir_update;
- if (time_before(next_gc,expires))
- expires = next_gc;
- if(time_before(expires,now))
- expires = now + HZ;
-
- Y_INIT_TIMER(&timer);
- timer.expires = expires+1;
- timer.data = (unsigned long) current;
- timer.function = yaffs_background_waker;
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_timer(&timer);
- schedule();
- del_timer_sync(&timer);
-#else
- msleep(10);
-#endif
- }
-
- return 0;
-}
-
-static int yaffs_bg_start(struct yaffs_dev *dev)
-{
- int retval = 0;
- struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
-
- if(dev->read_only)
- return -1;
-
- context->bg_running = 1;
-
- context->bg_thread = kthread_run(yaffs_bg_thread_fn,
- (void *)dev,"yaffs-bg-%d",context->mount_id);
-
- if(IS_ERR(context->bg_thread)){
- retval = PTR_ERR(context->bg_thread);
- context->bg_thread = NULL;
- context->bg_running = 0;
- }
- return retval;
-}
-
-static void yaffs_bg_stop(struct yaffs_dev *dev)
-{
- struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev);
-
- ctxt->bg_running = 0;