This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Pooled memory allocation for JFFS2


Hi,

I reworked my patch to make it easier to maintain, by
moving all the compression stuff to a separate file
named compr-ecos.c. This now allows to get rid of
zlib compression altogether in eCos without affecting
jffs2 mainline code, except for one place in write.c
where it was necessary to avoid allocation of a
compression buffer.

This is a full diff against current eCos CVS:


diff -x CVS -Nru packages-orig/fs/jffs2/current/ChangeLog packages/fs/jffs2/current/ChangeLog
--- packages-orig/fs/jffs2/current/ChangeLog	2003-10-16 14:25:18.000000000 +0200
+++ packages/fs/jffs2/current/ChangeLog	2003-11-18 11:55:46.000000000 +0100
@@ -1,3 +1,21 @@
+2003-11-18  Thomas Koeller  <thomas.koeller@baslerweb.com>
+
+	* compr-ecos.c: Created. Separate eCos compression from
+	Linux entirely.
+
+2003-11-14  Thomas Koeller  <thomas.koeller@baslerweb.com>
+
+	* cdl/jffs2.cdl:
+	* src/malloc-ecos.c:
+	* src/fs-ecos.c: Allocate jffs2_raw_node_ref structs
+	from pool.
+
+2003-11-12  Thomas Koeller  <thomas.koeller@baslerweb.com>
+
+	* cdl/jffs2.cdl:
+	* src/os-ecos.h: Added CYGPKG_FS_JFFS2_COMPRESS to
+	disable compression.
+
 2003-10-14  Thomas Koeller  <thomas.koeller@baslerweb.com>
 
 	* src/os-ecos.h: Made definition of CONFIG_JFFS2_FS_DEBUG
diff -x CVS -Nru packages-orig/fs/jffs2/current/cdl/jffs2.cdl packages/fs/jffs2/current/cdl/jffs2.cdl
--- packages-orig/fs/jffs2/current/cdl/jffs2.cdl	2003-10-16 14:25:18.000000000 +0200
+++ packages/fs/jffs2/current/cdl/jffs2.cdl	2003-11-18 11:50:01.000000000 +0100
@@ -45,6 +45,7 @@
 # Author(s):      David Woodhouse, Dominic Ostrowski
 # Original data:  ported from JFFS2 by David Woodhouse
 # Contributors:   dominic.ostrowski@3glab.com
+#                 tkoeller <thomas.koeller@baslerweb.com>
 # Date:           2000-08-28
 #
 #####DESCRIPTIONEND####
@@ -58,7 +59,6 @@
 
     requires       CYGPKG_IO_FILEIO
     requires       CYGPKG_IO_FLASH
-    requires       CYGPKG_COMPRESS_ZLIB
     requires       CYGINT_ISO_MALLOC
 
     requires       CYGPKG_ISOINFRA
@@ -73,7 +73,37 @@
     implements     CYGINT_IO_FILEIO_FS      
 
     compile        -library=libextras.a fs-ecos.c
