From: Charles Manning Date: Wed, 7 May 2014 01:07:25 +0000 (+1200) Subject: yaffs direct: Expose background garbage collection X-Git-Tag: aleph1-release~41 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=de117c122a4328102305eb6dbe57ad22c1b1eba8 yaffs direct: Expose background garbage collection Expose background garbage collection and add a demo pthread implementation of background gc. Signed-off-by: Charles Manning --- diff --git a/direct/test-framework/tests/Makefile b/direct/test-framework/tests/Makefile index cbfe151..2fc97f0 100644 --- a/direct/test-framework/tests/Makefile +++ b/direct/test-framework/tests/Makefile @@ -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 $@ $< diff --git a/direct/test-framework/yaffs_osglue.c b/direct/test-framework/yaffs_osglue.c index 9d83274..e31ad22 100644 --- a/direct/test-framework/yaffs_osglue.c +++ b/direct/test-framework/yaffs_osglue.c @@ -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 #include +#include /* * 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 -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", diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index a01155f..9db29b9 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -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; diff --git a/direct/yaffsfs.h b/direct/yaffsfs.h index 3a73ffb..6ae5bc5 100644 --- a/direct/yaffsfs.h +++ b/direct/yaffsfs.h @@ -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,