summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-12-19 10:19:44 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-12-20 08:26:25 +0100
commitade135d45577263fe2c7b4d885e81c1798a1a79a (patch)
tree723884b48f9ad2acfd60f3e495438009ec22fb82
parent07c833f8f98c665e2f7d7e9adfa5f5503177dbff (diff)
downloadrtems-ade135d45577263fe2c7b4d885e81c1798a1a79a.tar.bz2
JFFS2: Add RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION
Add IO control to force a garbage collection. Update #2844.
-rw-r--r--cpukit/libfs/src/jffs2/include/rtems/jffs2.h8
-rw-r--r--cpukit/libfs/src/jffs2/src/fs-rtems.c3
-rw-r--r--testsuites/fstests/fsjffs2gc01/init.c57
3 files changed, 68 insertions, 0 deletions
diff --git a/cpukit/libfs/src/jffs2/include/rtems/jffs2.h b/cpukit/libfs/src/jffs2/include/rtems/jffs2.h
index 39c9420e62..11735cbb09 100644
--- a/cpukit/libfs/src/jffs2/include/rtems/jffs2.h
+++ b/cpukit/libfs/src/jffs2/include/rtems/jffs2.h
@@ -555,6 +555,14 @@ typedef struct {
*/
#define RTEMS_JFFS2_GET_INFO _IOR('F', 1, rtems_jffs2_info)
+/**
+ * @brief IO control to force a garbage collection in a JFFS2 filesystem
+ * instance.
+ *
+ * Use this operation with care since it may wear out your flash.
+ */
+#define RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION _IO('F', 3)
+
/** @} */
#ifdef __cplusplus
diff --git a/cpukit/libfs/src/jffs2/src/fs-rtems.c b/cpukit/libfs/src/jffs2/src/fs-rtems.c
index c8045dbed7..5f57a16bcb 100644
--- a/cpukit/libfs/src/jffs2/src/fs-rtems.c
+++ b/cpukit/libfs/src/jffs2/src/fs-rtems.c
@@ -568,6 +568,9 @@ static int rtems_jffs2_ioctl(
rtems_jffs2_get_info(&inode->i_sb->jffs2_sb, buffer);
eno = 0;
break;
+ case RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION:
+ eno = -jffs2_garbage_collect_pass(&inode->i_sb->jffs2_sb);
+ break;
default:
eno = EINVAL;
break;
diff --git a/testsuites/fstests/fsjffs2gc01/init.c b/testsuites/fstests/fsjffs2gc01/init.c
index df2e986412..8b5658c594 100644
--- a/testsuites/fstests/fsjffs2gc01/init.c
+++ b/testsuites/fstests/fsjffs2gc01/init.c
@@ -109,6 +109,38 @@ static const rtems_jffs2_info info_some_files_removed = {
.bad_blocks = 0
};
+static const rtems_jffs2_info info_after_first_gc = {
+ .flash_size = 131072,
+ .flash_blocks = 8,
+ .flash_block_size = 16384,
+ .used_size = 23540,
+ .dirty_size = 30988,
+ .wasted_size = 7368,
+ .free_size = 69176,
+ .bad_size = 0,
+ .clean_blocks = 0,
+ .dirty_blocks = 3,
+ .erasable_blocks = 0,
+ .free_blocks = 5,
+ .bad_blocks = 0
+};
+
+static const rtems_jffs2_info info_after_excessive_gc = {
+ .flash_size = 131072,
+ .flash_blocks = 8,
+ .flash_block_size = 16384,
+ .used_size = 7224,
+ .dirty_size = 0,
+ .wasted_size = 12,
+ .free_size = 123836,
+ .bad_size = 0,
+ .clean_blocks = 0,
+ .dirty_blocks = 0,
+ .erasable_blocks = 0,
+ .free_blocks = 8,
+ .bad_blocks = 0
+};
+
static char big[] = "big";
static const char * const more[] = {
@@ -225,6 +257,7 @@ void test(void)
{
int fd;
int rv;
+ int counter;
rtems_jffs2_info info;
init_keg();
@@ -246,6 +279,30 @@ void test(void)
remove_some_files();
ASSERT_INFO(&info, &info_some_files_removed);
+ rv = ioctl(fd, RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION);
+ rtems_test_assert(rv == 0);
+ ASSERT_INFO(&info, &info_after_first_gc);
+
+ counter = 0;
+
+ while (true) {
+ errno = ENXIO;
+ rv = ioctl(fd, RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION);
+ if (rv == -1) {
+ rtems_test_assert(errno == EIO);
+ break;
+ }
+
+ ++counter;
+ rtems_test_assert(rv == 0);
+ }
+
+ rtems_test_assert(counter == 19);
+
+ rv = ioctl(fd, RTEMS_JFFS2_GET_INFO, &info);
+ rtems_test_assert(rv == 0);
+ ASSERT_INFO(&info, &info_after_excessive_gc);
+
rv = close(fd);
rtems_test_assert(rv == 0);
}