-    compile        build.c scan.c malloc-ecos.c nodelist.c nodemgmt.c readinode.c erase.c dir-ecos.c write.c gc.c read.c compr.c compr_zlib.c compr_rtime.c compr_rubin.c file-ecos.c
+    compile        build.c scan.c malloc-ecos.c nodelist.c nodemgmt.c readinode.c erase.c dir-ecos.c write.c gc.c read.c compr-ecos.c file-ecos.c
+
+    cdl_option CYGOPT_FS_JFFS2_COMPRESS {
+        display         "Compress data"
+        flavor          bool
+        default_value   1
+        requires        CYGPKG_COMPRESS_ZLIB
+        compile         compr_zlib.c
+        description     "
+            Use the ZLIB package and store data in compressed form.
+            Compression and decompression are entirely handled by the file
+            system and are fully transparent to applications. However,
+            selecting this option increases the amount of RAM required and
+            slows down read and write operations considerably if you have a
+            slow CPU."
+    }
+    
+    cdl_option CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE {
+        display         "Memory pool size"
+        flavor          data
+        default_value   0
+        description     "
+            In order to manage data stored in flash, the file system
+            needs to use data structures (jffs2_raw_node_ref) allocated
+            in RAM. You can specify here the maximum number of such
+            structures you expect to be used, which will then be allocated
+            statically. If this option is set to 0, the structures will
+            be allocated dynamically via malloc(), which may incur some
+            memory overhead depending on the particular malloc()
+            implementation used."
+    }
 
     cdl_option CYGPKG_FS_JFFS2_CFLAGS_ADD {
 	display "Additional compiler flags"
diff -x CVS -Nru packages-orig/fs/jffs2/current/src/compr-ecos.c packages/fs/jffs2/current/src/compr-ecos.c
--- packages-orig/fs/jffs2/current/src/compr-ecos.c	1970-01-01 01:00:00.000000000 +0100
+++ packages/fs/jffs2/current/src/compr-ecos.c	2003-11-18 12:16:15.000000000 +0100
@@ -0,0 +1,84 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2001, 2002 Red Hat, Inc.
+ *
+ * Created by Arjan van de Ven <arjanv@redhat.com>
+ * Adapted for eCos by Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ * $Id$
+ *
+ */
+
+#include <pkgconf/fs_jffs2.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/jffs2.h>
+
+#if defined(CYGOPT_FS_JFFS2_COMPRESS)
+int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen);
+void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen);
+#endif
+
+
+/* jffs2_compress:
+ * @data: Pointer to uncompressed data
+ * @cdata: Pointer to buffer for compressed data
+ * @datalen: On entry, holds the amount of data available for compression.
+ *	On exit, expected to hold the amount of data actually compressed.
+ * @cdatalen: On entry, holds the amount of space available for compressed
+ *	data. On exit, expected to hold the actual size of the compressed
+ *	data.
+ *
+ * Returns: Byte to be stored with data indicating compression type used.
+ * Zero is used to show that the data could not be compressed - the 
+ * compressed version was actually larger than the original.
+ *
+ * If the cdata buffer isn't large enough to hold all the uncompressed data,
+ * jffs2_compress should compress as much as will fit, and should set 
+ * *datalen accordingly to show the amount of data which were compressed.
+ */
+unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, 
+		    uint32_t *datalen, uint32_t *cdatalen)
+{
+	int ret;
+
+#if defined(CYGOPT_FS_JFFS2_COMPRESS)
+	ret = jffs2_zlib_compress(data_in, cpage_out, datalen, cdatalen);
+	if (!ret) {
+		return JFFS2_COMPR_ZLIB;
+	}
+#endif
+	return JFFS2_COMPR_NONE; /* No compression */
+
+}
+
+
+int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, 
+		     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
+{
+	switch (comprtype) {
+	case JFFS2_COMPR_NONE:
+		/* This should be special-cased elsewhere, but we might as well deal with it */
+		memcpy(data_out, cdata_in, datalen);
+		break;
+
+	case JFFS2_COMPR_ZERO:
+		memset(data_out, 0, datalen);
+		break;
+#if defined(CYGOPT_FS_JFFS2_COMPRESS)
+	case JFFS2_COMPR_ZLIB:
+		jffs2_zlib_decompress(cdata_in, data_out, cdatalen, datalen);
+		break;
+#endif
+
+	default:
+		printk(KERN_NOTICE "Unknown JFFS2 compression type 0x%02x\n", comprtype);
+		return -EIO;
+	}
+	return 0;
+}
diff -x CVS -Nru packages-orig/fs/jffs2/current/src/fs-ecos.c packages/fs/jffs2/current/src/fs-ecos.c
--- packages-orig/fs/jffs2/current/src/fs-ecos.c	2003-10-08 14:06:52.000000000 +0200
+++ packages/fs/jffs2/current/src/fs-ecos.c	2003-11-14 19:36:43.000000000 +0100
@@ -142,6 +142,7 @@
 
 static char read_write_buffer[PAGE_CACHE_SIZE];	//avoids malloc when user may be under memory pressure
 static char gc_buffer[PAGE_CACHE_SIZE];	//avoids malloc when user may be under memory pressure
+static unsigned char n_fs_mounted = 0;	// a counter to track the number of jffs2 instances mounted
 
 //==========================================================================
 // Directory operations
@@ -552,10 +553,14 @@
 			return ENOMEM;
 		}
 		memset(c->inocache_list, 0, sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);
+		if (n_fs_mounted++ == 0)
+			jffs2_create_slab_caches(); // No error check, cannot fail
 
 		err = jffs2_read_super(jffs2_sb);
 
 		if (err) {
+			if (--n_fs_mounted == 0)
+				jffs2_destroy_slab_caches();
 			free(jffs2_sb);
 			free(c->inocache_list);
 			return err;
@@ -614,9 +619,11 @@
 		// That's all folks.
 		D2(printf("jffs2_umount No current mounts\n"));
 	} else {
-          jffs2_sb->s_mount_count--;
-        }
+		jffs2_sb->s_mount_count--;
+	}
         
+	if (--n_fs_mounted == 0)
+		jffs2_destroy_slab_caches();
 	return ENOERR;
 }
 
