- return 0;
-}
-
-
-
-static void yaffs_flush_inodes(struct super_block *sb)
-{
- struct inode *iptr;
- yaffs_obj_t *obj;
-
- list_for_each_entry(iptr,&sb->s_inodes, i_sb_list){
- obj = yaffs_inode_to_obj(iptr);
- if(obj){
- T(YAFFS_TRACE_OS, (TSTR("flushing obj %d\n"),
- obj->obj_id));
- yaffs_flush_file(obj,1,0);
- }
- }
-}
-
-
-static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
-{
- yaffs_dev_t *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(yaffs_dev_t *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)
-{
-
- yaffs_dev_t *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;
-
- 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)
-{
- yaffs_dev_t *dev = (yaffs_dev_t *)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(yaffs_dev_t *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;