- yaffs_gross_unlock(dev);
- return 0;
-}
-
-static void yaffs_flush_inodes(struct super_block *sb)
-{
- struct inode *iptr;
- struct yaffs_obj *obj;
-
- list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
- obj = yaffs_inode_to_obj(iptr);
- if (obj) {
- yaffs_trace(YAFFS_TRACE_OS,
- "flushing obj %d",
- obj->obj_id);
- yaffs_flush_file(obj, 1, 0);
- }
- }
-}
-
-static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
-{
- struct yaffs_dev *dev = yaffs_super_to_dev(sb);
- if (!dev)
- return;
-
- yaffs_flush_inodes(sb);
- yaffs_update_dirty_dirs(dev);
- yaffs_flush_whole_cache(dev);
- if (do_checkpoint)
- yaffs_checkpoint_save(dev);
-}
-
-static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
-{
- unsigned erased_chunks =
- dev->n_erased_blocks * dev->param.chunks_per_block;
- struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
- unsigned scattered = 0; /* Free chunks not in an erased block */
-
- if (erased_chunks < dev->n_free_chunks)
- scattered = (dev->n_free_chunks - erased_chunks);
-
- if (!context->bg_running)
- return 0;
- else if (scattered < (dev->param.chunks_per_block * 2))
- return 0;
- else if (erased_chunks > dev->n_free_chunks / 2)
- return 0;
- else if (erased_chunks > dev->n_free_chunks / 4)
- return 1;
- else
- return 2;
-}
-
-static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
-{
-
- struct yaffs_dev *dev = yaffs_super_to_dev(sb);
- unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
- unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
- int do_checkpoint;
-
- yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
- "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
- 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;
-
- yaffs_trace(YAFFS_TRACE_BACKGROUND,
- "yaffs_background starting for dev %p", (void *)dev);
-
-#ifdef YAFFS_COMPILE_FREEZER
- set_freezable();
-#endif
- while (context->bg_running) {
- yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background");
-
- 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
- }
-