diff -x CVS -Nru packages-orig/fs/jffs2/current/src/malloc-ecos.c packages/fs/jffs2/current/src/malloc-ecos.c
--- packages-orig/fs/jffs2/current/src/malloc-ecos.c	2003-02-05 01:00:40.000000000 +0100
+++ packages/fs/jffs2/current/src/malloc-ecos.c	2003-11-14 19:25:10.000000000 +0100
@@ -12,8 +12,13 @@
  */
 
 #include <linux/kernel.h>
+#include <cyg/hal/drv_api.h>
 #include "nodelist.h"
 
+#if !defined(CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE)
+# define CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE 0
+#endif
+
 struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
 {
 	return malloc(sizeof(struct jffs2_full_dirent) + namesize);
@@ -64,16 +69,6 @@
 	free(x);
 }
 
-struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
-{
-	return malloc(sizeof(struct jffs2_raw_node_ref));
-}
-
-void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
-{
-	free(x);
-}
-
 struct jffs2_node_frag *jffs2_alloc_node_frag(void)
 {
 	return malloc(sizeof(struct jffs2_node_frag));
@@ -97,3 +92,71 @@
 	free(x);
 }
 
+#if CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
+
+int jffs2_create_slab_caches(void)
+{
+	return 0;
+}
+
+void jffs2_destroy_slab_caches(void)
+{
+}
+
+struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
+{
+	return malloc(sizeof(struct jffs2_raw_node_ref));
+}
+
+void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
+{
+	free(x);
+}
+
+#else // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
+
+static struct jffs2_raw_node_ref
+	rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE] __attribute__ ((aligned (4))),
+	* first = NULL;
+static cyg_drv_mutex_t mutex;
+
+int jffs2_create_slab_caches(void)
+{
+	struct jffs2_raw_node_ref * p;
+	cyg_drv_mutex_init(&mutex);
+	for (
+		p = rnr_pool;
+		p < rnr_pool + CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1;
+		p++
+	)
+		p->next_phys = p + 1;
+	rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1].next_phys = NULL;
+	first = &rnr_pool[0];
+	return 0;
+}
+
+void jffs2_destroy_slab_caches(void)
+{
+}
+
+struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
+{
+	struct jffs2_raw_node_ref * p;
+	
+	cyg_drv_mutex_lock(&mutex);
+	p = first;
+	if (p != NULL)
+		first = p->next_phys;
+	cyg_drv_mutex_unlock(&mutex);
+	return p;
+}
+
+void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
+{
+	cyg_drv_mutex_lock(&mutex);
+	x->next_phys = first;
+	first = x;
+	cyg_drv_mutex_unlock(&mutex);
+}
+
+#endif // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
diff -x CVS -Nru packages-orig/fs/jffs2/current/src/os-ecos.h packages/fs/jffs2/current/src/os-ecos.h
--- packages-orig/fs/jffs2/current/src/os-ecos.h	2003-10-16 14:25:18.000000000 +0200
+++ packages/fs/jffs2/current/src/os-ecos.h	2003-11-14 19:25:10.000000000 +0100
@@ -14,6 +14,7 @@
 #ifndef __JFFS2_OS_ECOS_H__
 #define __JFFS2_OS_ECOS_H__
 
+#include <pkgconf/fs_jffs2.h>
 #include <cyg/io/io.h>
 #include <sys/types.h>
 #include <asm/atomic.h>
diff -x CVS -Nru packages-orig/fs/jffs2/current/src/write.c packages/fs/jffs2/current/src/write.c
--- packages-orig/fs/jffs2/current/src/write.c	2003-02-05 01:00:40.000000000 +0100
+++ packages/fs/jffs2/current/src/write.c	2003-11-18 11:20:07.000000000 +0100
@@ -300,6 +300,10 @@
 		datalen = writelen;
 		cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), writelen);
 
+#if defined(__ECOS) && !defined(CYGOPT_FS_JFFS2_COMPRESS)
+		comprbuf = buf;
+		datalen = cdatalen;
+#else
 		comprbuf = kmalloc(cdatalen, GFP_KERNEL);
 		if (comprbuf) {
 			comprtype = jffs2_compress(buf, comprbuf, &datalen, &cdatalen);
@@ -311,6 +315,7 @@
 			comprbuf = buf;
 			datalen = cdatalen;
 		}
+#endif
 		/* Now comprbuf points to the data to be written, be it compressed or not.
 		   comprtype holds the compression type, and comprtype == JFFS2_COMPR_NONE means
 		   that the comprbuf doesn't need to be kfree()d. 


-- 
--------------------------------------------------

Thomas Koeller, Software Development

Basler Vision Technologies
An der Strusbek 60-62
22926 Ahrensburg
Germany

Tel +49 (4102) 463-162
Fax +49 (4102) 463-239

mailto:thomas.koeller@baslerweb.com
http://www.baslerweb.com

==============================


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]