JFFS2: Add RTEMS support

This commit is contained in:
Sebastian Huber
2013-09-19 13:16:06 +02:00
parent 78b85286f0
commit 3c96bee3f9
24 changed files with 2032 additions and 2969 deletions
+3
View File
@@ -120,6 +120,9 @@ include_rtems_rfs_HEADERS += libfs/src/rfs/rtems-rfs-link.h
include_rtems_rfs_HEADERS += libfs/src/rfs/rtems-rfs-mutex.h
include_rtems_rfs_HEADERS += libfs/src/rfs/rtems-rfs-trace.h
# JFFS2
include_rtems_HEADERS += libfs/src/jffs2/include/rtems/jffs2.h
## libblock
include_rtems_HEADERS += libblock/include/rtems/bdbuf.h
include_rtems_HEADERS += libblock/include/rtems/blkdev.h
+1
View File
@@ -1437,6 +1437,7 @@ extern int rtems_mkdir(const char *path, mode_t mode);
#define RTEMS_FILESYSTEM_TYPE_NFS "nfs"
#define RTEMS_FILESYSTEM_TYPE_DOSFS "dosfs"
#define RTEMS_FILESYSTEM_TYPE_RFS "rfs"
#define RTEMS_FILESYSTEM_TYPE_JFFS2 "jffs2"
/** @} */
+29
View File
@@ -102,6 +102,35 @@ librfs_a_SOURCES = \
src/rfs/rtems-rfs-rtems-dir.c src/rfs/rtems-rfs-rtems-file.c \
src/rfs/rtems-rfs-trace.c
# JFFS2
noinst_LIBRARIES += libjffs2.a
libjffs2_a_SOURCES =
libjffs2_a_SOURCES += src/jffs2/src/build.c
libjffs2_a_SOURCES += src/jffs2/src/compat-crc32.c
libjffs2_a_SOURCES += src/jffs2/src/compat-rbtree.c
libjffs2_a_SOURCES += src/jffs2/src/compr.c
libjffs2_a_SOURCES += src/jffs2/src/compr_rtime.c
libjffs2_a_SOURCES += src/jffs2/src/compr_zlib.c
libjffs2_a_SOURCES += src/jffs2/src/debug.c
libjffs2_a_SOURCES += src/jffs2/src/dir-rtems.c
libjffs2_a_SOURCES += src/jffs2/src/erase.c
libjffs2_a_SOURCES += src/jffs2/src/flashio.c
libjffs2_a_SOURCES += src/jffs2/src/fs-rtems.c
libjffs2_a_SOURCES += src/jffs2/src/gc.c
libjffs2_a_SOURCES += src/jffs2/src/malloc-rtems.c
libjffs2_a_SOURCES += src/jffs2/src/nodelist.c
libjffs2_a_SOURCES += src/jffs2/src/nodemgmt.c
libjffs2_a_SOURCES += src/jffs2/src/read.c
libjffs2_a_SOURCES += src/jffs2/src/readinode.c
libjffs2_a_SOURCES += src/jffs2/src/scan.c
libjffs2_a_SOURCES += src/jffs2/src/write.c
libjffs2_a_CFLAGS =
libjffs2_a_CFLAGS += -Wno-pointer-sign
libjffs2_a_CPPFLAGS =
libjffs2_a_CPPFLAGS += $(AM_CPPFLAGS) -I$(srcdir)/src/jffs2/include
libjffs2_a_CPPFLAGS += -D__ECOS
libjffs2_a_CPPFLAGS += '-DKBUILD_MODNAME="JFFS2"'
# ---
include $(srcdir)/preinstall.am
include $(top_srcdir)/automake/subdirs.am
@@ -55,130 +55,11 @@
//
#include <stddef.h> // Definition of NULL from the compiler
#include <stdint.h>
// -------------------------------------------------------------------------
// Some useful macros. These are defined here by default.
typedef uint16_t cyg_uint16;
// __externC is used in mixed C/C++ headers to force C linkage on an external
// definition. It avoids having to put all sorts of ifdefs in.
#ifdef __cplusplus
# define __externC extern "C"
#else
# define __externC extern
#endif
// Also define externC for now - but it is deprecated
#define externC __externC
// Compiler version.
#ifdef __GNUC__
# if defined(__GNU_PATCHLEVEL__)
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
# else
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100)
# endif
#endif
// -------------------------------------------------------------------------
// The header <basetype.h> defines the base types used here. It is
// supplied either by the target architecture HAL, or by the host
// porting kit. They are all defined as macros, and only those that
// make choices other than the defaults given below need be defined.
#define CYG_LSBFIRST 1234
#define CYG_MSBFIRST 4321
#include <cyg/hal/basetype.h>
#if (CYG_BYTEORDER != CYG_LSBFIRST) && (CYG_BYTEORDER != CYG_MSBFIRST)
# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
#endif
#ifndef CYG_DOUBLE_BYTEORDER
#define CYG_DOUBLE_BYTEORDER CYG_BYTEORDER
#endif
#ifndef cyg_halint8
# define cyg_halint8 char
#endif
#ifndef cyg_halint16
# define cyg_halint16 short
#endif
#ifndef cyg_halint32
# define cyg_halint32 int
#endif
#ifndef cyg_halint64
# define cyg_halint64 long long
#endif
#ifndef cyg_halcount8
# define cyg_halcount8 int
#endif
#ifndef cyg_halcount16
# define cyg_halcount16 int
#endif
#ifndef cyg_halcount32
# define cyg_halcount32 int
#endif
#ifndef cyg_halcount64
# define cyg_halcount64 long long
#endif
#ifndef cyg_haladdress
# define cyg_haladdress cyg_uint32
#endif
#ifndef cyg_haladdrword
# define cyg_haladdrword cyg_uint32
#endif
#ifndef cyg_halbool
# define cyg_halbool int
#endif
#ifndef cyg_halatomic
# define cyg_halatomic cyg_halint8
#endif
// -------------------------------------------------------------------------
// Provide a default architecture alignment
// This may be overridden in basetype.h if necessary.
// These should be straightforward numbers to allow use in assembly.
#ifndef CYGARC_ALIGNMENT
# define CYGARC_ALIGNMENT 8
#endif
// And corresponding power of two alignment
#ifndef CYGARC_P2ALIGNMENT
# define CYGARC_P2ALIGNMENT 3
#endif
#if (CYGARC_ALIGNMENT) != (1 << CYGARC_P2ALIGNMENT)
# error "Inconsistent CYGARC_ALIGNMENT and CYGARC_P2ALIGNMENT values"
#endif
// -------------------------------------------------------------------------
// The obvious few that compilers may define for you.
// But in case they don't:
#ifndef NULL
# define NULL 0
#endif
#ifndef __cplusplus
typedef cyg_halbool bool;
# ifndef false
# define false 0
# endif
# ifndef true
# define true (!false)
# endif
#endif
typedef uint32_t cyg_uint32;
// -------------------------------------------------------------------------
// Allow creation of procedure-like macros that are a single statement,
@@ -195,365 +76,6 @@ typedef cyg_halbool bool;
__tmp1 = __tmp2; \
CYG_MACRO_END
//----------------------------------------------------------------------------
// The unused attribute stops the compiler warning about the variable
// not being used.
// The used attribute prevents the compiler from optimizing it away.
#define CYG_REFERENCE_OBJECT(__object__) \
CYG_MACRO_START \
static const void* __cygvar_discard_me__ \
__attribute__ ((unused, used)) = (const void*)&(__object__); \
CYG_MACRO_END
// -------------------------------------------------------------------------
// Define basic types for using integers in memory and structures;
// depends on compiler defaults and CPU type.
typedef unsigned cyg_halint8 cyg_uint8 ;
typedef signed cyg_halint8 cyg_int8 ;
typedef unsigned cyg_halint16 cyg_uint16 ;
typedef signed cyg_halint16 cyg_int16 ;
typedef unsigned cyg_halint32 cyg_uint32 ;
typedef signed cyg_halint32 cyg_int32 ;
typedef unsigned cyg_halint64 cyg_uint64 ;
typedef signed cyg_halint64 cyg_int64 ;
typedef cyg_halbool cyg_bool ;
// -------------------------------------------------------------------------
// Define types for using integers in registers for looping and the like;
// depends on CPU type, choose what it is most comfortable with, with at
// least the range required.
typedef unsigned cyg_halcount8 cyg_ucount8 ;
typedef signed cyg_halcount8 cyg_count8 ;
typedef unsigned cyg_halcount16 cyg_ucount16 ;
typedef signed cyg_halcount16 cyg_count16 ;
typedef unsigned cyg_halcount32 cyg_ucount32 ;
typedef signed cyg_halcount32 cyg_count32 ;
typedef unsigned cyg_halcount64 cyg_ucount64 ;
typedef signed cyg_halcount64 cyg_count64 ;
// -------------------------------------------------------------------------
// Define a type to be used for atomic accesses. This type is guaranteed
// to be read or written in a single uninterruptible operation. This type
// is at least a single byte.
typedef volatile unsigned cyg_halatomic cyg_atomic;
typedef volatile unsigned cyg_halatomic CYG_ATOMIC;
// -------------------------------------------------------------------------
// Define types for access plain, on-the-metal memory or devices.
typedef cyg_uint32 CYG_WORD;
typedef cyg_uint8 CYG_BYTE;
typedef cyg_uint16 CYG_WORD16;
typedef cyg_uint32 CYG_WORD32;
typedef cyg_uint64 CYG_WORD64;
typedef cyg_haladdress CYG_ADDRESS;
typedef cyg_haladdrword CYG_ADDRWORD;
// -------------------------------------------------------------------------
// Number of elements in a (statically allocated) array.
#define CYG_NELEM(a) (sizeof(a) / sizeof((a)[0]))
// -------------------------------------------------------------------------
// Constructor ordering macros. These are added as annotations to all
// static objects to order the constuctors appropriately.
#if defined(__cplusplus) && defined(__GNUC__) && \
!defined(CYGBLD_ATTRIB_INIT_PRI)
# define CYGBLD_ATTRIB_INIT_PRI( _pri_ ) __attribute__((init_priority(_pri_)))
#elif !defined(CYGBLD_ATTRIB_INIT_PRI)
// FIXME: should maybe just bomb out if this is attempted anywhere else?
// Not sure
# define CYGBLD_ATTRIB_INIT_PRI( _pri_ )
#endif
// The following will be removed eventually as it doesn't allow the use of
// e.g. pri+5 format
#define CYG_INIT_PRIORITY( _pri_ ) CYGBLD_ATTRIB_INIT_PRI( CYG_INIT_##_pri_ )
#define CYGBLD_ATTRIB_INIT_BEFORE( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_-100)
#define CYGBLD_ATTRIB_INIT_AFTER( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_+100)
#if defined(__GNUC__) && !defined(__cplusplus) && (__GNUC_VERSION__ >= 40300)
// Equivalents of the above for C functions, available from gcc 4.3 onwards.
# define CYGBLD_ATTRIB_C_INIT_PRI( _pri_) __attribute__((constructor (_pri_)))
# define CYGBLD_ATTRIB_C_INIT_BEFORE( _pri_ ) __attribute__((constructor (_pri_-100)))
# define CYGBLD_ATTRIB_C_INIT_AFTER( _pri_ ) __attribute__((constructor (_pri_+100)))
#endif
// Start with initializing everything inside the cpu and the main memory.
#define CYG_INIT_HAL 10000
#define CYG_INIT_SCHEDULER 11000
#define CYG_INIT_IDLE_THREAD 11100
#define CYG_INIT_INTERRUPTS 12000
#define CYG_INIT_CLOCK 14000
#define CYG_INIT_THREADS 16000
#define CYG_INIT_KERNEL 19000
#define CYG_INIT_MEMALLOC 20000
// Now move on to I/O subsystems and device drivers. These can make use of
// kernel and HAL functionality, and can dynamically allocate memory if
// absolutely needed. For now they can also assume that diag_printf()
// functionality is available, but that may change in future.
//
// Primary buses are ones very closely tied to the processor, e.g. PCI.
#define CYG_INIT_BUS_PRIMARY 30000
// Not yet: on some targets cyg_pci_init() has to be called very early
// on for HAL diagnostics to work.
// #define CYG_INIT_BUS_PCI CYG_INIT_BUS_PRIMARY
//
// Secondary buses may hang off primary buses, e.g. USB host.
#define CYG_INIT_BUS_SECONDARY 31000
// Tertiary buses are everything else.
#define CYG_INIT_BUS_TERTIARY 32000
#define CYG_INIT_BUS_I2C CYG_INIT_BUS_TERTIARY
#define CYG_INIT_BUS_SPI CYG_INIT_BUS_TERTIARY
//
// In future HAL diag initialization may happen at this point.
//
// Watchdogs and wallclocks often hang off a tertiary bus but
// have no dependencies
#define CYG_INIT_DEV_WATCHDOG 35000
#define CYG_INIT_DEV_WALLCLOCK 36000
// A primary block configuration can be initialized with no need
// for per-unit configuration information.
#define CYG_INIT_DEV_BLOCK_PRIMARY 37000
#define CYG_INIT_DEV_FLASH CYG_INIT_DEV_BLOCK_PRIMARY
// Per-unit configuration data extracted from primary storage.
// NOTE: for future use, not implemented yet.
#define CYG_INIT_CONFIG 38000
// Secondary block devices may use per-unit configuration data
// for e.g. interpreting partition layout. Few devices are expected
// to fall into this category. Note that these devices, as well as
// some char devices, may not actually be usable until interrupts
// are enabled.
#define CYG_INIT_DEV_BLOCK_SECONDARY 40000
// Char devices are everything else: serial, ethernet, CAN, ...
#define CYG_INIT_DEV_CHAR 41000
// For backwards compatibility. Subject to change in future so
// a CYG_INIT_DEV_ priority should be used instead.
#define CYG_INIT_DRIVERS 48000
// CYG_INIT_IO and CYG_INIT_IO_FS are poorly defined at present,
// and may get reorganized in future.
#define CYG_INIT_IO 49000
#define CYG_INIT_IO_FS 50000
// The I/O subsystems and device drivers have been initialized.
#define CYG_INIT_LIBC 56000
#define CYG_INIT_COMPAT 58000
#define CYG_INIT_APPLICATION 60000
#define CYG_INIT_PREDEFAULT 65534
#define CYG_INIT_DEFAULT 65535
// -------------------------------------------------------------------------
// Label name macros. Some toolsets generate labels with initial
// underscores and others don't. CYG_LABEL_NAME should be used on
// labels in C/C++ code that are defined in assembly code or linker
// scripts. CYG_LABEL_DEFN is for use in assembly code and linker
// scripts where we need to manufacture labels that can be used from
// C/C++.
// These are default implementations that should work for most targets.
// They may be overridden in basetype.h if necessary.
#ifndef CYG_LABEL_NAME
#define CYG_LABEL_NAME(_name_) _name_
#endif
#ifndef CYG_LABEL_DEFN
#define CYG_LABEL_DEFN(_label) _label
#endif
// -------------------------------------------------------------------------
// COMPILER-SPECIFIC STUFF
#ifdef __GNUC__
// Force a 'C' routine to be called like a 'C++' contructor
# if !defined(CYGBLD_ATTRIB_CONSTRUCTOR)
# define CYGBLD_ATTRIB_CONSTRUCTOR __attribute__((constructor))
# endif
// Define a compiler-specific rune for saying a function doesn't return
# if !defined(CYGBLD_ATTRIB_NORET)
# define CYGBLD_ATTRIB_NORET __attribute__((noreturn))
# endif
// How to define weak symbols - this is only relevant for ELF and a.out,
// but that won't be a problem for eCos
# if !defined(CYGBLD_ATTRIB_WEAK)
# define CYGBLD_ATTRIB_WEAK __attribute__ ((weak))
# endif
// How to define alias to symbols. Just pass in the symbol itself, not
// the string name of the symbol
# if !defined(CYGBLD_ATTRIB_ALIAS)
# define CYGBLD_ATTRIB_ALIAS(__symbol__) \
__attribute__ ((alias (#__symbol__)))
# endif
// This effectively does the reverse of the previous macro. It defines
// a name that the attributed variable or function will actually have
// in assembler.
# if !defined(CYGBLD_ATTRIB_ASM_ALIAS)
# define __Str(x) #x
# define __Xstr(x) __Str(x)
# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) \
__asm__ ( __Xstr( CYG_LABEL_DEFN( __symbol__ ) ) )
# endif
// Shows that a function returns the same value when given the same args, but
// note this can't be used if there are pointer args
# if !defined(CYGBLD_ATTRIB_CONST)
# define CYGBLD_ATTRIB_CONST __attribute__((const))
#endif
// Assign a defined variable to a specific section
# if !defined(CYGBLD_ATTRIB_SECTION)
# define CYGBLD_ATTRIB_SECTION(__sect__) __attribute__((section (__sect__)))
# endif
// Give a type or object explicit minimum alignment
# if !defined(CYGBLD_ATTRIB_ALIGN)
# define CYGBLD_ATTRIB_ALIGN(__align__) __attribute__((aligned(__align__)))
# endif
# if !defined(CYGBLD_ATTRIB_ALIGN_MAX)
# define CYGBLD_ATTRIB_ALIGN_MAX __attribute__((aligned))
# endif
# if !defined(CYGBLD_ATTRIB_ALIGNOFTYPE)
# define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) \
__attribute__((aligned(__alignof__( _type_ ))))
# endif
// Teach compiler how to check format of printf-like functions
# define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__) \
__attribute__((format (printf, __format__, __args__)))
// Teach compiler how to check format of scanf-like functions
# define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__) \
__attribute__((format (scanf, __format__, __args__)))
// Teach compiler how to check format of strftime-like functions
# define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__) \
__attribute__((format (strftime, __format__, __args__)))
// Tell compiler not to warn us about an unused variable -- generally
// because it will be used when sources are build under certain
// circumstances (e.g. with debugging or asserts enabled.
# define CYGBLD_ATTRIB_UNUSED __attribute__((unused))
// Tell the compiler not to throw away a variable or function. Only known
// available on 3.3.2 or above. Old version's didn't throw them away,
// but using the unused attribute should stop warnings.
# if !defined(CYGBLD_ATTRIB_USED)
# if __GNUC_VERSION__ >= 30302
# define CYGBLD_ATTRIB_USED __attribute__((used))
# else
# define CYGBLD_ATTRIB_USED __attribute__((unused))
# endif
# endif
// Enforce inlining of a C function. GCC does not inline any C
// function when not optimizing, unless you specify "always_inline" attribute.
// Other attributes suppress generation of standalone function.
# if !defined(CYGBLD_FORCE_INLINE)
# define CYGBLD_FORCE_INLINE __externC inline __attribute((gnu_inline)) __attribute((always_inline))
# endif
// Suppress function inlining
#define CYGBLD_ATTRIB_NO_INLINE __attribute__((noinline))
#else // non-GNU
# define CYGBLD_ATTRIB_UNUSED /* nothing */
# define CYGBLD_ATTRIB_CONSTRUCTOR
# define CYGBLD_ATTRIB_NORET
// This intentionally gives an error only if we actually try to
// use it. #error would give an error if we simply can't.
// FIXME: Had to disarm the bomb - the CYGBLD_ATTRIB_WEAK macro is now
// (indirectly) used in host tools.
# define CYGBLD_ATTRIB_WEAK /* !!!-- Attribute weak not defined --!!! */
# define CYGBLD_ATTRIB_ALIAS(__x__) !!!-- Attribute alias not defined --!!!
# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) !!!-- Asm alias not defined --!!!
# define CYGBLD_ATTRIB_CONST
# define CYGBLD_ATTRIB_ALIGN(__align__) !!!-- Alignment alias not defined --!!!
# define CYGBLD_ATTRIB_ALIGN_MAX !!!-- Alignment alias not defined --!!!
# define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) !!!-- Alignment alias not defined --!!!
# define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__)
# define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__)
# define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__)
#define CYGBLD_FORCE_INLINE
#define CYGBLD_ATTRIB_NO_INLINE
#endif
// How to define weak aliases. Currently this is simply a mixture of the
// above
# define CYGBLD_ATTRIB_WEAK_ALIAS(__symbol__) \
CYGBLD_ATTRIB_WEAK CYGBLD_ATTRIB_ALIAS(__symbol__)
#ifdef __cplusplus
# define __THROW throw()
#else
# define __THROW
#endif
// -------------------------------------------------------------------------
// Variable annotations
// These annotations may be added to various static variables in the
// HAL and kernel to indicate which component they belong to. These
// are used by some targets to optimize memory placement of these
// variables.
#ifndef CYGBLD_ANNOTATE_VARIABLE_HAL
#define CYGBLD_ANNOTATE_VARIABLE_HAL
#endif
#ifndef CYGBLD_ANNOTATE_VARIABLE_SCHED
#define CYGBLD_ANNOTATE_VARIABLE_SCHED
#endif
#ifndef CYGBLD_ANNOTATE_VARIABLE_CLOCK
#define CYGBLD_ANNOTATE_VARIABLE_CLOCK
#endif
#ifndef CYGBLD_ANNOTATE_VARIABLE_INTR
#define CYGBLD_ANNOTATE_VARIABLE_INTR
#endif
// -------------------------------------------------------------------------
// Various "flavours" of memory regions that can be described by the
// Memory Layout Tool (MLT).
#define CYGMEM_REGION_ATTR_R 0x01 // Region can be read
#define CYGMEM_REGION_ATTR_W 0x02 // Region can be written
// -------------------------------------------------------------------------
#endif // CYGONCE_INFRA_CYG_TYPE_H multiple inclusion protection
// EOF cyg_type.h
@@ -0,0 +1,455 @@
/*
* Copyright (c) 2013 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/
#ifndef RTEMS_JFFS2_H
#define RTEMS_JFFS2_H
#include <rtems/fs.h>
#include <sys/param.h>
#include <zlib.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct rtems_jffs2_flash_control rtems_jffs2_flash_control;
/**
* @defgroup JFFS2 Journalling Flash File System Version 2 (JFFS2) Support
*
* @ingroup FileSystemTypesAndMount
*
* @brief Mount options for the Journalling Flash File System, Version 2
* (JFFS2).
*
* The application must provide flash device geometry information and flash
* device operations in the flash control structure
* @ref rtems_jffs2_flash_control.
*
* The application can optionally provide a compressor control structure to
* enable data compression using the selected compression algorithm.
*
* The application must enable JFFS2 support with rtems_filesystem_register()
* or CONFIGURE_FILESYSTEM_JFFS2 via <rtems/confdefs.h>.
*
* An example mount with a simple memory based flash device simulation follows.
* The zlib is used for as the compressor.
*
* @code
* #include <string.h>
*
* #include <rtems/jffs2.h>
* #include <rtems/libio.h>
*
* #define BLOCK_SIZE (32UL * 1024UL)
*
* #define FLASH_SIZE (32UL * BLOCK_SIZE)
*
* typedef struct {
* rtems_jffs2_flash_control super;
* unsigned char area[FLASH_SIZE];
* } flash_control;
*
* static flash_control *get_flash_control(rtems_jffs2_flash_control *super)
* {
* return (flash_control *) super;
* }
*
* static int flash_read(
* rtems_jffs2_flash_control *super,
* uint32_t offset,
* unsigned char *buffer,
* size_t size_of_buffer
* )
* {
* flash_control *self = get_flash_control(super);
* unsigned char *chunk = &self->area[offset];
*
* memcpy(buffer, chunk, size_of_buffer);
*
* return 0;
* }
*
* static int flash_write(
* rtems_jffs2_flash_control *super,
* uint32_t offset,
* const unsigned char *buffer,
* size_t size_of_buffer
* )
* {
* flash_control *self = get_flash_control(super);
* unsigned char *chunk = &self->area[offset];
* size_t i;
*
* for (i = 0; i < size_of_buffer; ++i) {
* chunk[i] &= buffer[i];
* }
*
* return 0;
* }
*
* static int flash_erase(
* rtems_jffs2_flash_control *super,
* uint32_t offset
* )
* {
* flash_control *self = get_flash_control(super);
* unsigned char *chunk = &self->area[offset];
*
* memset(chunk, 0xff, BLOCK_SIZE);
*
* return 0;
* }
*
* static flash_control flash_instance = {
* .super = {
* .block_size = BLOCK_SIZE,
* .flash_size = FLASH_SIZE,
* .read = flash_read,
* .write = flash_write,
* .erase = flash_erase
* }
* };
*
* static rtems_jffs2_compressor_zlib_control compressor_instance = {
* .super = {
* .compress = rtems_jffs2_compressor_zlib_compress,
* .decompress = rtems_jffs2_compressor_zlib_decompress
* }
* };
*
* static const rtems_jffs2_mount_data mount_data = {
* .flash_control = &flash_instance.super,
* .compressor_control = &compressor_instance.super
* };
*
* static void erase_all(void)
* {
* memset(&flash_instance.area[0], 0xff, FLASH_SIZE);
* }
*
* void example_jffs2_mount(const char *mount_dir)
* {
* int rv;
*
* erase_all();
*
* rv = mount_and_make_target_path(
* NULL,
* mount_dir,
* RTEMS_FILESYSTEM_TYPE_JFFS2,
* RTEMS_FILESYSTEM_READ_WRITE,
* &mount_data
* );
* assert(rv == 0);
* }
* @endcode
*
* @{
*/
/**
* @brief Read from flash operation.
*
* @param[in, out] self The flash control.
* @param[in] offset The offset to read from the flash begin in bytes.
* @param[out] buffer The buffer receiving the data.
* @param[in] size_of_buffer The size of the buffer in bytes.
*
* @retval 0 Successful operation.
* @retval -EIO An error occurred. Please note that the value is negative.
* @retval other All other values are reserved and must not be used.
*/
typedef int (*rtems_jffs2_flash_read)(
rtems_jffs2_flash_control *self,
uint32_t offset,
unsigned char *buffer,
size_t size_of_buffer
);
/**
* @brief Write to flash operation.
*
* @param[in, out] self The flash control.
* @param[in] offset The offset to write from the flash begin in bytes.
* @param[in] buffer The buffer containing the data to write.
* @param[in] size_of_buffer The size of the buffer in bytes.
*
* @retval 0 Successful operation.
* @retval -EIO An error occurred. Please note that the value is negative.
* @retval other All other values are reserved and must not be used.
*/
typedef int (*rtems_jffs2_flash_write)(
rtems_jffs2_flash_control *self,
uint32_t offset,
const unsigned char *buffer,
size_t size_of_buffer
);
/**
* @brief Flash erase operation.
*
* This operation must erase one block specified by the offset.
*
* @param[in, out] self The flash control.
* @param[in] offset The offset to erase from the flash begin in bytes.
*
* @retval 0 Successful operation.
* @retval -EIO An error occurred. Please note that the value is negative.
* @retval other All other values are reserved and must not be used.
*/
typedef int (*rtems_jffs2_flash_erase)(
rtems_jffs2_flash_control *self,
uint32_t offset
);
/**
* @brief Flash destroy operation.
*
* The flash destroy operation is called during unmount of the file system
* instance. It can be used to free the resources associated with the now
* unused flash control
*
* @param[in, out] self The flash control.
*/
typedef void (*rtems_jffs2_flash_destroy)(
rtems_jffs2_flash_control *self
);
/**
* @brief JFFS2 flash device control.
*/
struct rtems_jffs2_flash_control {
/**
* @brief The size in bytes of the erasable unit of the flash device.
*/
uint32_t block_size;
/**
* @brief The size in bytes of the flash device.
*
* It must be an integral multiple of the block size. The flash device must
* have at least five blocks.
*/
uint32_t flash_size;
/**
* @brief Read from flash operation.
*/
rtems_jffs2_flash_read read;
/**
* @brief Write to flash operation.
*/
rtems_jffs2_flash_write write;
/**
* @brief Flash erase operation.
*/
rtems_jffs2_flash_erase erase;
/**
* @brief Flash destroy operation.
*
* This operation is optional and the pointer may be @c NULL.
*/
rtems_jffs2_flash_destroy destroy;
};
typedef struct rtems_jffs2_compressor_control rtems_jffs2_compressor_control;
/**
* @brief Compress operation.
*
* @param[in, out] self The compressor control.
* @param[in] data_in The uncompressed data.
* @param[out] cdata_out Pointer to buffer with the compressed data.
* @param[in, out] datalen On entry, the size in bytes of the uncompressed
* data. On exit, the size in bytes of uncompressed data which was actually
* compressed.
* @param[in, out] cdatalen On entry, the size in bytes available for
* compressed data. On exit, the size in bytes of the actually compressed
* data.
*
* @return The compressor type.
*/
typedef uint16_t (*rtems_jffs2_compressor_compress)(
rtems_jffs2_compressor_control *self,
unsigned char *data_in,
unsigned char *cdata_out,
uint32_t *datalen,
uint32_t *cdatalen
);
/**
* @brief Decompress operation.
*
* @param[in, out] self The compressor control.
* @param[in] comprtype The compressor type.
* @param[in] cdata_in The compressed data.
* @param[out] data_out The uncompressed data.
* @param[in] cdatalen The size in bytes of the compressed data.
* @param[in] datalen The size in bytes of the uncompressed data.
*
* @retval 0 Successful operation.
* @retval -EIO An error occurred. Please note that the value is negative.
* @retval other All other values are reserved and must not be used.
*/
typedef int (*rtems_jffs2_compressor_decompress)(
rtems_jffs2_compressor_control *self,
uint16_t comprtype,
unsigned char *cdata_in,
unsigned char *data_out,
uint32_t cdatalen,
uint32_t datalen
);
/**
* @brief Compressor destroy operation.
*
* The compressor destroy operation is called during unmount of the file system
* instance. It can be used to free the resources associated with the now
* unused compressor operations.
*
* @param[in, out] self The compressor control.
*/
typedef void (*rtems_jffs2_compressor_destroy)(
rtems_jffs2_compressor_control *self
);
/**
* @brief JFFS2 compressor control.
*/
struct rtems_jffs2_compressor_control {
/**
* @brief Compress operation.
*/
rtems_jffs2_compressor_compress compress;
/**
* @brief Decompress operation.
*/
rtems_jffs2_compressor_decompress decompress;
/**
* @brief Compressor destroy operation.
*
* This operation is optional and the pointer may be @c NULL.
*/
rtems_jffs2_compressor_destroy destroy;
/**
* @brief Compression buffer.
*/
unsigned char buffer[PAGE_SIZE];
};
/**
* @brief RTIME compressor compress operation.
*/
uint16_t rtems_jffs2_compressor_rtime_compress(
rtems_jffs2_compressor_control *self,
unsigned char *data_in,
unsigned char *cdata_out,
uint32_t *datalen,
uint32_t *cdatalen
);
/**
* @brief RTIME compressor decompress operation.
*/
int rtems_jffs2_compressor_rtime_decompress(
rtems_jffs2_compressor_control *self,
uint16_t comprtype,
unsigned char *cdata_in,
unsigned char *data_out,
uint32_t cdatalen,
uint32_t datalen
);
/**
* @brief ZLIB compressor control structure.
*/
typedef struct {
rtems_jffs2_compressor_control super;
z_stream stream;
} rtems_jffs2_compressor_zlib_control;
/**
* @brief ZLIB compressor compress operation.
*/
uint16_t rtems_jffs2_compressor_zlib_compress(
rtems_jffs2_compressor_control *self,
unsigned char *data_in,
unsigned char *cdata_out,
uint32_t *datalen,
uint32_t *cdatalen
);
/**
* @brief ZLIB compressor decompress operation.
*/
int rtems_jffs2_compressor_zlib_decompress(
rtems_jffs2_compressor_control *self,
uint16_t comprtype,
unsigned char *cdata_in,
unsigned char *data_out,
uint32_t cdatalen,
uint32_t datalen
);
/**
* @brief JFFS2 mount options.
*
* For JFFS2 the mount options are mandatory.
*/
typedef struct {
/**
* @brief Flash control.
*/
rtems_jffs2_flash_control *flash_control;
/**
* @brief Compressor control.
*
* The compressor is optional and this pointer may be @c NULL.
*/
rtems_jffs2_compressor_control *compressor_control;
} rtems_jffs2_mount_data;
/**
* @brief Initialization handler of the JFFS2 file system.
*
* @param[in, out] mt_entry The mount table entry.
* @param[in] data The mount options are mandatory for JFFS2 and data must
* point to a valid @ref rtems_jffs2_mount_data structure used for this file
* system instance.
*
* @retval 0 Successful operation.
* @retval -1 An error occurred. The @c errno indicates the error.
*
* @see mount().
*/
int rtems_jffs2_initialize(
rtems_filesystem_mount_table_entry_t *mt_entry,
const void *data
);
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* RTEMS_JFFS2_H */
+15 -345
View File
@@ -5,6 +5,7 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
* Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* University of Szeged, Hungary
* Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
*
* Created by Arjan van de Ven <arjan@infradead.org>
*
@@ -16,117 +17,6 @@
#include "compr.h"
static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
/* Available compressors are on this list */
static LIST_HEAD(jffs2_compressor_list);
/* Actual compression mode */
static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
/* Statistics for blocks stored without compression */
static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
/*
* Return 1 to use this compression
*/
static int jffs2_is_best_compression(struct jffs2_compressor *this,
struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
{
switch (jffs2_compression_mode) {
case JFFS2_COMPR_MODE_SIZE:
if (bestsize > size)
return 1;
return 0;
case JFFS2_COMPR_MODE_FAVOURLZO:
if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
return 1;
if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
return 1;
if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
return 1;
if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
return 1;
return 0;
}
/* Shouldn't happen */
return 0;
}
/*
* jffs2_selected_compress:
* @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
* If 0, just take the first available compression mode.
* @data_in: Pointer to uncompressed data
* @cpage_out: Pointer to returned 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: the compression type used. Zero is used to show that the data
* could not be compressed; probably because we couldn't find the requested
* compression mode.
*/
static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
{
struct jffs2_compressor *this;
int err, ret = JFFS2_COMPR_NONE;
uint32_t orig_slen, orig_dlen;
char *output_buf;
output_buf = kmalloc(*cdatalen, GFP_KERNEL);
if (!output_buf) {
pr_warn("No memory for compressor allocation. Compression failed.\n");
return ret;
}
orig_slen = *datalen;
orig_dlen = *cdatalen;
spin_lock(&jffs2_compressor_list_lock);
list_for_each_entry(this, &jffs2_compressor_list, list) {
/* Skip decompress-only and disabled modules */
if (!this->compress || this->disabled)
continue;
/* Skip if not the desired compression type */
if (compr && (compr != this->compr))
continue;
/*
* Either compression type was unspecified, or we found our
* compressor; either way, we're good to go.
*/
this->usecount++;
spin_unlock(&jffs2_compressor_list_lock);
*datalen = orig_slen;
*cdatalen = orig_dlen;
err = this->compress(data_in, output_buf, datalen, cdatalen);
spin_lock(&jffs2_compressor_list_lock);
this->usecount--;
if (!err) {
/* Success */
ret = this->compr;
this->stat_compr_blocks++;
this->stat_compr_orig_size += *datalen;
this->stat_compr_new_size += *cdatalen;
break;
}
}
spin_unlock(&jffs2_compressor_list_lock);
if (ret == JFFS2_COMPR_NONE)
kfree(output_buf);
else
*cpage_out = output_buf;
return ret;
}
/* jffs2_compress:
* @data_in: Pointer to uncompressed data
* @cpage_out: Pointer to returned pointer to buffer for compressed data
@@ -149,103 +39,20 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
unsigned char *data_in, unsigned char **cpage_out,
uint32_t *datalen, uint32_t *cdatalen)
{
int ret = JFFS2_COMPR_NONE;
int mode, compr_ret;
struct jffs2_compressor *this, *best=NULL;
unsigned char *output_buf = NULL, *tmp_buf;
uint32_t orig_slen, orig_dlen;
uint32_t best_slen=0, best_dlen=0;
struct super_block *sb = OFNI_BS_2SFFJ(c);
rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
int ret;
if (c->mount_opts.override_compr)
mode = c->mount_opts.compr;
else
mode = jffs2_compression_mode;
switch (mode) {
case JFFS2_COMPR_MODE_NONE:
break;
case JFFS2_COMPR_MODE_PRIORITY:
ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
cdatalen);
break;
case JFFS2_COMPR_MODE_SIZE:
case JFFS2_COMPR_MODE_FAVOURLZO:
orig_slen = *datalen;
orig_dlen = *cdatalen;
spin_lock(&jffs2_compressor_list_lock);
list_for_each_entry(this, &jffs2_compressor_list, list) {
/* Skip decompress-only backwards-compatibility and disabled modules */
if ((!this->compress)||(this->disabled))
continue;
/* Allocating memory for output buffer if necessary */
if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
spin_unlock(&jffs2_compressor_list_lock);
kfree(this->compr_buf);
spin_lock(&jffs2_compressor_list_lock);
this->compr_buf_size=0;
this->compr_buf=NULL;
}
if (!this->compr_buf) {
spin_unlock(&jffs2_compressor_list_lock);
tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
spin_lock(&jffs2_compressor_list_lock);
if (!tmp_buf) {
pr_warn("No memory for compressor allocation. (%d bytes)\n",
orig_slen);
continue;
}
else {
this->compr_buf = tmp_buf;
this->compr_buf_size = orig_slen;
}
}
this->usecount++;
spin_unlock(&jffs2_compressor_list_lock);
*datalen = orig_slen;
*cdatalen = orig_dlen;
compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
spin_lock(&jffs2_compressor_list_lock);
this->usecount--;
if (!compr_ret) {
if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
&& (*cdatalen < *datalen)) {
best_dlen = *cdatalen;
best_slen = *datalen;
best = this;
}
}
}
if (best_dlen) {
*cdatalen = best_dlen;
*datalen = best_slen;
output_buf = best->compr_buf;
best->compr_buf = NULL;
best->compr_buf_size = 0;
best->stat_compr_blocks++;
best->stat_compr_orig_size += best_slen;
best->stat_compr_new_size += best_dlen;
ret = best->compr;
*cpage_out = output_buf;
}
spin_unlock(&jffs2_compressor_list_lock);
break;
case JFFS2_COMPR_MODE_FORCELZO:
ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
cpage_out, datalen, cdatalen);
break;
case JFFS2_COMPR_MODE_FORCEZLIB:
ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
cpage_out, datalen, cdatalen);
break;
default:
pr_err("unknown compression mode\n");
if (cc != NULL) {
*cpage_out = &cc->buffer[0];
ret = (*cc->compress)(cc, data_in, *cpage_out, datalen, cdatalen);
} else {
ret = JFFS2_COMPR_NONE;
}
if (ret == JFFS2_COMPR_NONE) {
*cpage_out = data_in;
*datalen = *cdatalen;
none_stat_compr_blocks++;
none_stat_compr_size += *datalen;
}
return ret;
}
@@ -254,8 +61,8 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
uint16_t comprtype, unsigned char *cdata_in,
unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
{
struct jffs2_compressor *this;
int ret;
struct super_block *sb = OFNI_BS_2SFFJ(c);
rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
/* Older code had a bug where it would write non-zero 'usercompr'
fields. Deal with it. */
@@ -266,153 +73,16 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
case JFFS2_COMPR_NONE:
/* This should be special-cased elsewhere, but we might as well deal with it */
memcpy(data_out, cdata_in, datalen);
none_stat_decompr_blocks++;
break;
case JFFS2_COMPR_ZERO:
memset(data_out, 0, datalen);
break;
default:
spin_lock(&jffs2_compressor_list_lock);
list_for_each_entry(this, &jffs2_compressor_list, list) {
if (comprtype == this->compr) {
this->usecount++;
spin_unlock(&jffs2_compressor_list_lock);
ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
spin_lock(&jffs2_compressor_list_lock);
if (ret) {
pr_warn("Decompressor \"%s\" returned %d\n",
this->name, ret);
}
else {
this->stat_decompr_blocks++;
}
this->usecount--;
spin_unlock(&jffs2_compressor_list_lock);
return ret;
}
}
pr_warn("compression type 0x%02x not available\n", comprtype);
spin_unlock(&jffs2_compressor_list_lock);
return -EIO;
}
return 0;
}
int jffs2_register_compressor(struct jffs2_compressor *comp)
{
struct jffs2_compressor *this;
if (!comp->name) {
pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
return -1;
}
comp->compr_buf_size=0;
comp->compr_buf=NULL;
comp->usecount=0;
comp->stat_compr_orig_size=0;
comp->stat_compr_new_size=0;
comp->stat_compr_blocks=0;
comp->stat_decompr_blocks=0;
jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
spin_lock(&jffs2_compressor_list_lock);
list_for_each_entry(this, &jffs2_compressor_list, list) {
if (this->priority < comp->priority) {
list_add(&comp->list, this->list.prev);
goto out;
if (cc != NULL) {
return (*cc->decompress)(cc, comprtype, cdata_in, data_out, cdatalen, datalen);
} else {
return -EIO;
}
}
list_add_tail(&comp->list, &jffs2_compressor_list);
out:
D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
})
spin_unlock(&jffs2_compressor_list_lock);
return 0;
}
int jffs2_unregister_compressor(struct jffs2_compressor *comp)
{
D2(struct jffs2_compressor *this);
jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
spin_lock(&jffs2_compressor_list_lock);
if (comp->usecount) {
spin_unlock(&jffs2_compressor_list_lock);
pr_warn("Compressor module is in use. Unregister failed.\n");
return -1;
}
list_del(&comp->list);
D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
})
spin_unlock(&jffs2_compressor_list_lock);
return 0;
}
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
{
if (orig != comprbuf)
kfree(comprbuf);
}
int __init jffs2_compressors_init(void)
{
/* Registering compressors */
#ifdef CONFIG_JFFS2_ZLIB
jffs2_zlib_init();
#endif
#ifdef CONFIG_JFFS2_RTIME
jffs2_rtime_init();
#endif
#ifdef CONFIG_JFFS2_RUBIN
jffs2_rubinmips_init();
jffs2_dynrubin_init();
#endif
#ifdef CONFIG_JFFS2_LZO
jffs2_lzo_init();
#endif
/* Setting default compression mode */
#ifdef CONFIG_JFFS2_CMODE_NONE
jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
jffs2_dbg(1, "default compression mode: none\n");
#else
#ifdef CONFIG_JFFS2_CMODE_SIZE
jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
jffs2_dbg(1, "default compression mode: size\n");
#else
#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
jffs2_dbg(1, "default compression mode: favourlzo\n");
#else
jffs2_dbg(1, "default compression mode: priority\n");
#endif
#endif
#endif
return 0;
}
int jffs2_compressors_exit(void)
{
/* Unregistering compressors */
#ifdef CONFIG_JFFS2_LZO
jffs2_lzo_exit();
#endif
#ifdef CONFIG_JFFS2_RUBIN
jffs2_dynrubin_exit();
jffs2_rubinmips_exit();
#endif
#ifdef CONFIG_JFFS2_RTIME
jffs2_rtime_exit();
#endif
#ifdef CONFIG_JFFS2_ZLIB
jffs2_zlib_exit();
#endif
return 0;
}
+1 -1
View File
@@ -78,7 +78,7 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
uint16_t comprtype, unsigned char *cdata_in,
unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
#define jffs2_free_comprbuf(x, y) do { } while (0)
/* Compressor modules */
/* These functions will be called by jffs2_compressors_init/exit */
+25 -32
View File
@@ -28,15 +28,20 @@
#include <linux/jffs2.h>
#include "compr.h"
/* _compress returns the compressed size, -1 if bigger */
static int jffs2_rtime_compress(unsigned char *data_in,
unsigned char *cpage_out,
uint32_t *sourcelen, uint32_t *dstlen)
uint16_t rtems_jffs2_compressor_rtime_compress(
rtems_jffs2_compressor_control *self,
unsigned char *data_in,
unsigned char *cpage_out,
uint32_t *sourcelen,
uint32_t *dstlen
)
{
short positions[256];
int outpos = 0;
int pos=0;
(void) self;
memset(positions,0,sizeof(positions));
while (pos < (*sourcelen) && outpos <= (*dstlen)-2) {
@@ -60,24 +65,35 @@ static int jffs2_rtime_compress(unsigned char *data_in,
if (outpos >= pos) {
/* We failed */
return -1;
return JFFS2_COMPR_NONE;
}
/* Tell the caller how much we managed to compress, and how much space it took */
*sourcelen = pos;
*dstlen = outpos;
return 0;
return JFFS2_COMPR_RTIME;
}
static int jffs2_rtime_decompress(unsigned char *data_in,
unsigned char *cpage_out,
uint32_t srclen, uint32_t destlen)
int rtems_jffs2_compressor_rtime_decompress(
rtems_jffs2_compressor_control *self,
uint16_t comprtype,
unsigned char *data_in,
unsigned char *cpage_out,
uint32_t srclen,
uint32_t destlen
)
{
short positions[256];
int outpos = 0;
int pos=0;
(void) self;
if (comprtype != JFFS2_COMPR_RTIME) {
return -EIO;
}
memset(positions,0,sizeof(positions));
while (outpos<destlen) {
@@ -105,26 +121,3 @@ static int jffs2_rtime_decompress(unsigned char *data_in,
}
return 0;
}
static struct jffs2_compressor jffs2_rtime_comp = {
.priority = JFFS2_RTIME_PRIORITY,
.name = "rtime",
.compr = JFFS2_COMPR_RTIME,
.compress = &jffs2_rtime_compress,
.decompress = &jffs2_rtime_decompress,
#ifdef JFFS2_RTIME_DISABLED
.disabled = 1,
#else
.disabled = 0,
#endif
};
int jffs2_rtime_init(void)
{
return jffs2_register_compressor(&jffs2_rtime_comp);
}
void jffs2_rtime_exit(void)
{
jffs2_unregister_compressor(&jffs2_rtime_comp);
}
+67 -112
View File
@@ -33,126 +33,115 @@
static DEFINE_MUTEX(deflate_mutex);
static DEFINE_MUTEX(inflate_mutex);
static z_stream inf_strm, def_strm;
#ifdef __KERNEL__ /* Linux-only */
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/mutex.h>
static int __init alloc_workspaces(void)
static rtems_jffs2_compressor_zlib_control *get_zlib_control(
rtems_jffs2_compressor_control *super
)
{
def_strm.workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS,
MAX_MEM_LEVEL));
if (!def_strm.workspace)
return -ENOMEM;
jffs2_dbg(1, "Allocated %d bytes for deflate workspace\n",
zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
if (!inf_strm.workspace) {
vfree(def_strm.workspace);
return -ENOMEM;
}
jffs2_dbg(1, "Allocated %d bytes for inflate workspace\n",
zlib_inflate_workspacesize());
return 0;
return (rtems_jffs2_compressor_zlib_control *) super;
}
static void free_workspaces(void)
{
vfree(def_strm.workspace);
vfree(inf_strm.workspace);
}
#else
#define alloc_workspaces() (0)
#define free_workspaces() do { } while(0)
#endif /* __KERNEL__ */
static int jffs2_zlib_compress(unsigned char *data_in,
unsigned char *cpage_out,
uint32_t *sourcelen, uint32_t *dstlen)
uint16_t rtems_jffs2_compressor_zlib_compress(
rtems_jffs2_compressor_control *super,
unsigned char *data_in,
unsigned char *cpage_out,
uint32_t *sourcelen,
uint32_t *dstlen
)
{
rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
z_stream *def_strm = &self->stream;
int ret;
if (*dstlen <= STREAM_END_SPACE)
return -1;
return JFFS2_COMPR_NONE;
mutex_lock(&deflate_mutex);
if (Z_OK != zlib_deflateInit(&def_strm, 3)) {
if (Z_OK != zlib_deflateInit(def_strm, 3)) {
pr_warn("deflateInit failed\n");
mutex_unlock(&deflate_mutex);
return -1;
return JFFS2_COMPR_NONE;
}
def_strm.next_in = data_in;
def_strm.total_in = 0;
def_strm->next_in = data_in;
def_strm->total_in = 0;
def_strm.next_out = cpage_out;
def_strm.total_out = 0;
def_strm->next_out = cpage_out;
def_strm->total_out = 0;
while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) {
def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE);
def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out);
while (def_strm->total_out < *dstlen - STREAM_END_SPACE && def_strm->total_in < *sourcelen) {
def_strm->avail_out = *dstlen - (def_strm->total_out + STREAM_END_SPACE);
def_strm->avail_in = min((unsigned)(*sourcelen-def_strm->total_in), def_strm->avail_out);
jffs2_dbg(1, "calling deflate with avail_in %d, avail_out %d\n",
def_strm.avail_in, def_strm.avail_out);
ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH);
def_strm->avail_in, def_strm->avail_out);
ret = zlib_deflate(def_strm, Z_PARTIAL_FLUSH);
jffs2_dbg(1, "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n",
def_strm.avail_in, def_strm.avail_out,
def_strm.total_in, def_strm.total_out);
def_strm->avail_in, def_strm->avail_out,
def_strm->total_in, def_strm->total_out);
if (ret != Z_OK) {
jffs2_dbg(1, "deflate in loop returned %d\n", ret);
zlib_deflateEnd(&def_strm);
zlib_deflateEnd(def_strm);
mutex_unlock(&deflate_mutex);
return -1;
return JFFS2_COMPR_NONE;
}
}
def_strm.avail_out += STREAM_END_SPACE;
def_strm.avail_in = 0;
ret = zlib_deflate(&def_strm, Z_FINISH);
zlib_deflateEnd(&def_strm);
def_strm->avail_out += STREAM_END_SPACE;
def_strm->avail_in = 0;
ret = zlib_deflate(def_strm, Z_FINISH);
zlib_deflateEnd(def_strm);
if (ret != Z_STREAM_END) {
jffs2_dbg(1, "final deflate returned %d\n", ret);
ret = -1;
ret = JFFS2_COMPR_NONE;
goto out;
}
if (def_strm.total_out >= def_strm.total_in) {
if (def_strm->total_out >= def_strm->total_in) {
jffs2_dbg(1, "zlib compressed %ld bytes into %ld; failing\n",
def_strm.total_in, def_strm.total_out);
ret = -1;
def_strm->total_in, def_strm->total_out);
ret = JFFS2_COMPR_NONE;
goto out;
}
jffs2_dbg(1, "zlib compressed %ld bytes into %ld\n",
def_strm.total_in, def_strm.total_out);
def_strm->total_in, def_strm->total_out);
*dstlen = def_strm.total_out;
*sourcelen = def_strm.total_in;
ret = 0;
*dstlen = def_strm->total_out;
*sourcelen = def_strm->total_in;
ret = JFFS2_COMPR_ZLIB;
out:
mutex_unlock(&deflate_mutex);
return ret;
}
static int jffs2_zlib_decompress(unsigned char *data_in,
unsigned char *cpage_out,
uint32_t srclen, uint32_t destlen)
int rtems_jffs2_compressor_zlib_decompress(
rtems_jffs2_compressor_control *super,
uint16_t comprtype,
unsigned char *data_in,
unsigned char *cpage_out,
uint32_t srclen,
uint32_t destlen
)
{
rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
z_stream *inf_strm = &self->stream;
int ret;
int wbits = MAX_WBITS;
if (comprtype != JFFS2_COMPR_ZLIB) {
return -EIO;
}
mutex_lock(&inflate_mutex);
inf_strm.next_in = data_in;
inf_strm.avail_in = srclen;
inf_strm.total_in = 0;
inf_strm->next_in = data_in;
inf_strm->avail_in = srclen;
inf_strm->total_in = 0;
inf_strm.next_out = cpage_out;
inf_strm.avail_out = destlen;
inf_strm.total_out = 0;
inf_strm->next_out = cpage_out;
inf_strm->avail_out = destlen;
inf_strm->total_out = 0;
/* If it's deflate, and it's got no preset dictionary, then
we can tell zlib to skip the adler32 check. */
@@ -162,60 +151,26 @@ static int jffs2_zlib_decompress(unsigned char *data_in,
jffs2_dbg(2, "inflate skipping adler32\n");
wbits = -((data_in[0] >> 4) + 8);
inf_strm.next_in += 2;
inf_strm.avail_in -= 2;
inf_strm->next_in += 2;
inf_strm->avail_in -= 2;
} else {
/* Let this remain D1 for now -- it should never happen */
jffs2_dbg(1, "inflate not skipping adler32\n");
}
if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) {
if (Z_OK != zlib_inflateInit2(inf_strm, wbits)) {
pr_warn("inflateInit failed\n");
mutex_unlock(&inflate_mutex);
return 1;
return -EIO;
}
while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK)
while((ret = zlib_inflate(inf_strm, Z_FINISH)) == Z_OK)
;
if (ret != Z_STREAM_END) {
pr_notice("inflate returned %d\n", ret);
}
zlib_inflateEnd(&inf_strm);
zlib_inflateEnd(inf_strm);
mutex_unlock(&inflate_mutex);
return 0;
}
static struct jffs2_compressor jffs2_zlib_comp = {
.priority = JFFS2_ZLIB_PRIORITY,
.name = "zlib",
.compr = JFFS2_COMPR_ZLIB,
.compress = &jffs2_zlib_compress,
.decompress = &jffs2_zlib_decompress,
#ifdef JFFS2_ZLIB_DISABLED
.disabled = 1,
#else
.disabled = 0,
#endif
};
int __init jffs2_zlib_init(void)
{
int ret;
ret = alloc_workspaces();
if (ret)
return ret;
ret = jffs2_register_compressor(&jffs2_zlib_comp);
if (ret)
free_workspaces();
return ret;
}
void jffs2_zlib_exit(void)
{
jffs2_unregister_compressor(&jffs2_zlib_comp);
free_workspaces();
}
+18
View File
@@ -75,6 +75,7 @@ do { \
#define JFFS2_DBG_MSG_PREFIX JFFS2_DBG JFFS2_DBG_PREFIX
/* JFFS2 message macros */
#ifndef __rtems__
#define JFFS2_ERROR(fmt, ...) \
pr_err("error: (%d) %s: " fmt, \
task_pid_nr(current), __func__, ##__VA_ARGS__)
@@ -90,6 +91,23 @@ do { \
#define JFFS2_DEBUG(fmt, ...) \
printk(KERN_DEBUG "[JFFS2 DBG] (%d) %s: " fmt, \
task_pid_nr(current), __func__, ##__VA_ARGS__)
#else /* __rtems__ */
#define JFFS2_ERROR(fmt, ...) \
pr_err("error: %s: " fmt, \
__func__, ##__VA_ARGS__)
#define JFFS2_WARNING(fmt, ...) \
pr_warn("warning: %s: " fmt, \
__func__, ##__VA_ARGS__)
#define JFFS2_NOTICE(fmt, ...) \
pr_notice("notice: %s: " fmt, \
__func__, ##__VA_ARGS__)
#define JFFS2_DEBUG(fmt, ...) \
printk(KERN_DEBUG "[JFFS2 DBG] %s: " fmt, \
__func__, ##__VA_ARGS__)
#endif /* __rtems__ */
/*
* We split our debugging messages on several parts, depending on the JFFS2
+141 -92
View File
@@ -1,10 +1,15 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001-2003 Free Software Foundation, Inc.
* Copyright © 2001-2003 Free Software Foundation, Inc.
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
* Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
*
* Created by David Woodhouse <dwmw2@cambridge.redhat.com>
*
* Port to the RTEMS by embedded brains GmbH.
*
* For licensing information, see the file 'LICENCE' in this directory.
*
* $Id: dir-ecos.c,v 1.11 2005/02/08 19:36:27 lunn Exp $
@@ -18,39 +23,39 @@
/***********************************************************************/
/* Takes length argument because it can be either NUL-terminated or '/'-terminated */
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, int namelen)
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, size_t namelen)
{
struct jffs2_inode_info *dir_f;
struct jffs2_sb_info *c;
struct jffs2_full_dirent *fd = NULL, *fd_list;
uint32_t ino = 0;
uint32_t hash = full_name_hash(d_name, namelen);
uint32_t hash = full_name_hash(name, namelen);
struct _inode *inode = NULL;
D1(printk("jffs2_lookup()\n"));
dir_f = JFFS2_INODE_INFO(dir_i);
c = JFFS2_SB_INFO(dir_i->i_sb);
down(&dir_f->sem);
mutex_lock(&dir_f->sem);
/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= hash; fd_list = fd_list->next) {
if (fd_list->nhash == hash &&
(!fd || fd_list->version > fd->version) &&
strlen((char *)fd_list->name) == namelen &&
!strncmp((char *)fd_list->name, (char *)d_name, namelen)) {
!strncmp((char *)fd_list->name, (char *)name, namelen)) {
fd = fd_list;
}
}
if (fd)
ino = fd->ino;
up(&dir_f->sem);
mutex_unlock(&dir_f->sem);
if (ino) {
inode = jffs2_iget(dir_i->i_sb, ino);
if (IS_ERR(inode)) {
printk("jffs2_iget() failed for ino #%u\n", ino);
return inode;
} else {
inode->i_fd = fd;
}
}
@@ -61,14 +66,17 @@ struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, i
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
struct _inode **new_i)
int jffs2_create(struct _inode *dir_i, const char *d_name, size_t d_namelen, int mode)
{
struct jffs2_raw_inode *ri;
struct jffs2_inode_info *f, *dir_f;
struct jffs2_sb_info *c;
struct _inode *inode;
int ret;
struct qstr qstr;
qstr.name = d_name;
qstr.len = d_namelen;
ri = jffs2_alloc_raw_inode();
if (!ri)
@@ -89,9 +97,7 @@ int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
f = JFFS2_INODE_INFO(inode);
dir_f = JFFS2_INODE_INFO(dir_i);
ret = jffs2_do_create(c, dir_f, f, ri,
(const char *)d_name,
strlen((char *)d_name));
ret = jffs2_do_create(c, dir_f, f, ri, &qstr);
if (ret) {
inode->i_nlink = 0;
@@ -100,34 +106,36 @@ int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
return ret;
}
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
jffs2_free_raw_inode(ri);
D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink));
*new_i = inode;
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink));
jffs2_iput(inode);
return 0;
}
/***********************************************************************/
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode);
int ret;
ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
strlen((char *)d_name), dead_f);
ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
d_namelen, dead_f, get_seconds());
if (dead_f->inocache)
d_inode->i_nlink = dead_f->inocache->nlink;
d_inode->i_nlink = dead_f->inocache->pino_nlink;
return ret;
}
/***********************************************************************/
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name)
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode);
@@ -140,17 +148,26 @@ int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned
ret = jffs2_do_link(c, dir_f, f->inocache->ino, type,
(const char * )d_name,
strlen((char *)d_name));
d_namelen, get_seconds());
if (!ret) {
down(&f->sem);
old_d_inode->i_nlink = ++f->inocache->nlink;
up(&f->sem);
mutex_lock(&f->sem);
old_d_inode->i_nlink = ++f->inocache->pino_nlink;
mutex_unlock(&f->sem);
}
return ret;
}
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
/***********************************************************************/
int jffs2_mknod(
struct _inode *dir_i,
const unsigned char *d_name,
size_t d_namelen,
int mode,
const unsigned char *data,
size_t datalen
)
{
struct jffs2_inode_info *f, *dir_f;
struct jffs2_sb_info *c;
@@ -159,23 +176,26 @@ int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
struct jffs2_raw_dirent *rd;
struct jffs2_full_dnode *fn;
struct jffs2_full_dirent *fd;
int namelen;
uint32_t alloclen, phys_ofs;
uint32_t alloclen;
int ret;
mode |= S_IFDIR;
/* FIXME: If you care. We'd need to use frags for the data
if it grows much more than this */
if (datalen > 254)
return -ENAMETOOLONG;
ri = jffs2_alloc_raw_inode();
if (!ri)
return -ENOMEM;
c = JFFS2_SB_INFO(dir_i->i_sb);
/* Try to reserve enough space for both node and dirent.
* Just the node will do for now, though
/* Try to reserve enough space for both node and dirent.
* Just the node will do for now, though
*/
namelen = strlen((char *)d_name);
ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &alloclen,
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
if (ret) {
jffs2_free_raw_inode(ri);
@@ -192,104 +212,132 @@ int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
f = JFFS2_INODE_INFO(inode);
ri->data_crc = cpu_to_je32(0);
inode->i_size = datalen;
ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);
ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);
ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
ri->compr = JFFS2_COMPR_NONE;
ri->data_crc = cpu_to_je32(crc32(0, data, datalen));
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
fn = jffs2_write_dnode(c, f, ri, data, datalen, ALLOC_NORMAL);
jffs2_free_raw_inode(ri);
if (IS_ERR(fn)) {
/* Eeek. Wave bye bye */
up(&f->sem);
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
inode->i_nlink = 0;
jffs2_iput(inode);
return PTR_ERR(fn);
ret = PTR_ERR(fn);
goto fail;
}
/* No data here. Only a metadata node, which will be
if (S_ISLNK(mode)) {
/* We use f->target field to store the target path. */
f->target = kmemdup(data, datalen + 1, GFP_KERNEL);
if (!f->target) {
pr_warn("Can't allocate %d bytes of memory\n", datalen + 1);
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
ret = -ENOMEM;
goto fail;
}
jffs2_dbg(1, "%s(): symlink's target '%s' cached\n",
__func__, (char *)f->target);
}
/* No data here. Only a metadata node, which will be
obsoleted by the first data write
*/
f->metadata = fn;
up(&f->sem);
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
if (ret) {
/* Eep. */
inode->i_nlink = 0;
jffs2_iput(inode);
return ret;
}
ret = jffs2_reserve_space(c, sizeof(*rd)+d_namelen, &alloclen,
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(d_namelen));
if (ret)
goto fail;
rd = jffs2_alloc_raw_dirent();
if (!rd) {
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation(c);
inode->i_nlink = 0;
jffs2_iput(inode);
return -ENOMEM;
ret = -ENOMEM;
goto fail;
}
dir_f = JFFS2_INODE_INFO(dir_i);
down(&dir_f->sem);
mutex_lock(&dir_f->sem);
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
rd->totlen = cpu_to_je32(sizeof(*rd) + d_namelen);
rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
rd->pino = cpu_to_je32(dir_i->i_ino);
rd->version = cpu_to_je32(++dir_f->highest_version);
rd->ino = cpu_to_je32(inode->i_ino);
rd->mctime = cpu_to_je32(cyg_timestamp());
rd->nsize = namelen;
rd->type = DT_DIR;
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen));
rd->mctime = cpu_to_je32(get_seconds());
rd->nsize = d_namelen;
/* XXX: This is ugly. */
rd->type = (mode & S_IFMT) >> 12;
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
rd->name_crc = cpu_to_je32(crc32(0, d_name, d_namelen));
fd = jffs2_write_dirent(c, dir_f, rd, d_name, d_namelen, ALLOC_NORMAL);
fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL);
jffs2_complete_reservation(c);
jffs2_free_raw_dirent(rd);
if (IS_ERR(fd)) {
/* dirent failed to write. Delete the inode normally
/* dirent failed to write. Delete the inode normally
as if it were the final unlink() */
up(&dir_f->sem);
inode->i_nlink = 0;
jffs2_iput(inode);
return PTR_ERR(fd);
jffs2_complete_reservation(c);
jffs2_free_raw_dirent(rd);
mutex_unlock(&dir_f->sem);
ret = PTR_ERR(fd);
goto fail;
}
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
jffs2_free_raw_dirent(rd);
/* Link the fd into the inode's list, obsoleting an old
one if necessary. */
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
up(&dir_f->sem);
mutex_unlock(&dir_f->sem);
jffs2_complete_reservation(c);
fail:
jffs2_iput(inode);
return 0;
return ret;
}
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
{
struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
struct jffs2_full_dirent *fd;
for (fd = f->dents ; fd; fd = fd->next) {
if (fd->ino)
return EPERM; //-ENOTEMPTY;
return -ENOTEMPTY;
}
return jffs2_unlink(dir_i, d_inode, d_name);
return jffs2_unlink(dir_i, d_inode, d_name, d_namelen);
}
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
struct _inode *new_dir_i, const unsigned char *new_d_name)
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, size_t old_d_namelen,
struct _inode *new_dir_i, const unsigned char *new_d_name, size_t new_d_namelen)
{
int ret;
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
struct jffs2_inode_info *victim_f = NULL;
uint8_t type;
uint32_t now;
#if 0 /* FIXME -- this really doesn't belong in individual file systems.
The fileio code ought to do this for us, or at least part of it */
@@ -309,14 +357,14 @@ int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsign
/* Cannot rename non-directory over directory */
return -EINVAL;
}
down(&victim_f->sem);
mutex_lock(&victim_f->sem);
for (fd = victim_f->dents; fd; fd = fd->next) {
if (fd->ino) {
up(&victim_f->sem);
mutex_unlock(&victim_f->sem);
return -ENOTEMPTY;
}
}
up(&victim_f->sem);
mutex_unlock(&victim_f->sem);
}
}
#endif
@@ -332,10 +380,11 @@ int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsign
type = (d_inode->i_mode & S_IFMT) >> 12;
if (!type) type = DT_REG;
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
now = get_seconds();
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
d_inode->i_ino, type,
(const char *)new_d_name,
strlen((char *)new_d_name));
(const char *)new_d_name,
new_d_namelen, now);
if (ret)
return ret;
@@ -345,24 +394,24 @@ int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsign
/* Don't oops if the victim was a dirent pointing to an
inode which didn't exist. */
if (victim_f->inocache) {
down(&victim_f->sem);
victim_f->inocache->nlink--;
up(&victim_f->sem);
mutex_lock(&victim_f->sem);
victim_f->inocache->pino_nlink--;
mutex_unlock(&victim_f->sem);
}
}
/* Unlink the original */
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
(const char *)old_d_name,
strlen((char *)old_d_name), NULL);
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
(const char *)old_d_name,
old_d_namelen, NULL, now);
if (ret) {
/* Oh shit. We really ought to make a single node which can do both atomically */
struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
down(&f->sem);
mutex_lock(&f->sem);
if (f->inocache)
d_inode->i_nlink = f->inocache->nlink++;
up(&f->sem);
d_inode->i_nlink = f->inocache->pino_nlink++;
mutex_unlock(&f->sem);
printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
}
+1 -1
View File
@@ -391,7 +391,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
*bad_offset = ofs;
ret = mtd_read(c->mtd, ofs, readlen, &retlen, ebuf);
ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf);
if (ret) {
pr_warn("Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n",
ofs, ret);
+14 -46
View File
@@ -15,46 +15,28 @@
#include <linux/kernel.h>
#include "nodelist.h"
#include <cyg/io/io.h>
#include <cyg/io/config_keys.h>
#include <cyg/io/flash.h>
cyg_bool jffs2_flash_read(struct jffs2_sb_info * c,
int jffs2_flash_read(struct jffs2_sb_info * c,
cyg_uint32 read_buffer_offset, const size_t size,
size_t * return_size, unsigned char *write_buffer)
{
Cyg_ErrNo err;
cyg_uint32 len = size;
struct super_block *sb = OFNI_BS_2SFFJ(c);
const struct super_block *sb = OFNI_BS_2SFFJ(c);
rtems_jffs2_flash_control *fc = sb->s_flash_control;
//D2(printf("FLASH READ\n"));
//D2(printf("read address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + read_buffer_offset));
//D2(printf("write address = %x\n", write_buffer));
//D2(printf("size = %x\n", size));
err = cyg_io_bread(sb->s_dev, write_buffer, &len, read_buffer_offset);
*return_size = size;
*return_size = (size_t) len;
return ((err == ENOERR) ? ENOERR : -EIO);
return (*fc->read)(fc, read_buffer_offset, write_buffer, size);
}
cyg_bool jffs2_flash_write(struct jffs2_sb_info * c,
int jffs2_flash_write(struct jffs2_sb_info * c,
cyg_uint32 write_buffer_offset, const size_t size,
size_t * return_size, unsigned char *read_buffer)
{
const struct super_block *sb = OFNI_BS_2SFFJ(c);
rtems_jffs2_flash_control *fc = sb->s_flash_control;
Cyg_ErrNo err;
cyg_uint32 len = size;
struct super_block *sb = OFNI_BS_2SFFJ(c);
*return_size = size;
// D2(printf("FLASH WRITE ENABLED!!!\n"));
// D2(printf("write address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + write_buffer_offset));
// D2(printf("read address = %x\n", read_buffer));
// D2(printf("size = %x\n", size));
err = cyg_io_bwrite(sb->s_dev, read_buffer, &len, write_buffer_offset);
*return_size = (size_t) len;
return ((err == ENOERR) ? ENOERR : -EIO);
return (*fc->write)(fc, write_buffer_offset, read_buffer, size);
}
int
@@ -140,26 +122,12 @@ jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
return ret;
}
cyg_bool jffs2_flash_erase(struct jffs2_sb_info * c,
int jffs2_flash_erase(struct jffs2_sb_info * c,
struct jffs2_eraseblock * jeb)
{
cyg_io_flash_getconfig_erase_t e;
cyg_flashaddr_t err_addr;
Cyg_ErrNo err;
cyg_uint32 len = sizeof (e);
struct super_block *sb = OFNI_BS_2SFFJ(c);
const struct super_block *sb = OFNI_BS_2SFFJ(c);
rtems_jffs2_flash_control *fc = sb->s_flash_control;
e.offset = jeb->offset;
e.len = c->sector_size;
e.err_address = &err_addr;
// D2(printf("FLASH ERASE ENABLED!!!\n"));
// D2(printf("erase address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + jeb->offset));
// D2(printf("size = %x\n", c->sector_size));
err = cyg_io_get_config(sb->s_dev, CYG_IO_GET_CONFIG_FLASH_ERASE,
&e, &len);
return (err != ENOERR || e.flasherr != 0);
return (*fc->erase)(fc, jeb->offset);
}
File diff suppressed because it is too large Load Diff
+6
View File
@@ -741,7 +741,9 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
struct jffs2_full_dnode *new_fn;
struct jffs2_raw_inode ri;
struct jffs2_node_frag *last_frag;
#ifndef __rtems__
union jffs2_device_node dev;
#endif /* __rtems__ */
char *mdata = NULL;
int mdatalen = 0;
uint32_t alloclen, ilen;
@@ -749,11 +751,15 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
S_ISCHR(JFFS2_F_I_MODE(f)) ) {
#ifndef __rtems__
/* For these, we don't actually need to read the old node */
mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
mdata = (char *)&dev;
jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n",
__func__, mdatalen);
#else /* __rtems__ */
return -EIO;
#endif /* __rtems__ */
} else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
mdatalen = fn->size;
mdata = kmalloc(fn->size, GFP_KERNEL);
+2
View File
@@ -50,7 +50,9 @@ struct jffs2_inode_info {
uint16_t flags;
uint8_t usercompr;
#if !defined (__ECOS)
struct inode vfs_inode;
#endif
};
#endif /* _JFFS2_FS_I */
+54 -74
View File
@@ -12,13 +12,8 @@
*/
#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);
@@ -69,6 +64,60 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
free(x);
}
static struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
{
struct jffs2_raw_node_ref *ret;
ret = malloc((REFS_PER_BLOCK + 1) * sizeof(*ret));
if (ret) {
int i = 0;
for (i=0; i < REFS_PER_BLOCK; i++) {
ret[i].flash_offset = REF_EMPTY_NODE;
ret[i].next_in_ino = NULL;
}
ret[i].flash_offset = REF_LINK_NODE;
ret[i].next_in_ino = NULL;
}
return ret;
}
int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb, int nr)
{
struct jffs2_raw_node_ref **p, *ref;
int i = nr;
p = &jeb->last_node;
ref = *p;
/* If jeb->last_node is really a valid node then skip over it */
if (ref && ref->flash_offset != REF_EMPTY_NODE)
ref++;
while (i) {
if (!ref) {
ref = *p = jffs2_alloc_refblock();
if (!ref)
return -ENOMEM;
}
if (ref->flash_offset == REF_LINK_NODE) {
p = &ref->next_in_ino;
ref = *p;
continue;
}
i--;
ref++;
}
jeb->allocated_refs = nr;
return 0;
}
void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
{
free(x);
}
struct jffs2_node_frag *jffs2_alloc_node_frag(void)
{
return malloc(sizeof(struct jffs2_node_frag));
@@ -79,75 +128,6 @@ void jffs2_free_node_frag(struct jffs2_node_frag *x)
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
struct jffs2_inode_cache *jffs2_alloc_inode_cache(void)
{
struct jffs2_inode_cache *ret = malloc(sizeof(struct jffs2_inode_cache));
+4 -2
View File
@@ -21,8 +21,8 @@
#include "acl.h"
#include "summary.h"
#ifdef __ECOS
#include "os-ecos.h"
#ifdef __rtems__
#include "os-rtems.h"
#else
#include "os-linux.h"
#endif
@@ -309,6 +309,7 @@ static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c)
#define PAD(x) (((x)+3)&~3)
#ifndef __rtems__
static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
{
if (old_valid_dev(rdev)) {
@@ -319,6 +320,7 @@ static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
return sizeof(jdev->new_id);
}
}
#endif /* __rtems__ */
static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
{
+67 -89
View File
@@ -1,55 +1,40 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2002-2003 Free Software Foundation, Inc.
* Copyright © 2002-2003 Free Software Foundation, Inc.
* Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
*
* Created by David Woodhouse <dwmw2@cambridge.redhat.com>
*
* Port to the RTEMS by embedded brains GmbH.
*
* For licensing information, see the file 'LICENCE' in this directory.
*
* $Id: os-ecos.h,v 1.24 2005/02/09 09:23:55 pavlov Exp $
*
*/
#ifndef __JFFS2_OS_ECOS_H__
#define __JFFS2_OS_ECOS_H__
#ifndef __JFFS2_OS_RTEMS_H__
#define __JFFS2_OS_RTEMS_H__
#include <pkgconf/fs_jffs2.h>
#include <cyg/io/io.h>
#include <sys/types.h>
#include <asm/atomic.h>
#include <linux/stat.h>
#include <linux/compiler.h>
#include <pkgconf/system.h>
#include <pkgconf/hal.h>
#include <pkgconf/io_fileio.h>
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <cyg/fileio/fileio.h>
#include <cyg/hal/drv_api.h>
#include <cyg/infra/diag.h>
#include <cyg/io/flash.h>
#include <linux/types.h>
#include <linux/list.h>
#include <asm/bug.h>
#include <linux/compiler.h>
#include <linux/list.h>
#include <linux/pagemap.h>
#include <linux/stat.h>
#include <linux/types.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#define printf diag_printf
#include <rtems/jffs2.h>
#define CONFIG_JFFS2_RTIME
#define CONFIG_JFFS2_ZLIB
struct _inode;
struct super_block;
@@ -59,7 +44,7 @@ struct iovec {
ssize_t iov_len;
};
static inline unsigned int full_name_hash(const unsigned char * name, unsigned int len) {
static inline unsigned int full_name_hash(const unsigned char * name, size_t len) {
unsigned hash = 0;
while (len--) {
@@ -69,17 +54,14 @@ static inline unsigned int full_name_hash(const unsigned char * name, unsigned i
return hash;
}
#ifdef CYGOPT_FS_JFFS2_WRITE
#define jffs2_is_readonly(c) (0)
#else
#define jffs2_is_readonly(c) (1)
#endif
/* NAND flash not currently supported on eCos */
/* NAND flash not currently supported on RTEMS */
#define jffs2_can_mark_obsolete(c) (1)
#define JFFS2_INODE_INFO(i) (&(i)->jffs2_i)
#define OFNI_EDONI_2SFFJ(f) ((struct _inode *) ( ((char *)f) - ((char *)(&((struct _inode *)NULL)->jffs2_i)) ) )
#define ITIME(sec) (sec)
#define I_SEC(tv) (tv)
#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size)
#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
@@ -89,11 +71,7 @@ static inline unsigned int full_name_hash(const unsigned char * name, unsigned i
#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime)
#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime)
/* FIXME: eCos doesn't hav a concept of device major/minor numbers */
#define JFFS2_F_I_RDEV_MIN(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)&0xff)
#define JFFS2_F_I_RDEV_MAJ(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)>>8)
#define get_seconds cyg_timestamp
#define get_seconds() time(NULL)
struct _inode {
cyg_uint32 i_ino;
@@ -112,6 +90,7 @@ struct _inode {
off_t i_size; // For files only
// };
struct super_block * i_sb;
struct jffs2_full_dirent * i_fd;
struct jffs2_inode_info jffs2_i;
@@ -125,39 +104,30 @@ struct _inode {
struct super_block {
struct jffs2_sb_info jffs2_sb;
struct _inode * s_root;
unsigned long s_mount_count;
cyg_io_handle_t s_dev;
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
cyg_mutex_t s_lock; // Lock the inode cache
cyg_flag_t s_gc_thread_flags; // Communication with the gcthread
cyg_handle_t s_gc_thread_handle;
cyg_thread s_gc_thread;
#if (CYGNUM_JFFS2_GC_THREAD_STACK_SIZE >= CYGNUM_HAL_STACK_SIZE_MINIMUM)
char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE];
#else
char s_gc_thread_stack[CYGNUM_HAL_STACK_SIZE_MINIMUM];
#endif
cyg_mtab_entry *mte;
#endif
rtems_jffs2_flash_control *s_flash_control;
rtems_jffs2_compressor_control *s_compressor_control;
bool s_is_readonly;
unsigned char s_gc_buffer[PAGE_CACHE_SIZE]; // Avoids malloc when user may be under memory pressure
rtems_id s_mutex;
char s_name_buf[JFFS2_MAX_NAME_LEN];
};
#define sleep_on_spinunlock(wq, sl) spin_unlock(sl)
#define EBADFD 32767
/* background.c */
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
#else
static inline bool jffs2_is_readonly(struct jffs2_sb_info *c)
{
struct super_block *sb = OFNI_BS_2SFFJ(c);
return sb->s_is_readonly;
}
static inline void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
{
/* We don't have a GC thread in eCos (yet) */
/* We don't have a GC thread in RTEMS (yet) */
}
#endif
/* fs-ecos.c */
/* fs-rtems.c */
struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri);
struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino);
void jffs2_iput(struct _inode * i);
@@ -167,30 +137,37 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct jffs2_inode_i
unsigned long offset, unsigned long *priv);
void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv);
/* Avoid polluting eCos namespace with names not starting in jffs2_ */
/* Avoid polluting RTEMS namespace with names not starting in jffs2_ */
#define os_to_jffs2_mode(x) jffs2_from_os_mode(x)
uint32_t jffs2_from_os_mode(uint32_t osmode);
uint32_t jffs2_to_os_mode (uint32_t jmode);
static inline uint32_t jffs2_from_os_mode(uint32_t osmode)
{
return osmode & (S_IFMT | S_IRWXU | S_IRWXG | S_IRWXO);
}
static inline uint32_t jffs2_to_os_mode (uint32_t jmode)
{
return jmode & (S_IFMT | S_IRWXU | S_IRWXG | S_IRWXO);
}
/* flashio.c */
cyg_bool jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset,
int jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset,
const size_t size, size_t * return_size, unsigned char * write_buffer);
cyg_bool jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset,
int jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset,
const size_t size, size_t * return_size, unsigned char * read_buffer);
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
unsigned long count, loff_t to, size_t *retlen);
cyg_bool jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
int jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
// dir-ecos.c
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, int namelen);
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode, struct _inode **new_i);
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode);
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name);
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
struct _inode *new_dir_i, const unsigned char *new_d_name);
// dir-rtems.c
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, size_t namelen);
int jffs2_create(struct _inode *dir_i, const char *d_name, size_t d_namelen, int mode);
int jffs2_mknod(struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen, int mode, const unsigned char *data, size_t datalen);
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen);
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen);
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen);
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, size_t old_d_namelen,
struct _inode *new_dir_i, const unsigned char *new_d_name, size_t new_d_namelen);
/* erase.c */
static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
@@ -199,6 +176,7 @@ static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER
#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) )
#define jffs2_can_mark_obsolete(c) (1)
#define jffs2_is_writebuffered(c) (0)
#define jffs2_cleanmarker_oob(c) (0)
#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO)
@@ -223,4 +201,4 @@ static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
#define __init
#endif /* __JFFS2_OS_ECOS_H__ */
#endif /* __JFFS2_OS_RTEMS_H__ */
+7
View File
@@ -416,7 +416,14 @@ static void eat_last(struct rb_root *root, struct rb_node *node)
*link = node->rb_left;
if (node->rb_left)
#ifndef __rtems__
node->rb_left->__rb_parent_color = node->__rb_parent_color;
#else /* __rtems__ */
{
node->rb_left->rb_parent = node->rb_parent;
node->rb_left->rb_color = node->rb_color;
}
#endif /* __rtems__ */
}
/* We put the version tree in reverse order, so we can use the same eat_last()
+2 -1
View File
@@ -95,8 +95,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
unsigned char *flashbuf = NULL;
uint32_t buf_size = 0;
struct jffs2_summary *s = NULL; /* summary info collected by the scan process */
size_t try_size;
#ifndef __ECOS
size_t pointlen, try_size;
size_t pointlen;
ret = mtd_point(c->mtd, 0, c->mtd->size, &pointlen,
(void **)&flashbuf, NULL);
+4
View File
@@ -257,6 +257,10 @@ $(PROJECT_INCLUDE)/rtems/rfs/rtems-rfs-trace.h: libfs/src/rfs/rtems-rfs-trace.h
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rfs/rtems-rfs-trace.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rfs/rtems-rfs-trace.h
$(PROJECT_INCLUDE)/rtems/jffs2.h: libfs/src/jffs2/include/rtems/jffs2.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/jffs2.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/jffs2.h
$(PROJECT_INCLUDE)/rtems/bdbuf.h: libblock/include/rtems/bdbuf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bdbuf.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bdbuf.h
+18 -1
View File
@@ -237,6 +237,7 @@ const rtems_libio_helper rtems_fs_init_helper =
* CONFIGURE_FILESYSTEM_NFS - Network File System, networking enabled
* CONFIGURE_FILESYSTEM_DOSFS - DOS File System, uses libblock
* CONFIGURE_FILESYSTEM_RFS - RTEMS File System (RFS), uses libblock
* CONFIGURE_FILESYSTEM_JFFS2 - Journalling Flash File System, Version 2
*
* Combinations:
*
@@ -264,6 +265,7 @@ const rtems_libio_helper rtems_fs_init_helper =
#define CONFIGURE_FILESYSTEM_NFS
#define CONFIGURE_FILESYSTEM_DOSFS
#define CONFIGURE_FILESYSTEM_RFS
#define CONFIGURE_FILESYSTEM_JFFS2
#endif
/*
@@ -283,7 +285,8 @@ const rtems_libio_helper rtems_fs_init_helper =
defined(CONFIGURE_FILESYSTEM_FTPFS) || \
defined(CONFIGURE_FILESYSTEM_NFS) || \
defined(CONFIGURE_FILESYSTEM_DOSFS) || \
defined(CONFIGURE_FILESYSTEM_RFS)
defined(CONFIGURE_FILESYSTEM_RFS) || \
defined(CONFIGURE_FILESYSTEM_JFFS2)
#error "Configured filesystems but root filesystem was not IMFS!"
#error "Filesystems could be disabled, DEVFS is root, or"
#error " miniIMFS is root!"
@@ -440,6 +443,16 @@ const rtems_libio_helper rtems_fs_init_helper =
{ RTEMS_FILESYSTEM_TYPE_RFS, rtems_rfs_rtems_initialise }
#endif
/**
* JFFS2
*/
#if !defined(CONFIGURE_FILESYSTEM_ENTRY_JFFS2) && \
defined(CONFIGURE_FILESYSTEM_JFFS2)
#include <rtems/jffs2.h>
#define CONFIGURE_FILESYSTEM_ENTRY_JFFS2 \
{ RTEMS_FILESYSTEM_TYPE_JFFS2, rtems_jffs2_initialize }
#endif
#ifdef CONFIGURE_INIT
/**
@@ -513,6 +526,10 @@ const rtems_libio_helper rtems_fs_init_helper =
defined(CONFIGURE_FILESYSTEM_ENTRY_RFS)
CONFIGURE_FILESYSTEM_ENTRY_RFS,
#endif
#if defined(CONFIGURE_FILESYSTEM_JFFS2) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_JFFS2)
CONFIGURE_FILESYSTEM_ENTRY_JFFS2,
#endif
CONFIGURE_FILESYSTEM_NULL
};
#endif
+1
View File
@@ -27,6 +27,7 @@ TMP_LIBS += ../libfs/libdefaultfs.a
TMP_LIBS += ../libfs/libdevfs.a
TMP_LIBS += ../libfs/libimfs.a
TMP_LIBS += ../libfs/librfs.a
TMP_LIBS += ../libfs/libjffs2.a
TMP_LIBS += ../libmisc/libmonitor.a
TMP_LIBS += ../libmisc/libuntar.a