yaffs direct: Expose background garbage collection
authorCharles Manning <cdhmanning@gmail.com>
Wed, 7 May 2014 01:07:25 +0000 (13:07 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Wed, 7 May 2014 01:07:25 +0000 (13:07 +1200)
Expose background garbage collection and add a demo
pthread implementation of background gc.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
direct/test-framework/tests/Makefile
direct/test-framework/yaffs_osglue.c
direct/yaffsfs.c
direct/yaffsfs.h

index cbfe151..2fc97f0 100644 (file)
@@ -29,9 +29,10 @@ ALL_UNSORTED_OBJS += $(YAFFS_TEST_OBJS) $(FUZZER_OBJS)
 
 include ../FrameworkRules.mk
 
+C_FLAGS += -DCONFIG_YAFFS_USE_PTHREADS
 
 yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
-       gcc $(CFLLAG) -o $@ $(YAFFS_TEST_OBJS)
+       gcc $(CFLLAG) -o $@ $(YAFFS_TEST_OBJS) -lpthread
 
 fuzzer: $(FUZZER_OBJS)
        gcc $(CFLAGS) -o $@ $<
index 9d83274..e31ad22 100644 (file)
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-/* 
+/*
  * Example OS glue functions for running on a Linux/POSIX system.
  */
 
@@ -22,6 +22,7 @@
 #include <assert.h>
 
 #include <errno.h>
+#include <unistd.h>
 
 /*
  * yaffsfs_SetError() and yaffsfs_GetError()
@@ -62,12 +63,16 @@ int yaffsfs_CheckMemRegion(const void *addr, size_t size, int write_request)
  * yaffsfs_Unlock()
  * A single mechanism to lock and unlock yaffs. Hook up to a mutex or whatever.
  * Here are two examples, one using POSIX pthreads, the other doing nothing.
+ *
+ * If we use pthreads then we also start a background gc thread.
  */
 
-#ifdef CONFIG_YAFFS_USE_PTHREADS
+#if 1
+
 #include <pthread.h>
-static pthread_mutex_t mutex1;
 
+static pthread_mutex_t mutex1;
+static pthread_t bc_gc_thread;
 
 void yaffsfs_Lock(void)
 {
@@ -79,9 +84,47 @@ void yaffsfs_Unlock(void)
        pthread_mutex_unlock( &mutex1 );
 }
 
+static void *bg_gc_func(void *dummy)
+{
+       struct yaffs_dev *dev;
+       int urgent = 0;
+       int result;
+       int next_urgent;
+
+       /* Sleep for a bit to allow start up */
+       sleep(2);
+
+
+       while (1) {
+               /* Iterate through devices, do bg gc updating ungency */
+               yaffs_dev_rewind();
+               next_urgent = 0;
+
+               while ((dev = yaffs_next_dev()) != NULL) {
+                       result = yaffs_do_background_gc_reldev(dev, urgent);
+                       if (result > 0)
+                               next_urgent = 1;
+               }
+
+               urgent = next_urgent;
+
+               if (next_urgent)
+                       sleep(1);
+               else
+                       sleep(5);
+       }
+
+       /* Don't ever return. */
+       return NULL;
+}
+
 void yaffsfs_LockInit(void)
 {
-       pthread_mutex_init( &mutex1, NULL);
+       /* Initialise lock */
+       pthread_mutex_init(&mutex1, NULL);
+
+       /* Sneak in starting a background gc thread too */
+       pthread_create(&bc_gc_thread, NULL, bg_gc_func, NULL);
 }
 
 #else
@@ -101,10 +144,10 @@ void yaffsfs_LockInit(void)
 
 /*
  * yaffsfs_CurrentTime() retrns a 32-bit timestamp.
- * 
+ *
  * Can return 0 if your system does not care about time.
  */
+
 u32 yaffsfs_CurrentTime(void)
 {
        return time(NULL);
@@ -117,7 +160,7 @@ u32 yaffsfs_CurrentTime(void)
  *
  * Functions to allocate and free memory.
  */
+
 #ifdef CONFIG_YAFFS_TEST_MALLOC
 
 static int yaffs_kill_alloc = 0;
@@ -161,7 +204,7 @@ void yaffsfs_OSInitialisation(void)
  * yaffs_bug_fn()
  * Function to report a bug.
  */
+
 void yaffs_bug_fn(const char *file_name, int line_no)
 {
        printf("yaffs bug detected %s:%d\n",
index a01155f..9db29b9 100644 (file)
@@ -2888,6 +2888,57 @@ int yaffs_sync(const YCHAR *path)
        return yaffs_sync_common(NULL, path);
 }
 
+
+static int yaffsfs_bg_gc_common(struct yaffs_dev *dev,
+                               const YCHAR *path,
+                               int urgency)
+{
+       int retVal = -1;
+       YCHAR *dummy;
+
+       if (!dev) {
+               if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+                       yaffsfs_SetError(-EFAULT);
+                       return -1;
+               }
+
+               if (yaffsfs_CheckPath(path) < 0) {
+                       yaffsfs_SetError(-ENAMETOOLONG);
+                       return -1;
+               }
+       }
+
+       yaffsfs_Lock();
+       if (!dev)
+               dev = yaffsfs_FindDevice(path, &dummy);
+
+       if (dev) {
+               if (!dev->is_mounted)
+                       yaffsfs_SetError(-EINVAL);
+               else
+                       retVal = yaffs_bg_gc(dev, urgency);
+       } else
+               yaffsfs_SetError(-ENODEV);
+
+       yaffsfs_Unlock();
+       return retVal;
+}
+
+/* Background gc functions.
+ * These return 0 when bg done or greater than 0 when gc has been
+ * done and there is still a lot of garbage to be cleaned up.
+ */
+
+int yaffs_do_background_gc(const YCHAR *path, int urgency)
+{
+       return yaffsfs_bg_gc_common(NULL, path, urgency);
+}
+
+int yaffs_do_background_gc_reldev(struct yaffs_dev *dev, int urgency)
+{
+       return yaffsfs_bg_gc_common(dev, NULL, urgency);
+}
+
 static int yaffsfs_IsDevBusy(struct yaffs_dev *dev)
 {
        int i;
index 3a73ffb..6ae5bc5 100644 (file)
@@ -260,7 +260,11 @@ int yaffs_mknod_reldev(struct yaffs_dev *dev, const YCHAR *pathname,
 struct yaffs_dirent *yaffs_readdir_fd(int fd);
 void yaffs_rewinddir_fd(int fd);
 
+/* Non-standard functions to pump garbage collection. */
+int yaffs_do_background_gc(const YCHAR *path, int urgency);
+int yaffs_do_background_gc_reldev(struct yaffs_dev *dev, int urgency);
 
+/* Non-standard functions to get usage info */
 int yaffs_inodecount(const YCHAR *path);
 
 int yaffs_n_handles(const YCHAR *path);
@@ -270,7 +274,6 @@ int yaffs_dump_dev_reldir(struct yaffs_obj *reldir, const YCHAR *path);
 int yaffs_n_handles_reldev(struct yaffs_dev *dev, const YCHAR *path);
 int yaffs_dump_dev_reldev(struct yaffs_dev *dev, const YCHAR *path);
 
-
 #ifdef CONFIG_YAFFS_WINCE
 int yaffs_set_wince_times(int fd,
                        const unsigned *wctime,