Changeset 3c96bee in rtems


Ignore:
Timestamp:
Sep 12, 2013, 1:32:07 PM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
0282e83
Parents:
78b85286
git-author:
Sebastian Huber <sebastian.huber@…> (09/12/13 13:32:07)
git-committer:
Sebastian Huber <sebastian.huber@…> (09/19/13 11:16:06)
Message:

JFFS2: Add RTEMS support

Location:
cpukit
Files:
1 added
23 edited

Legend:

Unmodified
Added
Removed
  • cpukit/Makefile.am

    r78b85286 r3c96bee  
    121121include_rtems_rfs_HEADERS += libfs/src/rfs/rtems-rfs-trace.h
    122122
     123# JFFS2
     124include_rtems_HEADERS += libfs/src/jffs2/include/rtems/jffs2.h
     125
    123126## libblock
    124127include_rtems_HEADERS += libblock/include/rtems/bdbuf.h
  • cpukit/libcsupport/include/rtems/libio.h

    r78b85286 r3c96bee  
    14381438#define RTEMS_FILESYSTEM_TYPE_DOSFS "dosfs"
    14391439#define RTEMS_FILESYSTEM_TYPE_RFS "rfs"
     1440#define RTEMS_FILESYSTEM_TYPE_JFFS2 "jffs2"
    14401441
    14411442/** @} */
  • cpukit/libfs/Makefile.am

    r78b85286 r3c96bee  
    103103    src/rfs/rtems-rfs-trace.c
    104104
     105# JFFS2
     106noinst_LIBRARIES += libjffs2.a
     107libjffs2_a_SOURCES =
     108libjffs2_a_SOURCES += src/jffs2/src/build.c
     109libjffs2_a_SOURCES += src/jffs2/src/compat-crc32.c
     110libjffs2_a_SOURCES += src/jffs2/src/compat-rbtree.c
     111libjffs2_a_SOURCES += src/jffs2/src/compr.c
     112libjffs2_a_SOURCES += src/jffs2/src/compr_rtime.c
     113libjffs2_a_SOURCES += src/jffs2/src/compr_zlib.c
     114libjffs2_a_SOURCES += src/jffs2/src/debug.c
     115libjffs2_a_SOURCES += src/jffs2/src/dir-rtems.c
     116libjffs2_a_SOURCES += src/jffs2/src/erase.c
     117libjffs2_a_SOURCES += src/jffs2/src/flashio.c
     118libjffs2_a_SOURCES += src/jffs2/src/fs-rtems.c
     119libjffs2_a_SOURCES += src/jffs2/src/gc.c
     120libjffs2_a_SOURCES += src/jffs2/src/malloc-rtems.c
     121libjffs2_a_SOURCES += src/jffs2/src/nodelist.c
     122libjffs2_a_SOURCES += src/jffs2/src/nodemgmt.c
     123libjffs2_a_SOURCES += src/jffs2/src/read.c
     124libjffs2_a_SOURCES += src/jffs2/src/readinode.c
     125libjffs2_a_SOURCES += src/jffs2/src/scan.c
     126libjffs2_a_SOURCES += src/jffs2/src/write.c
     127libjffs2_a_CFLAGS =
     128libjffs2_a_CFLAGS += -Wno-pointer-sign
     129libjffs2_a_CPPFLAGS =
     130libjffs2_a_CPPFLAGS += $(AM_CPPFLAGS) -I$(srcdir)/src/jffs2/include
     131libjffs2_a_CPPFLAGS += -D__ECOS
     132libjffs2_a_CPPFLAGS += '-DKBUILD_MODNAME="JFFS2"'
     133
    105134# ---
    106135include $(srcdir)/preinstall.am
  • cpukit/libfs/src/jffs2/include/cyg/infra/cyg_type.h

    r78b85286 r3c96bee  
    5656
    5757#include <stddef.h>           // Definition of NULL from the compiler
     58#include <stdint.h>
    5859
    59 // -------------------------------------------------------------------------
    60 // Some useful macros. These are defined here by default.
     60typedef uint16_t cyg_uint16;
    6161
    62 // __externC is used in mixed C/C++ headers to force C linkage on an external
    63 // definition. It avoids having to put all sorts of ifdefs in.
    64 
    65 #ifdef __cplusplus
    66 # define __externC extern "C"
    67 #else
    68 # define __externC extern
    69 #endif
    70 // Also define externC for now - but it is deprecated
    71 #define externC __externC
    72 
    73 // Compiler version.
    74 #ifdef __GNUC__
    75 # if defined(__GNU_PATCHLEVEL__)
    76 #  define __GNUC_VERSION__ (__GNUC__ * 10000 \
    77                              + __GNUC_MINOR__ * 100 \
    78                              + __GNUC_PATCHLEVEL__)
    79 # else
    80 #  define __GNUC_VERSION__ (__GNUC__ * 10000 \
    81                              + __GNUC_MINOR__ * 100)
    82 # endif
    83 #endif
    84 
    85 // -------------------------------------------------------------------------
    86 // The header <basetype.h> defines the base types used here. It is
    87 // supplied either by the target architecture HAL, or by the host
    88 // porting kit. They are all defined as macros, and only those that
    89 // make choices other than the defaults given below need be defined.
    90 
    91 #define CYG_LSBFIRST 1234
    92 #define CYG_MSBFIRST 4321
    93 
    94 #include <cyg/hal/basetype.h>
    95 
    96 #if (CYG_BYTEORDER != CYG_LSBFIRST) && (CYG_BYTEORDER != CYG_MSBFIRST)
    97 # error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
    98 #endif
    99 
    100 #ifndef CYG_DOUBLE_BYTEORDER
    101 #define CYG_DOUBLE_BYTEORDER CYG_BYTEORDER
    102 #endif
    103 
    104 #ifndef cyg_halint8
    105 # define cyg_halint8 char
    106 #endif
    107 #ifndef cyg_halint16
    108 # define cyg_halint16 short
    109 #endif
    110 #ifndef cyg_halint32
    111 # define cyg_halint32 int
    112 #endif
    113 #ifndef cyg_halint64
    114 # define cyg_halint64 long long
    115 #endif
    116 
    117 #ifndef cyg_halcount8
    118 # define cyg_halcount8 int
    119 #endif
    120 #ifndef cyg_halcount16
    121 # define cyg_halcount16 int
    122 #endif
    123 #ifndef cyg_halcount32
    124 # define cyg_halcount32 int
    125 #endif
    126 #ifndef cyg_halcount64
    127 # define cyg_halcount64 long long
    128 #endif
    129 
    130 #ifndef cyg_haladdress
    131 # define cyg_haladdress cyg_uint32
    132 #endif
    133 #ifndef cyg_haladdrword
    134 # define cyg_haladdrword cyg_uint32
    135 #endif
    136 
    137 #ifndef cyg_halbool
    138 # define cyg_halbool int
    139 #endif
    140 
    141 #ifndef cyg_halatomic
    142 # define cyg_halatomic cyg_halint8
    143 #endif
    144 
    145 // -------------------------------------------------------------------------
    146 // Provide a default architecture alignment
    147 // This may be overridden in basetype.h if necessary.
    148 // These should be straightforward numbers to allow use in assembly.
    149 
    150 #ifndef CYGARC_ALIGNMENT
    151 # define CYGARC_ALIGNMENT 8
    152 #endif
    153 // And corresponding power of two alignment
    154 #ifndef CYGARC_P2ALIGNMENT
    155 # define CYGARC_P2ALIGNMENT 3
    156 #endif
    157 #if (CYGARC_ALIGNMENT) != (1 << CYGARC_P2ALIGNMENT)
    158 # error "Inconsistent CYGARC_ALIGNMENT and CYGARC_P2ALIGNMENT values"
    159 #endif
    160 
    161 // -------------------------------------------------------------------------
    162 // The obvious few that compilers may define for you.
    163 // But in case they don't:
    164 
    165 #ifndef NULL
    166 # define NULL 0
    167 #endif
    168 
    169 #ifndef __cplusplus
    170 
    171 typedef cyg_halbool bool;
    172 
    173 # ifndef false
    174 #  define false 0
    175 # endif
    176 
    177 # ifndef true
    178 #  define true (!false)
    179 # endif
    180 
    181 #endif
     62typedef uint32_t cyg_uint32;
    18263
    18364// -------------------------------------------------------------------------
     
    19677CYG_MACRO_END
    19778
    198 
    199 //----------------------------------------------------------------------------
    200 // The unused attribute stops the compiler warning about the variable
    201 // not being used.
    202 // The used attribute prevents the compiler from optimizing it away.
    203 
    204 #define CYG_REFERENCE_OBJECT(__object__)                            \
    205     CYG_MACRO_START                                                 \
    206     static const void*  __cygvar_discard_me__                       \
    207     __attribute__ ((unused, used)) = (const void*)&(__object__);    \
    208     CYG_MACRO_END
    209 
    210 // -------------------------------------------------------------------------
    211 // Define basic types for using integers in memory and structures;
    212 // depends on compiler defaults and CPU type.
    213 
    214 typedef unsigned cyg_halint8    cyg_uint8  ;
    215 typedef   signed cyg_halint8    cyg_int8   ;
    216 
    217 typedef unsigned cyg_halint16   cyg_uint16 ;
    218 typedef   signed cyg_halint16   cyg_int16  ;
    219 
    220 typedef unsigned cyg_halint32   cyg_uint32 ;
    221 typedef   signed cyg_halint32   cyg_int32  ;
    222 
    223 typedef unsigned cyg_halint64   cyg_uint64 ;
    224 typedef   signed cyg_halint64   cyg_int64  ;
    225 
    226 typedef  cyg_halbool            cyg_bool   ;
    227 
    228 // -------------------------------------------------------------------------
    229 // Define types for using integers in registers for looping and the like;
    230 // depends on CPU type, choose what it is most comfortable with, with at
    231 // least the range required.
    232 
    233 typedef unsigned cyg_halcount8  cyg_ucount8  ;
    234 typedef   signed cyg_halcount8  cyg_count8   ;
    235 
    236 typedef unsigned cyg_halcount16 cyg_ucount16 ;
    237 typedef   signed cyg_halcount16 cyg_count16  ;
    238 
    239 typedef unsigned cyg_halcount32 cyg_ucount32 ;
    240 typedef   signed cyg_halcount32 cyg_count32  ;
    241 
    242 typedef unsigned cyg_halcount64 cyg_ucount64 ;
    243 typedef   signed cyg_halcount64 cyg_count64  ;
    244 
    245 // -------------------------------------------------------------------------
    246 // Define a type to be used for atomic accesses. This type is guaranteed
    247 // to be read or written in a single uninterruptible operation. This type
    248 // is at least a single byte.
    249 
    250 typedef volatile unsigned cyg_halatomic  cyg_atomic;
    251 typedef volatile unsigned cyg_halatomic  CYG_ATOMIC;
    252 
    253 // -------------------------------------------------------------------------
    254 // Define types for access plain, on-the-metal memory or devices.
    255 
    256 typedef cyg_uint32  CYG_WORD;
    257 typedef cyg_uint8   CYG_BYTE;
    258 typedef cyg_uint16  CYG_WORD16;
    259 typedef cyg_uint32  CYG_WORD32;
    260 typedef cyg_uint64  CYG_WORD64;
    261 
    262 typedef cyg_haladdress  CYG_ADDRESS;
    263 typedef cyg_haladdrword CYG_ADDRWORD;
    264 
    265 // -------------------------------------------------------------------------
    266 // Number of elements in a (statically allocated) array.
    267 
    268 #define CYG_NELEM(a) (sizeof(a) / sizeof((a)[0]))
    269 
    270 // -------------------------------------------------------------------------
    271 // Constructor ordering macros.  These are added as annotations to all
    272 // static objects to order the constuctors appropriately.
    273 
    274 #if defined(__cplusplus) && defined(__GNUC__) && \
    275     !defined(CYGBLD_ATTRIB_INIT_PRI)
    276 # define CYGBLD_ATTRIB_INIT_PRI( _pri_ ) __attribute__((init_priority(_pri_)))
    277 #elif !defined(CYGBLD_ATTRIB_INIT_PRI)
    278 // FIXME: should maybe just bomb out if this is attempted anywhere else?
    279 // Not sure
    280 # define CYGBLD_ATTRIB_INIT_PRI( _pri_ )
    281 #endif
    282    
    283 // The following will be removed eventually as it doesn't allow the use of
    284 // e.g. pri+5 format
    285 #define CYG_INIT_PRIORITY( _pri_ ) CYGBLD_ATTRIB_INIT_PRI( CYG_INIT_##_pri_ )
    286 
    287 #define CYGBLD_ATTRIB_INIT_BEFORE( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_-100)
    288 #define CYGBLD_ATTRIB_INIT_AFTER( _pri_ )  CYGBLD_ATTRIB_INIT_PRI(_pri_+100)
    289 
    290 #if defined(__GNUC__) && !defined(__cplusplus) && (__GNUC_VERSION__ >= 40300)
    291 // Equivalents of the above for C functions, available from gcc 4.3 onwards.
    292 # define CYGBLD_ATTRIB_C_INIT_PRI( _pri_)       __attribute__((constructor (_pri_)))
    293 # define CYGBLD_ATTRIB_C_INIT_BEFORE( _pri_ )   __attribute__((constructor (_pri_-100)))
    294 # define CYGBLD_ATTRIB_C_INIT_AFTER( _pri_ )    __attribute__((constructor (_pri_+100)))
    295 #endif
    296 
    297 // Start with initializing everything inside the cpu and the main memory.
    298 #define CYG_INIT_HAL                    10000
    299 #define CYG_INIT_SCHEDULER              11000
    300 #define CYG_INIT_IDLE_THREAD            11100
    301 #define CYG_INIT_INTERRUPTS             12000
    302 #define CYG_INIT_CLOCK                  14000
    303 #define CYG_INIT_THREADS                16000
    304 #define CYG_INIT_KERNEL                 19000
    305 #define CYG_INIT_MEMALLOC               20000
    306 // Now move on to I/O subsystems and device drivers. These can make use of
    307 // kernel and HAL functionality, and can dynamically allocate memory if
    308 // absolutely needed. For now they can also assume that diag_printf()
    309 // functionality is available, but that may change in future.
    310 //
    311 // Primary buses are ones very closely tied to the processor, e.g. PCI.
    312 #define CYG_INIT_BUS_PRIMARY            30000
    313 // Not yet: on some targets cyg_pci_init() has to be called very early
    314 // on for HAL diagnostics to work.
    315 // #define CYG_INIT_BUS_PCI                CYG_INIT_BUS_PRIMARY
    316 //
    317 // Secondary buses may hang off primary buses, e.g. USB host.
    318 #define CYG_INIT_BUS_SECONDARY          31000
    319 // Tertiary buses are everything else.
    320 #define CYG_INIT_BUS_TERTIARY           32000
    321 #define CYG_INIT_BUS_I2C                CYG_INIT_BUS_TERTIARY
    322 #define CYG_INIT_BUS_SPI                CYG_INIT_BUS_TERTIARY
    323 //
    324 // In future HAL diag initialization may happen at this point.
    325 //
    326 // Watchdogs and wallclocks often hang off a tertiary bus but
    327 // have no dependencies
    328 #define CYG_INIT_DEV_WATCHDOG           35000
    329 #define CYG_INIT_DEV_WALLCLOCK          36000
    330 // A primary block configuration can be initialized with no need
    331 // for per-unit configuration information.
    332 #define CYG_INIT_DEV_BLOCK_PRIMARY      37000
    333 #define CYG_INIT_DEV_FLASH              CYG_INIT_DEV_BLOCK_PRIMARY
    334 // Per-unit configuration data extracted from primary storage.
    335 // NOTE: for future use, not implemented yet.
    336 #define CYG_INIT_CONFIG                 38000
    337 // Secondary block devices may use per-unit configuration data
    338 // for e.g. interpreting partition layout. Few devices are expected
    339 // to fall into this category. Note that these devices, as well as
    340 // some char devices, may not actually be usable until interrupts
    341 // are enabled.
    342 #define CYG_INIT_DEV_BLOCK_SECONDARY    40000
    343 // Char devices are everything else: serial, ethernet, CAN, ...
    344 #define CYG_INIT_DEV_CHAR               41000
    345 // For backwards compatibility. Subject to change in future so
    346 // a CYG_INIT_DEV_ priority should be used instead.
    347 #define CYG_INIT_DRIVERS                48000
    348 // CYG_INIT_IO and CYG_INIT_IO_FS are poorly defined at present,
    349 // and may get reorganized in future.
    350 #define CYG_INIT_IO                     49000
    351 #define CYG_INIT_IO_FS                  50000
    352 // The I/O subsystems and device drivers have been initialized.
    353 #define CYG_INIT_LIBC                   56000
    354 #define CYG_INIT_COMPAT                 58000
    355 #define CYG_INIT_APPLICATION            60000
    356 #define CYG_INIT_PREDEFAULT             65534
    357 #define CYG_INIT_DEFAULT                65535
    358 
    359 // -------------------------------------------------------------------------
    360 // Label name macros. Some toolsets generate labels with initial
    361 // underscores and others don't. CYG_LABEL_NAME should be used on
    362 // labels in C/C++ code that are defined in assembly code or linker
    363 // scripts. CYG_LABEL_DEFN is for use in assembly code and linker
    364 // scripts where we need to manufacture labels that can be used from
    365 // C/C++.
    366 // These are default implementations that should work for most targets.
    367 // They may be overridden in basetype.h if necessary.
    368 
    369 #ifndef CYG_LABEL_NAME
    370 
    371 #define CYG_LABEL_NAME(_name_) _name_
    372 
    373 #endif
    374 
    375 #ifndef CYG_LABEL_DEFN
    376 
    377 #define CYG_LABEL_DEFN(_label) _label
    378 
    379 #endif
    380 
    381 // -------------------------------------------------------------------------
    382 // COMPILER-SPECIFIC STUFF
    383 
    384 #ifdef __GNUC__
    385 // Force a 'C' routine to be called like a 'C++' contructor
    386 # if !defined(CYGBLD_ATTRIB_CONSTRUCTOR)
    387 #  define CYGBLD_ATTRIB_CONSTRUCTOR __attribute__((constructor))
    388 # endif
    389 
    390 // Define a compiler-specific rune for saying a function doesn't return
    391 # if !defined(CYGBLD_ATTRIB_NORET)
    392 #  define CYGBLD_ATTRIB_NORET __attribute__((noreturn))
    393 # endif
    394 
    395 // How to define weak symbols - this is only relevant for ELF and a.out,
    396 // but that won't be a problem for eCos
    397 # if !defined(CYGBLD_ATTRIB_WEAK)
    398 #  define CYGBLD_ATTRIB_WEAK __attribute__ ((weak))
    399 # endif
    400 
    401 // How to define alias to symbols. Just pass in the symbol itself, not
    402 // the string name of the symbol
    403 # if !defined(CYGBLD_ATTRIB_ALIAS)
    404 #  define CYGBLD_ATTRIB_ALIAS(__symbol__) \
    405         __attribute__ ((alias (#__symbol__)))
    406 # endif
    407 
    408 // This effectively does the reverse of the previous macro. It defines
    409 // a name that the attributed variable or function will actually have
    410 // in assembler.
    411 # if !defined(CYGBLD_ATTRIB_ASM_ALIAS)
    412 #  define __Str(x) #x
    413 #  define __Xstr(x) __Str(x)
    414 #  define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) \
    415              __asm__ ( __Xstr( CYG_LABEL_DEFN( __symbol__ ) ) )
    416 # endif
    417 
    418 // Shows that a function returns the same value when given the same args, but
    419 // note this can't be used if there are pointer args
    420 # if !defined(CYGBLD_ATTRIB_CONST)
    421 #  define CYGBLD_ATTRIB_CONST __attribute__((const))
    422 #endif
    423 
    424 // Assign a defined variable to a specific section
    425 # if !defined(CYGBLD_ATTRIB_SECTION)
    426 #  define CYGBLD_ATTRIB_SECTION(__sect__) __attribute__((section (__sect__)))
    427 # endif
    428 
    429 // Give a type or object explicit minimum alignment
    430 # if !defined(CYGBLD_ATTRIB_ALIGN)
    431 #  define CYGBLD_ATTRIB_ALIGN(__align__) __attribute__((aligned(__align__)))
    432 # endif
    433 
    434 # if !defined(CYGBLD_ATTRIB_ALIGN_MAX)
    435 #  define CYGBLD_ATTRIB_ALIGN_MAX __attribute__((aligned))
    436 # endif
    437 
    438 # if !defined(CYGBLD_ATTRIB_ALIGNOFTYPE)
    439 #  define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) \
    440      __attribute__((aligned(__alignof__( _type_ ))))
    441 # endif
    442 
    443 // Teach compiler how to check format of printf-like functions
    444 # define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__) \
    445         __attribute__((format (printf, __format__, __args__)))
    446 
    447 // Teach compiler how to check format of scanf-like functions
    448 # define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__) \
    449         __attribute__((format (scanf, __format__, __args__)))
    450 
    451 // Teach compiler how to check format of strftime-like functions
    452 # define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__) \
    453         __attribute__((format (strftime, __format__, __args__)))
    454 
    455 // Tell compiler not to warn us about an unused variable -- generally
    456 // because it will be used when sources are build under certain
    457 // circumstances (e.g. with debugging or asserts enabled.
    458 # define CYGBLD_ATTRIB_UNUSED  __attribute__((unused))
    459 
    460 // Tell the compiler not to throw away a variable or function. Only known
    461 // available on 3.3.2 or above. Old version's didn't throw them away,
    462 // but using the unused attribute should stop warnings.
    463 # if !defined(CYGBLD_ATTRIB_USED)
    464 #  if __GNUC_VERSION__ >= 30302
    465 #   define CYGBLD_ATTRIB_USED __attribute__((used))
    466 #  else
    467 #   define CYGBLD_ATTRIB_USED __attribute__((unused))
    468 #  endif
    469 # endif
    470 
    471 // Enforce inlining of a C function. GCC does not inline any C
    472 // function when not optimizing, unless you specify "always_inline" attribute.
    473 // Other attributes suppress generation of standalone function.
    474 # if !defined(CYGBLD_FORCE_INLINE)
    475 #  define CYGBLD_FORCE_INLINE __externC inline __attribute((gnu_inline)) __attribute((always_inline))
    476 # endif
    477 
    478 // Suppress function inlining
    479 #define CYGBLD_ATTRIB_NO_INLINE __attribute__((noinline))
    480 
    481 #else // non-GNU
    482 
    483 # define CYGBLD_ATTRIB_UNUSED  /* nothing */
    484 
    485 # define CYGBLD_ATTRIB_CONSTRUCTOR
    486 
    487 # define CYGBLD_ATTRIB_NORET
    488     // This intentionally gives an error only if we actually try to
    489     // use it.  #error would give an error if we simply can't.
    490 // FIXME: Had to disarm the bomb - the CYGBLD_ATTRIB_WEAK macro is now
    491 //        (indirectly) used in host tools.
    492 # define CYGBLD_ATTRIB_WEAK /* !!!-- Attribute weak not defined --!!! */
    493 
    494 # define CYGBLD_ATTRIB_ALIAS(__x__) !!!-- Attribute alias not defined --!!!
    495 
    496 # define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) !!!-- Asm alias not defined --!!!
    497 
    498 # define CYGBLD_ATTRIB_CONST
    499 
    500 # define CYGBLD_ATTRIB_ALIGN(__align__) !!!-- Alignment alias not defined --!!!
    501 
    502 # define CYGBLD_ATTRIB_ALIGN_MAX !!!-- Alignment alias not defined --!!!
    503 
    504 # define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) !!!-- Alignment alias not defined --!!!
    505 
    506 # define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__)
    507 
    508 # define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__)
    509 
    510 # define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__)
    511 
    512 #define CYGBLD_FORCE_INLINE
    513 
    514 #define CYGBLD_ATTRIB_NO_INLINE
    515 
    516 #endif
    517 
    518 // How to define weak aliases. Currently this is simply a mixture of the
    519 // above
    520 
    521 # define CYGBLD_ATTRIB_WEAK_ALIAS(__symbol__) \
    522         CYGBLD_ATTRIB_WEAK CYGBLD_ATTRIB_ALIAS(__symbol__)
    523 
    524 #ifdef __cplusplus
    525 # define __THROW throw()
    526 #else
    527 # define __THROW
    528 #endif
    529 
    530 // -------------------------------------------------------------------------
    531 // Variable annotations
    532 // These annotations may be added to various static variables in the
    533 // HAL and kernel to indicate which component they belong to. These
    534 // are used by some targets to optimize memory placement of these
    535 // variables.
    536 
    537 #ifndef CYGBLD_ANNOTATE_VARIABLE_HAL
    538 #define CYGBLD_ANNOTATE_VARIABLE_HAL
    539 #endif
    540 #ifndef CYGBLD_ANNOTATE_VARIABLE_SCHED
    541 #define CYGBLD_ANNOTATE_VARIABLE_SCHED
    542 #endif
    543 #ifndef CYGBLD_ANNOTATE_VARIABLE_CLOCK
    544 #define CYGBLD_ANNOTATE_VARIABLE_CLOCK
    545 #endif
    546 #ifndef CYGBLD_ANNOTATE_VARIABLE_INTR
    547 #define CYGBLD_ANNOTATE_VARIABLE_INTR
    548 #endif
    549 
    550 // -------------------------------------------------------------------------
    551 // Various "flavours" of memory regions that can be described by the
    552 // Memory Layout Tool (MLT).
    553 
    554 #define CYGMEM_REGION_ATTR_R  0x01  // Region can be read
    555 #define CYGMEM_REGION_ATTR_W  0x02  // Region can be written
    556 
    55779// -------------------------------------------------------------------------
    55880#endif // CYGONCE_INFRA_CYG_TYPE_H multiple inclusion protection
  • cpukit/libfs/src/jffs2/src/compr.c

    r78b85286 r3c96bee  
    66 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
    77 *                  University of Szeged, Hungary
     8 * Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
    89 *
    910 * Created by Arjan van de Ven <arjan@infradead.org>
     
    1617
    1718#include "compr.h"
    18 
    19 static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
    20 
    21 /* Available compressors are on this list */
    22 static LIST_HEAD(jffs2_compressor_list);
    23 
    24 /* Actual compression mode */
    25 static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
    26 
    27 /* Statistics for blocks stored without compression */
    28 static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
    29 
    30 
    31 /*
    32  * Return 1 to use this compression
    33  */
    34 static int jffs2_is_best_compression(struct jffs2_compressor *this,
    35                 struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
    36 {
    37         switch (jffs2_compression_mode) {
    38         case JFFS2_COMPR_MODE_SIZE:
    39                 if (bestsize > size)
    40                         return 1;
    41                 return 0;
    42         case JFFS2_COMPR_MODE_FAVOURLZO:
    43                 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
    44                         return 1;
    45                 if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
    46                         return 1;
    47                 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
    48                         return 1;
    49                 if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
    50                         return 1;
    51 
    52                 return 0;
    53         }
    54         /* Shouldn't happen */
    55         return 0;
    56 }
    57 
    58 /*
    59  * jffs2_selected_compress:
    60  * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
    61  *      If 0, just take the first available compression mode.
    62  * @data_in: Pointer to uncompressed data
    63  * @cpage_out: Pointer to returned pointer to buffer for compressed data
    64  * @datalen: On entry, holds the amount of data available for compression.
    65  *      On exit, expected to hold the amount of data actually compressed.
    66  * @cdatalen: On entry, holds the amount of space available for compressed
    67  *      data. On exit, expected to hold the actual size of the compressed
    68  *      data.
    69  *
    70  * Returns: the compression type used.  Zero is used to show that the data
    71  * could not be compressed; probably because we couldn't find the requested
    72  * compression mode.
    73  */
    74 static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
    75                 unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
    76 {
    77         struct jffs2_compressor *this;
    78         int err, ret = JFFS2_COMPR_NONE;
    79         uint32_t orig_slen, orig_dlen;
    80         char *output_buf;
    81 
    82         output_buf = kmalloc(*cdatalen, GFP_KERNEL);
    83         if (!output_buf) {
    84                 pr_warn("No memory for compressor allocation. Compression failed.\n");
    85                 return ret;
    86         }
    87         orig_slen = *datalen;
    88         orig_dlen = *cdatalen;
    89         spin_lock(&jffs2_compressor_list_lock);
    90         list_for_each_entry(this, &jffs2_compressor_list, list) {
    91                 /* Skip decompress-only and disabled modules */
    92                 if (!this->compress || this->disabled)
    93                         continue;
    94 
    95                 /* Skip if not the desired compression type */
    96                 if (compr && (compr != this->compr))
    97                         continue;
    98 
    99                 /*
    100                  * Either compression type was unspecified, or we found our
    101                  * compressor; either way, we're good to go.
    102                  */
    103                 this->usecount++;
    104                 spin_unlock(&jffs2_compressor_list_lock);
    105 
    106                 *datalen  = orig_slen;
    107                 *cdatalen = orig_dlen;
    108                 err = this->compress(data_in, output_buf, datalen, cdatalen);
    109 
    110                 spin_lock(&jffs2_compressor_list_lock);
    111                 this->usecount--;
    112                 if (!err) {
    113                         /* Success */
    114                         ret = this->compr;
    115                         this->stat_compr_blocks++;
    116                         this->stat_compr_orig_size += *datalen;
    117                         this->stat_compr_new_size += *cdatalen;
    118                         break;
    119                 }
    120         }
    121         spin_unlock(&jffs2_compressor_list_lock);
    122         if (ret == JFFS2_COMPR_NONE)
    123                 kfree(output_buf);
    124         else
    125                 *cpage_out = output_buf;
    126 
    127         return ret;
    128 }
    12919
    13020/* jffs2_compress:
     
    15040                        uint32_t *datalen, uint32_t *cdatalen)
    15141{
    152         int ret = JFFS2_COMPR_NONE;
    153         int mode, compr_ret;
    154         struct jffs2_compressor *this, *best=NULL;
    155         unsigned char *output_buf = NULL, *tmp_buf;
    156         uint32_t orig_slen, orig_dlen;
    157         uint32_t best_slen=0, best_dlen=0;
     42        struct super_block *sb = OFNI_BS_2SFFJ(c);
     43        rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
     44        int ret;
    15845
    159         if (c->mount_opts.override_compr)
    160                 mode = c->mount_opts.compr;
    161         else
    162                 mode = jffs2_compression_mode;
    163 
    164         switch (mode) {
    165         case JFFS2_COMPR_MODE_NONE:
    166                 break;
    167         case JFFS2_COMPR_MODE_PRIORITY:
    168                 ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
    169                                 cdatalen);
    170                 break;
    171         case JFFS2_COMPR_MODE_SIZE:
    172         case JFFS2_COMPR_MODE_FAVOURLZO:
    173                 orig_slen = *datalen;
    174                 orig_dlen = *cdatalen;
    175                 spin_lock(&jffs2_compressor_list_lock);
    176                 list_for_each_entry(this, &jffs2_compressor_list, list) {
    177                         /* Skip decompress-only backwards-compatibility and disabled modules */
    178                         if ((!this->compress)||(this->disabled))
    179                                 continue;
    180                         /* Allocating memory for output buffer if necessary */
    181                         if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
    182                                 spin_unlock(&jffs2_compressor_list_lock);
    183                                 kfree(this->compr_buf);
    184                                 spin_lock(&jffs2_compressor_list_lock);
    185                                 this->compr_buf_size=0;
    186                                 this->compr_buf=NULL;
    187                         }
    188                         if (!this->compr_buf) {
    189                                 spin_unlock(&jffs2_compressor_list_lock);
    190                                 tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
    191                                 spin_lock(&jffs2_compressor_list_lock);
    192                                 if (!tmp_buf) {
    193                                         pr_warn("No memory for compressor allocation. (%d bytes)\n",
    194                                                 orig_slen);
    195                                         continue;
    196                                 }
    197                                 else {
    198                                         this->compr_buf = tmp_buf;
    199                                         this->compr_buf_size = orig_slen;
    200                                 }
    201                         }
    202                         this->usecount++;
    203                         spin_unlock(&jffs2_compressor_list_lock);
    204                         *datalen  = orig_slen;
    205                         *cdatalen = orig_dlen;
    206                         compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
    207                         spin_lock(&jffs2_compressor_list_lock);
    208                         this->usecount--;
    209                         if (!compr_ret) {
    210                                 if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
    211                                                 && (*cdatalen < *datalen)) {
    212                                         best_dlen = *cdatalen;
    213                                         best_slen = *datalen;
    214                                         best = this;
    215                                 }
    216                         }
    217                 }
    218                 if (best_dlen) {
    219                         *cdatalen = best_dlen;
    220                         *datalen  = best_slen;
    221                         output_buf = best->compr_buf;
    222                         best->compr_buf = NULL;
    223                         best->compr_buf_size = 0;
    224                         best->stat_compr_blocks++;
    225                         best->stat_compr_orig_size += best_slen;
    226                         best->stat_compr_new_size  += best_dlen;
    227                         ret = best->compr;
    228                         *cpage_out = output_buf;
    229                 }
    230                 spin_unlock(&jffs2_compressor_list_lock);
    231                 break;
    232         case JFFS2_COMPR_MODE_FORCELZO:
    233                 ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
    234                                 cpage_out, datalen, cdatalen);
    235                 break;
    236         case JFFS2_COMPR_MODE_FORCEZLIB:
    237                 ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
    238                                 cpage_out, datalen, cdatalen);
    239                 break;
    240         default:
    241                 pr_err("unknown compression mode\n");
     46        if (cc != NULL) {
     47                *cpage_out = &cc->buffer[0];
     48                ret = (*cc->compress)(cc, data_in, *cpage_out, datalen, cdatalen);
     49        } else {
     50                ret = JFFS2_COMPR_NONE;
    24251        }
    24352
     
    24554                *cpage_out = data_in;
    24655                *datalen = *cdatalen;
    247                 none_stat_compr_blocks++;
    248                 none_stat_compr_size += *datalen;
    24956        }
    25057        return ret;
     
    25562                     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
    25663{
    257         struct jffs2_compressor *this;
    258         int ret;
     64        struct super_block *sb = OFNI_BS_2SFFJ(c);
     65        rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
    25966
    26067        /* Older code had a bug where it would write non-zero 'usercompr'
     
    26774                /* This should be special-cased elsewhere, but we might as well deal with it */
    26875                memcpy(data_out, cdata_in, datalen);
    269                 none_stat_decompr_blocks++;
    27076                break;
    27177        case JFFS2_COMPR_ZERO:
     
    27379                break;
    27480        default:
    275                 spin_lock(&jffs2_compressor_list_lock);
    276                 list_for_each_entry(this, &jffs2_compressor_list, list) {
    277                         if (comprtype == this->compr) {
    278                                 this->usecount++;
    279                                 spin_unlock(&jffs2_compressor_list_lock);
    280                                 ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
    281                                 spin_lock(&jffs2_compressor_list_lock);
    282                                 if (ret) {
    283                                         pr_warn("Decompressor \"%s\" returned %d\n",
    284                                                 this->name, ret);
    285                                 }
    286                                 else {
    287                                         this->stat_decompr_blocks++;
    288                                 }
    289                                 this->usecount--;
    290                                 spin_unlock(&jffs2_compressor_list_lock);
    291                                 return ret;
    292                         }
     81                if (cc != NULL) {
     82                        return (*cc->decompress)(cc, comprtype, cdata_in, data_out, cdatalen, datalen);
     83                } else {
     84                        return -EIO;
    29385                }
    294                 pr_warn("compression type 0x%02x not available\n", comprtype);
    295                 spin_unlock(&jffs2_compressor_list_lock);
    296                 return -EIO;
    29786        }
    29887        return 0;
    29988}
    300 
    301 int jffs2_register_compressor(struct jffs2_compressor *comp)
    302 {
    303         struct jffs2_compressor *this;
    304 
    305         if (!comp->name) {
    306                 pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
    307                 return -1;
    308         }
    309         comp->compr_buf_size=0;
    310         comp->compr_buf=NULL;
    311         comp->usecount=0;
    312         comp->stat_compr_orig_size=0;
    313         comp->stat_compr_new_size=0;
    314         comp->stat_compr_blocks=0;
    315         comp->stat_decompr_blocks=0;
    316         jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
    317 
    318         spin_lock(&jffs2_compressor_list_lock);
    319 
    320         list_for_each_entry(this, &jffs2_compressor_list, list) {
    321                 if (this->priority < comp->priority) {
    322                         list_add(&comp->list, this->list.prev);
    323                         goto out;
    324                 }
    325         }
    326         list_add_tail(&comp->list, &jffs2_compressor_list);
    327 out:
    328         D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
    329                 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
    330         })
    331 
    332         spin_unlock(&jffs2_compressor_list_lock);
    333 
    334         return 0;
    335 }
    336 
    337 int jffs2_unregister_compressor(struct jffs2_compressor *comp)
    338 {
    339         D2(struct jffs2_compressor *this);
    340 
    341         jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
    342 
    343         spin_lock(&jffs2_compressor_list_lock);
    344 
    345         if (comp->usecount) {
    346                 spin_unlock(&jffs2_compressor_list_lock);
    347                 pr_warn("Compressor module is in use. Unregister failed.\n");
    348                 return -1;
    349         }
    350         list_del(&comp->list);
    351 
    352         D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
    353                 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
    354         })
    355         spin_unlock(&jffs2_compressor_list_lock);
    356         return 0;
    357 }
    358 
    359 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
    360 {
    361         if (orig != comprbuf)
    362                 kfree(comprbuf);
    363 }
    364 
    365 int __init jffs2_compressors_init(void)
    366 {
    367 /* Registering compressors */
    368 #ifdef CONFIG_JFFS2_ZLIB
    369         jffs2_zlib_init();
    370 #endif
    371 #ifdef CONFIG_JFFS2_RTIME
    372         jffs2_rtime_init();
    373 #endif
    374 #ifdef CONFIG_JFFS2_RUBIN
    375         jffs2_rubinmips_init();
    376         jffs2_dynrubin_init();
    377 #endif
    378 #ifdef CONFIG_JFFS2_LZO
    379         jffs2_lzo_init();
    380 #endif
    381 /* Setting default compression mode */
    382 #ifdef CONFIG_JFFS2_CMODE_NONE
    383         jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
    384         jffs2_dbg(1, "default compression mode: none\n");
    385 #else
    386 #ifdef CONFIG_JFFS2_CMODE_SIZE
    387         jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
    388         jffs2_dbg(1, "default compression mode: size\n");
    389 #else
    390 #ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
    391         jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
    392         jffs2_dbg(1, "default compression mode: favourlzo\n");
    393 #else
    394         jffs2_dbg(1, "default compression mode: priority\n");
    395 #endif
    396 #endif
    397 #endif
    398         return 0;
    399 }
    400 
    401 int jffs2_compressors_exit(void)
    402 {
    403 /* Unregistering compressors */
    404 #ifdef CONFIG_JFFS2_LZO
    405         jffs2_lzo_exit();
    406 #endif
    407 #ifdef CONFIG_JFFS2_RUBIN
    408         jffs2_dynrubin_exit();
    409         jffs2_rubinmips_exit();
    410 #endif
    411 #ifdef CONFIG_JFFS2_RTIME
    412         jffs2_rtime_exit();
    413 #endif
    414 #ifdef CONFIG_JFFS2_ZLIB
    415         jffs2_zlib_exit();
    416 #endif
    417         return 0;
    418 }
  • cpukit/libfs/src/jffs2/src/compr.h

    r78b85286 r3c96bee  
    7979                     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
    8080
    81 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
     81#define jffs2_free_comprbuf(x, y) do { } while (0)
    8282
    8383/* Compressor modules */
  • cpukit/libfs/src/jffs2/src/compr_rtime.c

    r78b85286 r3c96bee  
    2929#include "compr.h"
    3030
    31 /* _compress returns the compressed size, -1 if bigger */
    32 static int jffs2_rtime_compress(unsigned char *data_in,
    33                                 unsigned char *cpage_out,
    34                                 uint32_t *sourcelen, uint32_t *dstlen)
     31uint16_t rtems_jffs2_compressor_rtime_compress(
     32        rtems_jffs2_compressor_control *self,
     33        unsigned char *data_in,
     34        unsigned char *cpage_out,
     35        uint32_t *sourcelen,
     36        uint32_t *dstlen
     37)
    3538{
    3639        short positions[256];
    3740        int outpos = 0;
    3841        int pos=0;
     42
     43        (void) self;
    3944
    4045        memset(positions,0,sizeof(positions));
     
    6166        if (outpos >= pos) {
    6267                /* We failed */
    63                 return -1;
     68                return JFFS2_COMPR_NONE;
    6469        }
    6570
     
    6772        *sourcelen = pos;
    6873        *dstlen = outpos;
    69         return 0;
     74        return JFFS2_COMPR_RTIME;
    7075}
    7176
    7277
    73 static int jffs2_rtime_decompress(unsigned char *data_in,
    74                                   unsigned char *cpage_out,
    75                                   uint32_t srclen, uint32_t destlen)
     78int rtems_jffs2_compressor_rtime_decompress(
     79        rtems_jffs2_compressor_control *self,
     80        uint16_t comprtype,
     81        unsigned char *data_in,
     82        unsigned char *cpage_out,
     83        uint32_t srclen,
     84        uint32_t destlen
     85)
    7686{
    7787        short positions[256];
    7888        int outpos = 0;
    7989        int pos=0;
     90
     91        (void) self;
     92
     93        if (comprtype != JFFS2_COMPR_RTIME) {
     94                return -EIO;
     95        }
    8096
    8197        memset(positions,0,sizeof(positions));
     
    106122        return 0;
    107123}
    108 
    109 static struct jffs2_compressor jffs2_rtime_comp = {
    110     .priority = JFFS2_RTIME_PRIORITY,
    111     .name = "rtime",
    112     .compr = JFFS2_COMPR_RTIME,
    113     .compress = &jffs2_rtime_compress,
    114     .decompress = &jffs2_rtime_decompress,
    115 #ifdef JFFS2_RTIME_DISABLED
    116     .disabled = 1,
    117 #else
    118     .disabled = 0,
    119 #endif
    120 };
    121 
    122 int jffs2_rtime_init(void)
    123 {
    124     return jffs2_register_compressor(&jffs2_rtime_comp);
    125 }
    126 
    127 void jffs2_rtime_exit(void)
    128 {
    129     jffs2_unregister_compressor(&jffs2_rtime_comp);
    130 }
  • cpukit/libfs/src/jffs2/src/compr_zlib.c

    r78b85286 r3c96bee  
    3434static DEFINE_MUTEX(deflate_mutex);
    3535static DEFINE_MUTEX(inflate_mutex);
    36 static z_stream inf_strm, def_strm;
    3736
    38 #ifdef __KERNEL__ /* Linux-only */
    39 #include <linux/vmalloc.h>
    40 #include <linux/init.h>
    41 #include <linux/mutex.h>
    42 
    43 static int __init alloc_workspaces(void)
     37static rtems_jffs2_compressor_zlib_control *get_zlib_control(
     38        rtems_jffs2_compressor_control *super
     39)
    4440{
    45         def_strm.workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS,
    46                                                         MAX_MEM_LEVEL));
    47         if (!def_strm.workspace)
    48                 return -ENOMEM;
    49 
    50         jffs2_dbg(1, "Allocated %d bytes for deflate workspace\n",
    51                   zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
    52         inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
    53         if (!inf_strm.workspace) {
    54                 vfree(def_strm.workspace);
    55                 return -ENOMEM;
    56         }
    57         jffs2_dbg(1, "Allocated %d bytes for inflate workspace\n",
    58                   zlib_inflate_workspacesize());
    59         return 0;
     41        return (rtems_jffs2_compressor_zlib_control *) super;
    6042}
    6143
    62 static void free_workspaces(void)
     44uint16_t rtems_jffs2_compressor_zlib_compress(
     45        rtems_jffs2_compressor_control *super,
     46        unsigned char *data_in,
     47        unsigned char *cpage_out,
     48        uint32_t *sourcelen,
     49        uint32_t *dstlen
     50)
    6351{
    64         vfree(def_strm.workspace);
    65         vfree(inf_strm.workspace);
    66 }
    67 #else
    68 #define alloc_workspaces() (0)
    69 #define free_workspaces() do { } while(0)
    70 #endif /* __KERNEL__ */
    71 
    72 static int jffs2_zlib_compress(unsigned char *data_in,
    73                                unsigned char *cpage_out,
    74                                uint32_t *sourcelen, uint32_t *dstlen)
    75 {
     52        rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
     53        z_stream *def_strm = &self->stream;
    7654        int ret;
    7755
    7856        if (*dstlen <= STREAM_END_SPACE)
    79                 return -1;
     57                return JFFS2_COMPR_NONE;
    8058
    8159        mutex_lock(&deflate_mutex);
    8260
    83         if (Z_OK != zlib_deflateInit(&def_strm, 3)) {
     61        if (Z_OK != zlib_deflateInit(def_strm, 3)) {
    8462                pr_warn("deflateInit failed\n");
    8563                mutex_unlock(&deflate_mutex);
    86                 return -1;
     64                return JFFS2_COMPR_NONE;
    8765        }
    8866
    89         def_strm.next_in = data_in;
    90         def_strm.total_in = 0;
     67        def_strm->next_in = data_in;
     68        def_strm->total_in = 0;
    9169
    92         def_strm.next_out = cpage_out;
    93         def_strm.total_out = 0;
     70        def_strm->next_out = cpage_out;
     71        def_strm->total_out = 0;
    9472
    95         while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) {
    96                 def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE);
    97                 def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out);
     73        while (def_strm->total_out < *dstlen - STREAM_END_SPACE && def_strm->total_in < *sourcelen) {
     74                def_strm->avail_out = *dstlen - (def_strm->total_out + STREAM_END_SPACE);
     75                def_strm->avail_in = min((unsigned)(*sourcelen-def_strm->total_in), def_strm->avail_out);
    9876                jffs2_dbg(1, "calling deflate with avail_in %d, avail_out %d\n",
    99                           def_strm.avail_in, def_strm.avail_out);
    100                 ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH);
     77                          def_strm->avail_in, def_strm->avail_out);
     78                ret = zlib_deflate(def_strm, Z_PARTIAL_FLUSH);
    10179                jffs2_dbg(1, "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n",
    102                           def_strm.avail_in, def_strm.avail_out,
    103                           def_strm.total_in, def_strm.total_out);
     80                          def_strm->avail_in, def_strm->avail_out,
     81                          def_strm->total_in, def_strm->total_out);
    10482                if (ret != Z_OK) {
    10583                        jffs2_dbg(1, "deflate in loop returned %d\n", ret);
    106                         zlib_deflateEnd(&def_strm);
     84                        zlib_deflateEnd(def_strm);
    10785                        mutex_unlock(&deflate_mutex);
    108                         return -1;
     86                        return JFFS2_COMPR_NONE;
    10987                }
    11088        }
    111         def_strm.avail_out += STREAM_END_SPACE;
    112         def_strm.avail_in = 0;
    113         ret = zlib_deflate(&def_strm, Z_FINISH);
    114         zlib_deflateEnd(&def_strm);
     89        def_strm->avail_out += STREAM_END_SPACE;
     90        def_strm->avail_in = 0;
     91        ret = zlib_deflate(def_strm, Z_FINISH);
     92        zlib_deflateEnd(def_strm);
    11593
    11694        if (ret != Z_STREAM_END) {
    11795                jffs2_dbg(1, "final deflate returned %d\n", ret);
    118                 ret = -1;
     96                ret = JFFS2_COMPR_NONE;
    11997                goto out;
    12098        }
    12199
    122         if (def_strm.total_out >= def_strm.total_in) {
     100        if (def_strm->total_out >= def_strm->total_in) {
    123101                jffs2_dbg(1, "zlib compressed %ld bytes into %ld; failing\n",
    124                           def_strm.total_in, def_strm.total_out);
    125                 ret = -1;
     102                          def_strm->total_in, def_strm->total_out);
     103                ret = JFFS2_COMPR_NONE;
    126104                goto out;
    127105        }
    128106
    129107        jffs2_dbg(1, "zlib compressed %ld bytes into %ld\n",
    130                   def_strm.total_in, def_strm.total_out);
     108                  def_strm->total_in, def_strm->total_out);
    131109
    132         *dstlen = def_strm.total_out;
    133         *sourcelen = def_strm.total_in;
    134         ret = 0;
     110        *dstlen = def_strm->total_out;
     111        *sourcelen = def_strm->total_in;
     112        ret = JFFS2_COMPR_ZLIB;
    135113 out:
    136114        mutex_unlock(&deflate_mutex);
     
    138116}
    139117
    140 static int jffs2_zlib_decompress(unsigned char *data_in,
    141                                  unsigned char *cpage_out,
    142                                  uint32_t srclen, uint32_t destlen)
     118int rtems_jffs2_compressor_zlib_decompress(
     119        rtems_jffs2_compressor_control *super,
     120        uint16_t comprtype,
     121        unsigned char *data_in,
     122        unsigned char *cpage_out,
     123        uint32_t srclen,
     124        uint32_t destlen
     125)
    143126{
     127        rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
     128        z_stream *inf_strm = &self->stream;
    144129        int ret;
    145130        int wbits = MAX_WBITS;
    146131
     132        if (comprtype != JFFS2_COMPR_ZLIB) {
     133                return -EIO;
     134        }
     135
    147136        mutex_lock(&inflate_mutex);
    148137
    149         inf_strm.next_in = data_in;
    150         inf_strm.avail_in = srclen;
    151         inf_strm.total_in = 0;
     138        inf_strm->next_in = data_in;
     139        inf_strm->avail_in = srclen;
     140        inf_strm->total_in = 0;
    152141
    153         inf_strm.next_out = cpage_out;
    154         inf_strm.avail_out = destlen;
    155         inf_strm.total_out = 0;
     142        inf_strm->next_out = cpage_out;
     143        inf_strm->avail_out = destlen;
     144        inf_strm->total_out = 0;
    156145
    157146        /* If it's deflate, and it's got no preset dictionary, then
     
    163152                jffs2_dbg(2, "inflate skipping adler32\n");
    164153                wbits = -((data_in[0] >> 4) + 8);
    165                 inf_strm.next_in += 2;
    166                 inf_strm.avail_in -= 2;
     154                inf_strm->next_in += 2;
     155                inf_strm->avail_in -= 2;
    167156        } else {
    168157                /* Let this remain D1 for now -- it should never happen */
     
    171160
    172161
    173         if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) {
     162        if (Z_OK != zlib_inflateInit2(inf_strm, wbits)) {
    174163                pr_warn("inflateInit failed\n");
    175164                mutex_unlock(&inflate_mutex);
    176                 return 1;
     165                return -EIO;
    177166        }
    178167
    179         while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK)
     168        while((ret = zlib_inflate(inf_strm, Z_FINISH)) == Z_OK)
    180169                ;
    181170        if (ret != Z_STREAM_END) {
    182171                pr_notice("inflate returned %d\n", ret);
    183172        }
    184         zlib_inflateEnd(&inf_strm);
     173        zlib_inflateEnd(inf_strm);
    185174        mutex_unlock(&inflate_mutex);
    186175        return 0;
    187176}
    188 
    189 static struct jffs2_compressor jffs2_zlib_comp = {
    190     .priority = JFFS2_ZLIB_PRIORITY,
    191     .name = "zlib",
    192     .compr = JFFS2_COMPR_ZLIB,
    193     .compress = &jffs2_zlib_compress,
    194     .decompress = &jffs2_zlib_decompress,
    195 #ifdef JFFS2_ZLIB_DISABLED
    196     .disabled = 1,
    197 #else
    198     .disabled = 0,
    199 #endif
    200 };
    201 
    202 int __init jffs2_zlib_init(void)
    203 {
    204     int ret;
    205 
    206     ret = alloc_workspaces();
    207     if (ret)
    208             return ret;
    209 
    210     ret = jffs2_register_compressor(&jffs2_zlib_comp);
    211     if (ret)
    212             free_workspaces();
    213 
    214     return ret;
    215 }
    216 
    217 void jffs2_zlib_exit(void)
    218 {
    219     jffs2_unregister_compressor(&jffs2_zlib_comp);
    220     free_workspaces();
    221 }
  • cpukit/libfs/src/jffs2/src/debug.h

    r78b85286 r3c96bee  
    7676
    7777/* JFFS2 message macros */
     78#ifndef __rtems__
    7879#define JFFS2_ERROR(fmt, ...)                                   \
    7980        pr_err("error: (%d) %s: " fmt,                          \
     
    9192        printk(KERN_DEBUG "[JFFS2 DBG] (%d) %s: " fmt,                  \
    9293               task_pid_nr(current), __func__, ##__VA_ARGS__)
     94#else /* __rtems__ */
     95#define JFFS2_ERROR(fmt, ...)                                   \
     96        pr_err("error: %s: " fmt,                               \
     97               __func__, ##__VA_ARGS__)
     98
     99#define JFFS2_WARNING(fmt, ...)                                         \
     100        pr_warn("warning: %s: " fmt,                            \
     101                __func__, ##__VA_ARGS__)
     102
     103#define JFFS2_NOTICE(fmt, ...)                                          \
     104        pr_notice("notice: %s: " fmt,                           \
     105                  __func__, ##__VA_ARGS__)
     106
     107#define JFFS2_DEBUG(fmt, ...)                                           \
     108        printk(KERN_DEBUG "[JFFS2 DBG] %s: " fmt,                       \
     109               __func__, ##__VA_ARGS__)
     110#endif /* __rtems__ */
    93111
    94112/*
  • cpukit/libfs/src/jffs2/src/dir-rtems.c

    r78b85286 r3c96bee  
    22 * JFFS2 -- Journalling Flash File System, Version 2.
    33 *
    4  * Copyright (C) 2001-2003 Free Software Foundation, Inc.
     4 * Copyright © 2001-2003 Free Software Foundation, Inc.
     5 * Copyright © 2001-2007 Red Hat, Inc.
     6 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
     7 * Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
    58 *
    69 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
     10 *
     11 * Port to the RTEMS by embedded brains GmbH.
    712 *
    813 * For licensing information, see the file 'LICENCE' in this directory.
     
    1924
    2025/* Takes length argument because it can be either NUL-terminated or '/'-terminated */
    21 struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, int namelen)
     26struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, size_t namelen)
    2227{
    2328        struct jffs2_inode_info *dir_f;
    24         struct jffs2_sb_info *c;
    2529        struct jffs2_full_dirent *fd = NULL, *fd_list;
    2630        uint32_t ino = 0;
    27         uint32_t hash = full_name_hash(d_name, namelen);
     31        uint32_t hash = full_name_hash(name, namelen);
    2832        struct _inode *inode = NULL;
    2933
     
    3135
    3236        dir_f = JFFS2_INODE_INFO(dir_i);
    33         c = JFFS2_SB_INFO(dir_i->i_sb);
    34 
    35         down(&dir_f->sem);
     37
     38        mutex_lock(&dir_f->sem);
    3639
    3740        /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
     
    4043                    (!fd || fd_list->version > fd->version) &&
    4144                    strlen((char *)fd_list->name) == namelen &&
    42                     !strncmp((char *)fd_list->name, (char *)d_name, namelen)) {
     45                    !strncmp((char *)fd_list->name, (char *)name, namelen)) {
    4346                        fd = fd_list;
    4447                }
     
    4649        if (fd)
    4750                ino = fd->ino;
    48         up(&dir_f->sem);
     51        mutex_unlock(&dir_f->sem);
    4952        if (ino) {
    5053                inode = jffs2_iget(dir_i->i_sb, ino);
     
    5255                        printk("jffs2_iget() failed for ino #%u\n", ino);
    5356                        return inode;
     57                } else {
     58                        inode->i_fd = fd;
    5459                }
    5560        }
     
    6267
    6368
    64 int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
    65                  struct _inode **new_i)
     69int jffs2_create(struct _inode *dir_i, const char *d_name, size_t d_namelen, int mode)
    6670{
    6771        struct jffs2_raw_inode *ri;
     
    7074        struct _inode *inode;
    7175        int ret;
     76        struct qstr qstr;
     77
     78        qstr.name = d_name;
     79        qstr.len = d_namelen;
    7280
    7381        ri = jffs2_alloc_raw_inode();
     
    9098        dir_f = JFFS2_INODE_INFO(dir_i);
    9199
    92         ret = jffs2_do_create(c, dir_f, f, ri,
    93                               (const char *)d_name,
    94                               strlen((char *)d_name));
     100        ret = jffs2_do_create(c, dir_f, f, ri, &qstr);
    95101
    96102        if (ret) {
     
    101107        }
    102108
     109        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
     110
    103111        jffs2_free_raw_inode(ri);
    104112
    105113        D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
    106                   inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink));
    107         *new_i = inode;
     114                  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink));
     115        jffs2_iput(inode);
    108116        return 0;
    109117}
     
    112120
    113121
    114 int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
     122int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
    115123{
    116124        struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
     
    119127        int ret;
    120128
    121         ret = jffs2_do_unlink(c, dir_f, (const char *)d_name, 
    122                                strlen((char *)d_name), dead_f);
     129        ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
     130                               d_namelen, dead_f, get_seconds());
    123131        if (dead_f->inocache)
    124                 d_inode->i_nlink = dead_f->inocache->nlink;
     132                d_inode->i_nlink = dead_f->inocache->pino_nlink;
    125133        return ret;
    126134}
     
    128136
    129137
    130 int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name)
     138int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen)
    131139{
    132140        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
     
    141149        ret = jffs2_do_link(c, dir_f, f->inocache->ino, type,
    142150                            (const char * )d_name,
    143                             strlen((char *)d_name));
     151                            d_namelen, get_seconds());
    144152
    145153        if (!ret) {
    146                 down(&f->sem);
    147                 old_d_inode->i_nlink = ++f->inocache->nlink;
    148                 up(&f->sem);
     154                mutex_lock(&f->sem);
     155                old_d_inode->i_nlink = ++f->inocache->pino_nlink;
     156                mutex_unlock(&f->sem);
    149157        }
    150158        return ret;
    151159}
    152160
    153 int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
     161/***********************************************************************/
     162
     163int jffs2_mknod(
     164        struct _inode *dir_i,
     165        const unsigned char *d_name,
     166        size_t d_namelen,
     167        int mode,
     168        const unsigned char *data,
     169        size_t datalen
     170)
    154171{
    155172        struct jffs2_inode_info *f, *dir_f;
     
    160177        struct jffs2_full_dnode *fn;
    161178        struct jffs2_full_dirent *fd;
    162         int namelen;
    163         uint32_t alloclen, phys_ofs;
     179        uint32_t alloclen;
    164180        int ret;
    165181
    166         mode |= S_IFDIR;
     182        /* FIXME: If you care. We'd need to use frags for the data
     183           if it grows much more than this */
     184        if (datalen > 254)
     185                return -ENAMETOOLONG;
    167186
    168187        ri = jffs2_alloc_raw_inode();
     188
    169189        if (!ri)
    170190                return -ENOMEM;
    171        
     191
    172192        c = JFFS2_SB_INFO(dir_i->i_sb);
    173193
    174         /* Try to reserve enough space for both node and dirent. 
    175          * Just the node will do for now, though 
     194        /* Try to reserve enough space for both node and dirent.
     195         * Just the node will do for now, though
    176196         */
    177         namelen = strlen((char *)d_name);
    178         ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
     197        ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &alloclen,
     198                                  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
    179199
    180200        if (ret) {
     
    193213        f = JFFS2_INODE_INFO(inode);
    194214
    195         ri->data_crc = cpu_to_je32(0);
     215        inode->i_size = datalen;
     216        ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);
     217        ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);
     218        ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
     219
     220        ri->compr = JFFS2_COMPR_NONE;
     221        ri->data_crc = cpu_to_je32(crc32(0, data, datalen));
    196222        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
    197        
    198         fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
     223
     224        fn = jffs2_write_dnode(c, f, ri, data, datalen, ALLOC_NORMAL);
    199225
    200226        jffs2_free_raw_inode(ri);
     
    202228        if (IS_ERR(fn)) {
    203229                /* Eeek. Wave bye bye */
    204                 up(&f->sem);
     230                mutex_unlock(&f->sem);
    205231                jffs2_complete_reservation(c);
    206                 inode->i_nlink = 0;
    207                 jffs2_iput(inode);
    208                 return PTR_ERR(fn);
    209         }
    210         /* No data here. Only a metadata node, which will be
     232                ret = PTR_ERR(fn);
     233                goto fail;
     234        }
     235
     236        if (S_ISLNK(mode)) {
     237                /* We use f->target field to store the target path. */
     238                f->target = kmemdup(data, datalen + 1, GFP_KERNEL);
     239                if (!f->target) {
     240                        pr_warn("Can't allocate %d bytes of memory\n", datalen + 1);
     241                        mutex_unlock(&f->sem);
     242                        jffs2_complete_reservation(c);
     243                        ret = -ENOMEM;
     244                        goto fail;
     245                }
     246
     247                jffs2_dbg(1, "%s(): symlink's target '%s' cached\n",
     248                          __func__, (char *)f->target);
     249        }
     250
     251        /* No data here. Only a metadata node, which will be
    211252           obsoleted by the first data write
    212253        */
    213254        f->metadata = fn;
    214         up(&f->sem);
     255        mutex_unlock(&f->sem);
    215256
    216257        jffs2_complete_reservation(c);
    217         ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
    218         if (ret) {
    219                 /* Eep. */
    220                 inode->i_nlink = 0;
    221                 jffs2_iput(inode);
    222                 return ret;
    223         }
    224        
     258
     259        ret = jffs2_reserve_space(c, sizeof(*rd)+d_namelen, &alloclen,
     260                                  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(d_namelen));
     261        if (ret)
     262                goto fail;
     263
    225264        rd = jffs2_alloc_raw_dirent();
    226265        if (!rd) {
    227266                /* Argh. Now we treat it like a normal delete */
    228267                jffs2_complete_reservation(c);
    229                 inode->i_nlink = 0;
    230                 jffs2_iput(inode);
    231                 return -ENOMEM;
     268                ret = -ENOMEM;
     269                goto fail;
    232270        }
    233271
    234272        dir_f = JFFS2_INODE_INFO(dir_i);
    235         down(&dir_f->sem);
     273        mutex_lock(&dir_f->sem);
    236274
    237275        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
    238276        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
    239         rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
     277        rd->totlen = cpu_to_je32(sizeof(*rd) + d_namelen);
    240278        rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
    241279
     
    243281        rd->version = cpu_to_je32(++dir_f->highest_version);
    244282        rd->ino = cpu_to_je32(inode->i_ino);
    245         rd->mctime = cpu_to_je32(cyg_timestamp());
    246         rd->nsize = namelen;
    247         rd->type = DT_DIR;
     283        rd->mctime = cpu_to_je32(get_seconds());
     284        rd->nsize = d_namelen;
     285
     286        /* XXX: This is ugly. */
     287        rd->type = (mode & S_IFMT) >> 12;
     288
    248289        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
    249         rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen));
    250 
    251         fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL);
    252        
    253         jffs2_complete_reservation(c);
     290        rd->name_crc = cpu_to_je32(crc32(0, d_name, d_namelen));
     291
     292        fd = jffs2_write_dirent(c, dir_f, rd, d_name, d_namelen, ALLOC_NORMAL);
     293
     294        if (IS_ERR(fd)) {
     295                /* dirent failed to write. Delete the inode normally
     296                   as if it were the final unlink() */
     297                jffs2_complete_reservation(c);
     298                jffs2_free_raw_dirent(rd);
     299                mutex_unlock(&dir_f->sem);
     300                ret = PTR_ERR(fd);
     301                goto fail;
     302        }
     303
     304        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
     305
    254306        jffs2_free_raw_dirent(rd);
    255        
    256         if (IS_ERR(fd)) {
    257                 /* dirent failed to write. Delete the inode normally
    258                    as if it were the final unlink() */
    259                 up(&dir_f->sem);
    260                 inode->i_nlink = 0;
    261                 jffs2_iput(inode);
    262                 return PTR_ERR(fd);
    263         }
    264307
    265308        /* Link the fd into the inode's list, obsoleting an old
    266309           one if necessary. */
    267310        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
    268         up(&dir_f->sem);
    269 
     311
     312        mutex_unlock(&dir_f->sem);
     313        jffs2_complete_reservation(c);
     314
     315 fail:
    270316        jffs2_iput(inode);
    271         return 0;
    272 }
    273 
    274 int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
     317
     318        return ret;
     319}
     320
     321int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
    275322{
    276323        struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
     
    279326        for (fd = f->dents ; fd; fd = fd->next) {
    280327                if (fd->ino)
    281                         return EPERM; //-ENOTEMPTY;
    282         }
    283         return jffs2_unlink(dir_i, d_inode, d_name);
    284 }
    285 
    286 int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
    287                   struct _inode *new_dir_i, const unsigned char *new_d_name)
     328                        return -ENOTEMPTY;
     329        }
     330        return jffs2_unlink(dir_i, d_inode, d_name, d_namelen);
     331}
     332
     333int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, size_t old_d_namelen,
     334                  struct _inode *new_dir_i, const unsigned char *new_d_name, size_t new_d_namelen)
    288335{
    289336        int ret;
     
    291338        struct jffs2_inode_info *victim_f = NULL;
    292339        uint8_t type;
     340        uint32_t now;
    293341
    294342#if 0 /* FIXME -- this really doesn't belong in individual file systems.
     
    310358                                return -EINVAL;
    311359                        }
    312                         down(&victim_f->sem);
     360                        mutex_lock(&victim_f->sem);
    313361                        for (fd = victim_f->dents; fd; fd = fd->next) {
    314362                                if (fd->ino) {
    315                                         up(&victim_f->sem);
     363                                        mutex_unlock(&victim_f->sem);
    316364                                        return -ENOTEMPTY;
    317365                                }
    318366                        }
    319                         up(&victim_f->sem);
     367                        mutex_unlock(&victim_f->sem);
    320368                }
    321369        }
     
    333381        if (!type) type = DT_REG;
    334382
    335         ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
     383        now = get_seconds();
     384        ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
    336385                            d_inode->i_ino, type,
    337                             (const char *)new_d_name, 
    338                             strlen((char *)new_d_name));
     386                            (const char *)new_d_name,
     387                            new_d_namelen, now);
    339388
    340389        if (ret)
     
    346395                   inode which didn't exist. */
    347396                if (victim_f->inocache) {
    348                         down(&victim_f->sem);
    349                         victim_f->inocache->nlink--;
    350                         up(&victim_f->sem);
     397                        mutex_lock(&victim_f->sem);
     398                        victim_f->inocache->pino_nlink--;
     399                        mutex_unlock(&victim_f->sem);
    351400                }
    352401        }
    353402
    354403        /* Unlink the original */
    355         ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), 
    356                               (const char *)old_d_name, 
    357                               strlen((char *)old_d_name), NULL);
     404        ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
     405                              (const char *)old_d_name,
     406                              old_d_namelen, NULL, now);
    358407
    359408        if (ret) {
    360409                /* Oh shit. We really ought to make a single node which can do both atomically */
    361410                struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
    362                 down(&f->sem);
     411                mutex_lock(&f->sem);
    363412                if (f->inocache)
    364                         d_inode->i_nlink = f->inocache->nlink++;
    365                 up(&f->sem);
     413                        d_inode->i_nlink = f->inocache->pino_nlink++;
     414                mutex_unlock(&f->sem);
    366415
    367416                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
  • cpukit/libfs/src/jffs2/src/erase.c

    r78b85286 r3c96bee  
    392392                *bad_offset = ofs;
    393393
    394                 ret = mtd_read(c->mtd, ofs, readlen, &retlen, ebuf);
     394                ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf);
    395395                if (ret) {
    396396                        pr_warn("Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n",
  • cpukit/libfs/src/jffs2/src/flashio.c

    r78b85286 r3c96bee  
    1616#include "nodelist.h"
    1717
    18 #include <cyg/io/io.h>
    19 #include <cyg/io/config_keys.h>
    20 #include <cyg/io/flash.h>
    21 
    22 cyg_bool jffs2_flash_read(struct jffs2_sb_info * c,
     18int jffs2_flash_read(struct jffs2_sb_info * c,
    2319                          cyg_uint32 read_buffer_offset, const size_t size,
    2420                          size_t * return_size, unsigned char *write_buffer)
    2521{
    26         Cyg_ErrNo err;
    27         cyg_uint32 len = size;
    28         struct super_block *sb = OFNI_BS_2SFFJ(c);
     22        const struct super_block *sb = OFNI_BS_2SFFJ(c);
     23        rtems_jffs2_flash_control *fc = sb->s_flash_control;
    2924
    30         //D2(printf("FLASH READ\n"));
    31         //D2(printf("read address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + read_buffer_offset));
    32         //D2(printf("write address = %x\n", write_buffer));
    33         //D2(printf("size = %x\n", size));
    34         err = cyg_io_bread(sb->s_dev, write_buffer, &len, read_buffer_offset);
     25        *return_size = size;
    3526
    36         *return_size = (size_t) len;
    37         return ((err == ENOERR) ? ENOERR : -EIO);
     27        return (*fc->read)(fc, read_buffer_offset, write_buffer, size);
    3828}
    3929
    40 cyg_bool jffs2_flash_write(struct jffs2_sb_info * c,
     30int jffs2_flash_write(struct jffs2_sb_info * c,
    4131                           cyg_uint32 write_buffer_offset, const size_t size,
    4232                           size_t * return_size, unsigned char *read_buffer)
    4333{
     34        const struct super_block *sb = OFNI_BS_2SFFJ(c);
     35        rtems_jffs2_flash_control *fc = sb->s_flash_control;
    4436
    45         Cyg_ErrNo err;
    46         cyg_uint32 len = size;
    47         struct super_block *sb = OFNI_BS_2SFFJ(c);
     37        *return_size = size;
    4838
    49         //    D2(printf("FLASH WRITE ENABLED!!!\n"));
    50         //    D2(printf("write address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + write_buffer_offset));
    51         //    D2(printf("read address = %x\n", read_buffer));
    52         //    D2(printf("size = %x\n", size));
    53 
    54         err = cyg_io_bwrite(sb->s_dev, read_buffer, &len, write_buffer_offset);
    55         *return_size = (size_t) len;
    56 
    57         return ((err == ENOERR) ? ENOERR : -EIO);
     39        return (*fc->write)(fc, write_buffer_offset, read_buffer, size);
    5840}
    5941
     
    141123}
    142124
    143 cyg_bool jffs2_flash_erase(struct jffs2_sb_info * c,
     125int jffs2_flash_erase(struct jffs2_sb_info * c,
    144126                           struct jffs2_eraseblock * jeb)
    145127{
    146         cyg_io_flash_getconfig_erase_t e;
    147         cyg_flashaddr_t err_addr;
    148         Cyg_ErrNo err;
    149         cyg_uint32 len = sizeof (e);
    150         struct super_block *sb = OFNI_BS_2SFFJ(c);
     128        const struct super_block *sb = OFNI_BS_2SFFJ(c);
     129        rtems_jffs2_flash_control *fc = sb->s_flash_control;
    151130
    152         e.offset = jeb->offset;
    153         e.len = c->sector_size;
    154         e.err_address = &err_addr;
    155 
    156         //        D2(printf("FLASH ERASE ENABLED!!!\n"));
    157         //        D2(printf("erase address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + jeb->offset));
    158         //        D2(printf("size = %x\n", c->sector_size));
    159 
    160         err = cyg_io_get_config(sb->s_dev, CYG_IO_GET_CONFIG_FLASH_ERASE,
    161                                 &e, &len);
    162 
    163         return (err != ENOERR || e.flasherr != 0);
     131        return (*fc->erase)(fc, jeb->offset);
    164132}
    165133
  • cpukit/libfs/src/jffs2/src/fs-rtems.c

    r78b85286 r3c96bee  
    22 * JFFS2 -- Journalling Flash File System, Version 2.
    33 *
    4  * Copyright (C) 2001-2003 Free Software Foundation, Inc.
     4 * Copyright © 2001-2003 Free Software Foundation, Inc.
     5 * Copyright © 2001-2007 Red Hat, Inc.
     6 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
     7 * Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
    58 *
    69 * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com>
    710 * Contributors: David Woodhouse, Nick Garnett, Richard Panton.
     11 *
     12 * Port to the RTEMS by embedded brains GmbH.
    813 *
    914 * For licensing information, see the file 'LICENCE' in this directory.
     
    2025#include <errno.h>
    2126#include <string.h>
    22 #include <cyg/io/config_keys.h>
    23 
    24 #if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) && \
    25     (defined (__arm__) || defined (_mips))
    26 #error This compiler is known to be broken. Please see:
    27 #error "http://ecos.sourceware.org/ml/ecos-patches/2003-08/msg00006.html"
    28 #endif
    29 
    30 //==========================================================================
    31 // Forward definitions
    32 
    33 // Filesystem operations
    34 static int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte);
    35 static int jffs2_umount(cyg_mtab_entry * mte);
    36 static int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    37                       int mode, cyg_file * fte);
    38 #ifdef CYGOPT_FS_JFFS2_WRITE
    39 static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir,
    40                             const char *name);
    41 static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);
    42 static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);
    43 static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,
    44                             const char *name1, cyg_dir dir2, const char *name2);
    45 static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1,
    46                           cyg_dir dir2, const char *name2, int type);
    47 #endif
    48 static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    49                          cyg_file * fte);
    50 static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    51                        cyg_dir * dir_out);
    52 static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    53                       struct stat *buf);
    54 static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    55                          int key, void *buf, int len);
    56 static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    57                          int key, void *buf, int len);
    58 
    59 // File operations
    60 static int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
    61 #ifdef CYGOPT_FS_JFFS2_WRITE
    62 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
    63 #endif
    64 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);
    65 static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
    66                           CYG_ADDRWORD data);
    67 static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
    68 static int jffs2_fo_close(struct CYG_FILE_TAG *fp);
    69 static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf);
    70 static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
    71                             int len);
    72 static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
    73                             int len);
    74 
    75 // Directory operations
    76 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
    77 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);
    78 
     27#include <assert.h>
     28#include <rtems/libio_.h>
     29
     30/* Ensure that the JFFS2 values are identical to the POSIX defines */
     31
     32RTEMS_STATIC_ASSERT(DT_DIR == (S_IFDIR >> 12), DT_DIR);
     33RTEMS_STATIC_ASSERT(DT_LNK == (S_IFLNK >> 12), DT_LNK);
     34RTEMS_STATIC_ASSERT(DT_REG == (S_IFREG >> 12), DT_REG);
     35
     36RTEMS_STATIC_ASSERT(00400 == S_IRUSR, S_IRUSR);
     37RTEMS_STATIC_ASSERT(00200 == S_IWUSR, S_IWUSR);
     38RTEMS_STATIC_ASSERT(00100 == S_IXUSR, S_IXUSR);
     39RTEMS_STATIC_ASSERT(00040 == S_IRGRP, S_IRGRP);
     40RTEMS_STATIC_ASSERT(00020 == S_IWGRP, S_IWGRP);
     41RTEMS_STATIC_ASSERT(00010 == S_IXGRP, S_IXGRP);
     42RTEMS_STATIC_ASSERT(00004 == S_IROTH, S_IROTH);
     43RTEMS_STATIC_ASSERT(00002 == S_IWOTH, S_IWOTH);
     44RTEMS_STATIC_ASSERT(00001 == S_IXOTH, S_IXOTH);
     45
     46RTEMS_STATIC_ASSERT(0140000 == S_IFSOCK, S_IFSOCK);
     47RTEMS_STATIC_ASSERT(0120000 == S_IFLNK, S_IFLNK);
     48RTEMS_STATIC_ASSERT(0100000 == S_IFREG, S_IFREG);
     49RTEMS_STATIC_ASSERT(0060000 == S_IFBLK, S_IFBLK);
     50RTEMS_STATIC_ASSERT(0040000 == S_IFDIR, S_IFDIR);
     51RTEMS_STATIC_ASSERT(0020000 == S_IFCHR, S_IFCHR);
     52RTEMS_STATIC_ASSERT(0010000 == S_IFIFO, S_IFIFO);
     53RTEMS_STATIC_ASSERT(0004000 == S_ISUID, S_ISUID);
     54RTEMS_STATIC_ASSERT(0002000 == S_ISGID, S_ISGID);
     55RTEMS_STATIC_ASSERT(0001000 == S_ISVTX, S_ISVTX);
    7956
    8057static int jffs2_read_inode (struct _inode *inode);
    8158static void jffs2_clear_inode (struct _inode *inode);
    82 static int jffs2_truncate_file (struct _inode *inode);
    83 
    84 //==========================================================================
    85 // Filesystem table entries
    86 
    87 // -------------------------------------------------------------------------
    88 // Fstab entry.
    89 // This defines the entry in the filesystem table.
    90 // For simplicity we use _FILESYSTEM synchronization for all accesses since
    91 // we should never block in any filesystem operations.
    92 
    93 #ifdef CYGOPT_FS_JFFS2_WRITE
    94 FSTAB_ENTRY(jffs2_fste, "jffs2", 0,
    95             CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
    96             jffs2_mount,
    97             jffs2_umount,
    98             jffs2_open,
    99             jffs2_ops_unlink,
    100             jffs2_ops_mkdir,
    101             jffs2_ops_rmdir,
    102             jffs2_ops_rename,
    103             jffs2_ops_link,
    104             jffs2_opendir,
    105             jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo);
    106 #else
    107 FSTAB_ENTRY(jffs2_fste, "jffs2", 0,
    108             CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
    109             jffs2_mount,
    110             jffs2_umount,
    111             jffs2_open,
    112             (cyg_fsop_unlink *)cyg_fileio_erofs,
    113             (cyg_fsop_mkdir *)cyg_fileio_erofs,
    114             (cyg_fsop_rmdir *)cyg_fileio_erofs,
    115             (cyg_fsop_rename *)cyg_fileio_erofs,
    116             (cyg_fsop_link *)cyg_fileio_erofs,
    117             jffs2_opendir,
    118             jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo);
    119 #endif
    120 
    121 // -------------------------------------------------------------------------
    122 // File operations.
    123 // This set of file operations are used for normal open files.
    124 
    125 static cyg_fileops jffs2_fileops = {
    126         jffs2_fo_read,
    127 #ifdef CYGOPT_FS_JFFS2_WRITE
    128         jffs2_fo_write,
    129 #else
    130         (cyg_fileop_write *) cyg_fileio_erofs,
    131 #endif
    132         jffs2_fo_lseek,
    133         jffs2_fo_ioctl,
    134         cyg_fileio_seltrue,
    135         jffs2_fo_fsync,
    136         jffs2_fo_close,
    137         jffs2_fo_fstat,
    138         jffs2_fo_getinfo,
    139         jffs2_fo_setinfo
    140 };
    141 
    142 // -------------------------------------------------------------------------
    143 // Directory file operations.
    144 // This set of operations are used for open directories. Most entries
    145 // point to error-returning stub functions. Only the read, lseek and
    146 // close entries are functional.
    147 
    148 static cyg_fileops jffs2_dirops = {
    149         jffs2_fo_dirread,
    150         (cyg_fileop_write *) cyg_fileio_enosys,
    151         jffs2_fo_dirlseek,
    152         (cyg_fileop_ioctl *) cyg_fileio_enosys,
    153         cyg_fileio_seltrue,
    154         (cyg_fileop_fsync *) cyg_fileio_enosys,
    155         jffs2_fo_close,
    156         (cyg_fileop_fstat *) cyg_fileio_enosys,
    157         (cyg_fileop_getinfo *) cyg_fileio_enosys,
    158         (cyg_fileop_setinfo *) cyg_fileio_enosys
    159 };
    160 
    161 //==========================================================================
    162 // STATIC VARIABLES !!!
    163 
    164 static unsigned char gc_buffer[PAGE_CACHE_SIZE];        //avoids malloc when user may be under memory pressure
    165 static unsigned char n_fs_mounted = 0;  // a counter to track the number of jffs2 instances mounted
    166 
    167 //==========================================================================
    168 // Directory operations
    169 
    170 struct jffs2_dirsearch {
    171         struct _inode *dir;         // directory to search
    172         const unsigned char *path;  // path to follow
    173         struct _inode *node;        // Node found
    174         const unsigned char *name;  // last name fragment used
    175         int namelen;                // name fragment length
    176         cyg_bool last;              // last name in path?
    177 };
    178 
    179 typedef struct jffs2_dirsearch jffs2_dirsearch;
    18059
    18160//==========================================================================
     
    21594}
    21695
    217 //==========================================================================
    218 // Directory search
    219 
    220 // -------------------------------------------------------------------------
    221 // init_dirsearch()
    222 // Initialize a dirsearch object to start a search
    223 
    224 static void init_dirsearch(jffs2_dirsearch * ds,
    225                            struct _inode *dir, const unsigned char *name)
    226 {
    227         D2(printf("init_dirsearch name = %s\n", name));
    228         D2(printf("init_dirsearch dir = %x\n", dir));
    229 
    230         dir->i_count++;
    231         ds->dir = dir;
    232         ds->path = name;
    233         ds->node = dir;
    234         ds->name = name;
    235         ds->namelen = 0;
    236         ds->last = false;
    237 }
    238 
    239 // -------------------------------------------------------------------------
    240 // find_entry()
    241 // Search a single directory for the next name in a path and update the
    242 // dirsearch object appropriately.
    243 
    244 static int find_entry(jffs2_dirsearch * ds)
    245 {
    246         struct _inode *dir = ds->dir;
    247         const unsigned char *name = ds->path;
    248         const unsigned char *n = name;
    249         char namelen = 0;
    250         struct _inode *d;
    251 
    252         D2(printf("find_entry\n"));
    253 
    254         // check that we really have a directory
    255         if (!S_ISDIR(dir->i_mode))
    256                 return ENOTDIR;
    257 
    258         // Isolate the next element of the path name.
    259         while (*n != '\0' && *n != '/')
    260                 n++, namelen++;
    261 
    262         // Check if this is the last path element.
    263         while( *n == '/') n++;
    264         if (*n == '\0')
    265                 ds->last = true;
    266 
    267         // update name in dirsearch object
    268         ds->name = name;
    269         ds->namelen = namelen;
    270 
    271         if (name[0] == '.')
    272                 switch (namelen) {
    273                 default:
    274                         break;
    275                 case 2:
    276                         // Dot followed by not Dot, treat as any other name
    277                         if (name[1] != '.')
    278                                 break;
    279                         // Dot Dot
    280                         // Move back up the search path
    281                         D2(printf("find_entry found ..\n"));
    282                         ds->dir = ds->node;
    283                         ds->node = ds->dir->i_parent;
    284                         ds->node->i_count++;
    285                         return ENOERR;
    286                 case 1:
    287                         // Dot is consumed
    288                         D2(printf("find_entry found .\n"));
    289                         ds->node = ds->dir;
    290                         ds->dir->i_count++;
    291                         return ENOERR;
    292                 }
    293 
    294         // Here we have the name and its length set up.
    295         // Search the directory for a matching entry
    296 
    297         D2(printf("find_entry for name = %s\n", ds->path));
    298         d = jffs2_lookup(dir, name, namelen);
    299         D2(printf("find_entry got dir = %x\n", d));
    300 
    301         if (d == NULL)
    302                 return ENOENT;
    303         if (IS_ERR(d))
    304                 return -PTR_ERR(d);
    305 
    306         // If it's a new directory inode, increase refcount on its parent
    307         if (S_ISDIR(d->i_mode) && !d->i_parent) {
    308                 d->i_parent = dir;
    309                 dir->i_count++;
    310         }
    311 
    312         // pass back the node we have found
    313         ds->node = d;
    314         return ENOERR;
    315 
    316 }
    317 
    318 // -------------------------------------------------------------------------
    319 // jffs2_find()
    320 // Main interface to directory search code. This is used in all file
    321 // level operations to locate the object named by the pathname.
    322 
    323 // Returns with use count incremented on both the sought object and
    324 // the directory it was found in
    325 static int jffs2_find(jffs2_dirsearch * d)
    326 {
    327         int err;
    328 
    329         D2(printf("jffs2_find for path =%s\n", d->path));
    330 
    331         // Short circuit empty paths
    332         if (*(d->path) == '\0') {
    333                 d->node->i_count++;
    334                 return ENOERR;
    335         }
    336 
    337         // iterate down directory tree until we find the object
    338         // we want.
    339         for (;;) {
    340                 err = find_entry(d);
    341 
    342                 if (err != ENOERR)
    343                         return err;
    344 
    345                 if (d->last)
    346                         return ENOERR;
    347 
    348                 /* We're done with it, although it we found a subdir that
    349                    will have caused the refcount to have been increased */
    350                 jffs2_iput(d->dir);
    351 
    352                 // Update dirsearch object to search next directory.
    353                 d->dir = d->node;
    354                 d->path += d->namelen;
    355                 while (*(d->path) == '/')
    356                         d->path++;      // skip dirname separators
    357         }
    358 }
    359 
    360 //==========================================================================
    361 // Pathconf support
    362 // This function provides support for pathconf() and fpathconf().
    363 
    364 static int jffs2_pathconf(struct _inode *node, struct cyg_pathconf_info *info)
    365 {
    366         int err = ENOERR;
    367         D2(printf("jffs2_pathconf\n"));
    368 
    369         switch (info->name) {
    370         case _PC_LINK_MAX:
    371                 info->value = LINK_MAX;
    372                 break;
    373 
    374         case _PC_MAX_CANON:
    375                 info->value = -1;       // not supported
    376                 err = EINVAL;
    377                 break;
    378 
    379         case _PC_MAX_INPUT:
    380                 info->value = -1;       // not supported
    381                 err = EINVAL;
    382                 break;
    383 
    384         case _PC_NAME_MAX:
    385                 info->value = NAME_MAX;
    386                 break;
    387 
    388         case _PC_PATH_MAX:
    389                 info->value = PATH_MAX;
    390                 break;
    391 
    392         case _PC_PIPE_BUF:
    393                 info->value = -1;       // not supported
    394                 err = EINVAL;
    395                 break;
    396 
    397         case _PC_ASYNC_IO:
    398                 info->value = -1;       // not supported
    399                 err = EINVAL;
    400                 break;
    401 
    402         case _PC_CHOWN_RESTRICTED:
    403                 info->value = -1;       // not supported
    404                 err = EINVAL;
    405                 break;
    406 
    407         case _PC_NO_TRUNC:
    408                 info->value = 0;
    409                 break;
    410 
    411         case _PC_PRIO_IO:
    412                 info->value = 0;
    413                 break;
    414 
    415         case _PC_SYNC_IO:
    416                 info->value = 0;
    417                 break;
    418 
    419         case _PC_VDISABLE:
    420                 info->value = -1;       // not supported
    421                 err = EINVAL;
    422                 break;
    423 
    424         default:
    425                 err = EINVAL;
    426                 break;
    427         }
    428 
    429         return err;
    430 }
    431 
    432 //==========================================================================
    433 // Filesystem operations
    434 
    435 // -------------------------------------------------------------------------
    436 // jffs2_mount()
    437 // Process a mount request. This mainly creates a root for the
    438 // filesystem.
    439 static int jffs2_read_super(struct super_block *sb)
    440 {
    441         struct jffs2_sb_info *c;
    442         Cyg_ErrNo err;
    443         cyg_uint32 len;
    444         cyg_io_flash_getconfig_devsize_t ds;
    445         cyg_io_flash_getconfig_blocksize_t bs;
    446 
    447         D1(printk(KERN_DEBUG "jffs2: read_super\n"));
    448 
    449         c = JFFS2_SB_INFO(sb);
    450 
    451         len = sizeof (ds);
    452         err = cyg_io_get_config(sb->s_dev,
    453                                 CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
    454         if (err != ENOERR) {
    455                 D1(printf
    456                    ("jffs2: cyg_io_get_config failed to get dev size: %d\n",
    457                     err));
    458                 return err;
    459         }
    460         len = sizeof (bs);
    461         bs.offset = 0;
    462         err = cyg_io_get_config(sb->s_dev,
    463                                 CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE, &bs, &len);
    464         if (err != ENOERR) {
    465                 D1(printf
    466                    ("jffs2: cyg_io_get_config failed to get block size: %d\n",
    467                     err));
    468                 return err;
    469         }
    470 
    471         c->sector_size = bs.block_size;
    472         c->flash_size = ds.dev_size;
    473         c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
    474 
    475         err = jffs2_do_mount_fs(c);
    476         if (err)
    477                 return -err;
    478 
    479         D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n"));
    480         sb->s_root = jffs2_iget(sb, 1);
    481         if (IS_ERR(sb->s_root)) {
    482                 D1(printk(KERN_WARNING "get root inode failed\n"));
    483                 err = PTR_ERR(sb->s_root);
    484                 sb->s_root = NULL;
    485                 goto out_nodes;
    486         }
    487 
    488         return 0;
    489 
    490       out_nodes:
    491         jffs2_free_ino_caches(c);
    492         jffs2_free_raw_node_refs(c);
    493         free(c->blocks);
    494 
    495         return err;
    496 }
    497 
    498 static int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte)
    499 {
    500         extern cyg_mtab_entry cyg_mtab[], cyg_mtab_end;
    501         struct super_block *jffs2_sb = NULL;
    502         struct jffs2_sb_info *c;
    503         cyg_mtab_entry *m;
    504         cyg_io_handle_t t;
    505         Cyg_ErrNo err;
    506 
    507         D2(printf("jffs2_mount\n"));
    508 
    509         err = cyg_io_lookup(mte->devname, &t);
    510         if (err != ENOERR)
    511                 return -err;
    512 
    513         // Iterate through the mount table to see if we're mounted
    514         // FIXME: this should be done better - perhaps if the superblock
    515         // can be stored as an inode in the icache.
    516         for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) {
    517                 // stop if there are more than the configured maximum
    518                 if (m - &cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) {
    519                         m = &cyg_mtab_end;
    520                         break;
    521                 }
    522                 if (m->valid && strcmp(m->fsname, "jffs2") == 0 &&
    523                     strcmp(m->devname, mte->devname) == 0) {
    524                         jffs2_sb = (struct super_block *) m->data;
    525                 }
    526         }
    527 
    528         if (jffs2_sb == NULL) {
    529                 jffs2_sb = malloc(sizeof (struct super_block));
    530 
    531                 if (jffs2_sb == NULL)
    532                         return ENOMEM;
    533 
    534                 c = JFFS2_SB_INFO(jffs2_sb);
    535                 memset(jffs2_sb, 0, sizeof (struct super_block));
    536                 jffs2_sb->s_dev = t;
    537 
    538                 c->inocache_list = malloc(sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);
    539                 if (!c->inocache_list) {
    540                         free(jffs2_sb);
    541                         return ENOMEM;
    542                 }
    543                 memset(c->inocache_list, 0, sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);
    544                 if (n_fs_mounted++ == 0) {
    545                         jffs2_create_slab_caches(); // No error check, cannot fail
    546                         jffs2_compressors_init();
    547                 }
    548 
    549                 err = jffs2_read_super(jffs2_sb);
    550 
    551                 if (err) {
    552                         if (--n_fs_mounted == 0) {
    553                                 jffs2_destroy_slab_caches();
    554                                 jffs2_compressors_exit();
    555                         }
    556                        
    557                         free(jffs2_sb);
    558                         free(c->inocache_list);
    559                         return err;
    560                 }
    561 
    562                 jffs2_sb->s_root->i_parent = jffs2_sb->s_root;  // points to itself, no dotdot paths above mountpoint
    563                 jffs2_sb->s_root->i_cache_prev = NULL;  // root inode, so always null
    564                 jffs2_sb->s_root->i_cache_next = NULL;
    565                 jffs2_sb->s_root->i_count = 1;  // Ensures the root inode is always in ram until umount
    566 
    567                 D2(printf("jffs2_mount erasing pending blocks\n"));
    568 #ifdef CYGOPT_FS_JFFS2_WRITE
    569                 if (!jffs2_is_readonly(c))
    570                     jffs2_erase_pending_blocks(c,0);
    571 #endif
    572 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
    573                 jffs2_start_garbage_collect_thread(c);
    574 #endif
    575         }
    576         mte->data = (CYG_ADDRWORD) jffs2_sb;
    577 
    578         jffs2_sb->s_mount_count++;
    579         mte->root = (cyg_dir) jffs2_sb->s_root;
    580         D2(printf("jffs2_mounted superblock at %x\n", mte->root));
    581 
    582         return ENOERR;
    583 }
    584 
    585 extern cyg_dir cyg_cdir_dir;
    586 extern cyg_mtab_entry *cyg_cdir_mtab_entry;
    587 
    588 // -------------------------------------------------------------------------
    589 // jffs2_umount()
    590 // Unmount the filesystem.
    591 
    592 static int jffs2_umount(cyg_mtab_entry * mte)
    593 {
    594         struct _inode *root = (struct _inode *) mte->root;
    595         struct super_block *jffs2_sb = root->i_sb;
    596         struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb);
    597         struct jffs2_full_dirent *fd, *next;
    598 
    599         D2(printf("jffs2_umount\n"));
    600 
    601         // Only really umount if this is the only mount
    602         if (jffs2_sb->s_mount_count == 1) {
    603                 icache_evict(root, NULL);
    604                 if (root->i_cache_next != NULL) {
    605                         struct _inode *inode = root;
    606                         printf("Refuse to unmount.\n");
    607                         while (inode) {
    608                                 printf("Ino #%u has use count %d\n",
    609                                        inode->i_ino, inode->i_count);
    610                                 inode = inode->i_cache_next;
    611                         }
    612                         // root icount was set to 1 on mount
    613                         return EBUSY;
    614                 }
    615                 if (root->i_count == 2 &&
    616                     cyg_cdir_mtab_entry == mte &&
    617                     cyg_cdir_dir == (cyg_dir)root &&
    618                     !strcmp(mte->name, "/")) {
    619                         /* If we were mounted on root, there's no
    620                            way for the cwd to change out and free
    621                            the file system for unmounting. So we hack
    622                            it -- if cwd is '/' we unset it. Perhaps
    623                            we should allow chdir(NULL) to unset
    624                            cyg_cdir_dir? */
    625                         cyg_cdir_dir = CYG_DIR_NULL;
    626                         jffs2_iput(root);
    627                 }
    628                 /* Argh. The fileio code sets this; never clears it */
    629                 if (cyg_cdir_mtab_entry == mte)
    630                         cyg_cdir_mtab_entry = NULL;
    631 
    632                 if (root->i_count != 1) {
    633                         printf("Ino #1 has use count %d\n",
    634                                root->i_count);
    635                         return EBUSY;
    636                 }
    637 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
    638                 jffs2_stop_garbage_collect_thread(c);
    639 #endif
    640                 jffs2_iput(root);       // Time to free the root inode
    641 
    642                 // free directory entries
    643                 for (fd = root->jffs2_i.dents; fd; fd = next) {
    644                   next=fd->next;
    645                   jffs2_free_full_dirent(fd);
    646                 }
    647 
    648                 free(root);
    649                 //Clear root inode
    650                 //root_i = NULL;
    651 
    652                 // Clean up the super block and root inode
    653                 jffs2_free_ino_caches(c);
    654                 jffs2_free_raw_node_refs(c);
    655                 free(c->blocks);
    656                 free(c->inocache_list);
    657                 free(jffs2_sb);
    658                 // Clear superblock & root pointer
    659                 mte->root = CYG_DIR_NULL;
    660                 mte->data = 0;
    661                 mte->fs->data = 0;      // fstab entry, visible to all mounts. No current mount
    662                 // That's all folks.
    663                 D2(printf("jffs2_umount No current mounts\n"));
    664         } else {
    665                 jffs2_sb->s_mount_count--;
    666         }
    667         if (--n_fs_mounted == 0) {
    668                 jffs2_destroy_slab_caches();       
    669                 jffs2_compressors_exit();
    670         }
    671         return ENOERR;
    672 }
    673 
    674 // -------------------------------------------------------------------------
    675 // jffs2_open()
    676 // Open a file for reading or writing.
    677 
    678 static int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    679                       int mode, cyg_file * file)
    680 {
    681 
    682         jffs2_dirsearch ds;
    683         struct _inode *node = NULL;
    684         int err;
    685 
    686         D2(printf("jffs2_open\n"));
    687 
    688         /* If no chdir has been called and we were the first file system
    689            mounted, we get called with dir == NULL. Deal with it */
    690         if (!dir)
    691                 dir = mte->root;
    692 
    693 #ifndef CYGOPT_FS_JFFS2_WRITE
    694         if (mode & (O_CREAT|O_TRUNC|O_WRONLY))
    695                 return EROFS;
    696 #endif
    697         init_dirsearch(&ds, (struct _inode *) dir,
    698                        (const unsigned char *) name);
    699 
    700         err = jffs2_find(&ds);
    701 
    702         if (err == ENOENT) {
    703 #ifdef CYGOPT_FS_JFFS2_WRITE
    704                 if (ds.last && (mode & O_CREAT)) {
    705 
    706                         // No node there, if the O_CREAT bit is set then we must
    707                         // create a new one. The dir and name fields of the dirsearch
    708                         // object will have been updated so we know where to put it.
    709 
    710                         err = jffs2_create(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR|S_IFREG, &node);
    711 
    712                         if (err != 0) {
    713                                 //Possible orphaned inode on the flash - but will be gc'd
    714                                 jffs2_iput(ds.dir);
    715                                 return -err;
    716                         }
    717 
    718                         err = ENOERR;
    719                 }
    720 #endif
    721         } else if (err == ENOERR) {
    722                 // The node exists. If the O_CREAT and O_EXCL bits are set, we
    723                 // must fail the open.
    724 
    725                 if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
    726                         jffs2_iput(ds.node);
    727                         err = EEXIST;
    728                 } else
    729                         node = ds.node;
    730         }
    731 
    732         // Finished with the directory now
    733         jffs2_iput(ds.dir);
    734 
    735         if (err != ENOERR)
    736                 return err;
    737 
    738         // Check that we actually have a file here
    739         if (S_ISDIR(node->i_mode)) {
    740                 jffs2_iput(node);
    741                 return EISDIR;
    742         }
    743 
    744              // If the O_TRUNC bit is set we must clean out the file data.
    745         if (mode & O_TRUNC) {
    746 #ifdef CYGOPT_FS_JFFS2_WRITE
    747              err = jffs2_truncate_file(node);
    748              if (err) {
    749                   jffs2_iput(node);
    750                   return err;
    751              }
    752 #else
    753              jffs2_iput(node);
    754              return EROFS;
    755 #endif
    756         }
    757        
    758         // Initialise the file object
    759         file->f_flag |= mode & CYG_FILE_MODE_MASK;
    760         file->f_type = CYG_FILE_TYPE_FILE;
    761         file->f_ops = &jffs2_fileops;
    762         file->f_offset = (mode & O_APPEND) ? node->i_size : 0;
    763         file->f_data = (CYG_ADDRWORD) node;
    764         file->f_xops = 0;
    765 
    766         return ENOERR;
    767 }
    768 
    769 #ifdef CYGOPT_FS_JFFS2_WRITE
    770 // -------------------------------------------------------------------------
    771 // jffs2_ops_unlink()
    772 // Remove a file link from its directory.
    773 
    774 static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
    775 {
    776         jffs2_dirsearch ds;
    777         int err;
    778 
    779         D2(printf("jffs2_ops_unlink\n"));
    780 
    781         init_dirsearch(&ds, (struct _inode *) dir,
    782                        (const unsigned char *)name);
    783 
    784         err = jffs2_find(&ds);
    785 
    786         if (err != ENOERR) {
    787                 jffs2_iput(ds.dir);
    788                 return err;
    789         }
    790 
    791         // Cannot unlink directories, use rmdir() instead
    792         if (S_ISDIR(ds.node->i_mode)) {
    793                 jffs2_iput(ds.dir);
    794                 jffs2_iput(ds.node);
    795                 return EPERM;
    796         }
    797 
    798         // Delete it from its directory
    799 
    800         err = jffs2_unlink(ds.dir, ds.node, ds.name);
    801         jffs2_iput(ds.dir);
    802         jffs2_iput(ds.node);
    803 
    804         return -err;
    805 }
    806 
    807 // -------------------------------------------------------------------------
    808 // jffs2_ops_mkdir()
    809 // Create a new directory.
    810 
    811 static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
    812 {
    813         jffs2_dirsearch ds;
    814         int err;
    815 
    816         D2(printf("jffs2_ops_mkdir\n"));
    817 
    818         init_dirsearch(&ds, (struct _inode *) dir,
    819                        (const unsigned char *)name);
    820 
    821         err = jffs2_find(&ds);
    822 
    823         if (err == ENOENT) {
    824                 if (ds.last) {
    825                         // The entry does not exist, and it is the last element in
    826                         // the pathname, so we can create it here.
    827 
    828                         err = -jffs2_mkdir(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR);
    829                 }
    830                 // If this was not the last element, then an intermediate
    831                 // directory does not exist.
    832         } else {
    833                 // If there we no error, something already exists with that
    834                 // name, so we cannot create another one.
    835                if (err == ENOERR) {
    836                         jffs2_iput(ds.node);
    837                         err = EEXIST;
    838                }
    839         }
    840         jffs2_iput(ds.dir);
    841         return err;
    842 }
    843 
    844 // -------------------------------------------------------------------------
    845 // jffs2_ops_rmdir()
    846 // Remove a directory.
    847 
    848 static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
    849 {
    850         jffs2_dirsearch ds;
    851         int err;
    852 
    853         D2(printf("jffs2_ops_rmdir\n"));
    854 
    855         init_dirsearch(&ds, (struct _inode *) dir,
    856                        (const unsigned char *)name);
    857 
    858         err = jffs2_find(&ds);
    859 
    860         if (err != ENOERR) {
    861                 jffs2_iput(ds.dir);
    862                 return err;
    863         }
    864 
    865         // Check that this is actually a directory.
    866         if (!S_ISDIR(ds.node->i_mode)) {
    867                 jffs2_iput(ds.dir);
    868                 jffs2_iput(ds.node);
    869                 return EPERM;
    870         }
    871 
    872         err = jffs2_rmdir(ds.dir, ds.node, ds.name);
    873 
    874         jffs2_iput(ds.dir);
    875         jffs2_iput(ds.node);
    876         return -err;
    877 }
    878 
    879 // -------------------------------------------------------------------------
    880 // jffs2_ops_rename()
    881 // Rename a file/dir.
    882 
    883 static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,
    884                             const char *name1, cyg_dir dir2, const char *name2)
    885 {
    886         jffs2_dirsearch ds1, ds2;
    887         int err;
    888 
    889         D2(printf("jffs2_ops_rename\n"));
    890 
    891         init_dirsearch(&ds1, (struct _inode *) dir1,
    892                        (const unsigned char *)name1);
    893 
    894         err = jffs2_find(&ds1);
    895 
    896         if (err != ENOERR) {
    897                 jffs2_iput(ds1.dir);
    898                 return err;
    899         }
    900 
    901         init_dirsearch(&ds2, (struct _inode *) dir2,
    902                        (const unsigned char *)name2);
    903 
    904         err = jffs2_find(&ds2);
    905 
    906         // Allow through renames to non-existent objects.
    907         if (ds2.last && err == ENOENT) {
    908                 ds2.node = NULL;
    909                 err = ENOERR;
    910         }
    911 
    912         if (err != ENOERR) {
    913                 jffs2_iput(ds1.dir);
    914                 jffs2_iput(ds1.node);
    915                 jffs2_iput(ds2.dir);
    916                 return err;
    917         }
    918 
    919         // Null rename, just return
    920         if (ds1.node == ds2.node) {
    921                 err = ENOERR;
    922                 goto out;
    923         }
    924 
    925         // First deal with any entry that is at the destination
    926         if (ds2.node) {
    927                 // Check that we are renaming like-for-like
    928 
    929                 if (!S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode)) {
    930                         err = EISDIR;
    931                         goto out;
    932                 }
    933 
    934                 if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode)) {
    935                         err = ENOTDIR;
    936                         goto out;
    937                 }
    938 
    939                 // Now delete the destination directory entry
    940                 /* Er, what happened to atomicity of rename()? */
    941                 err = -jffs2_unlink(ds2.dir, ds2.node, ds2.name);
    942 
    943                 if (err != 0)
    944                         goto out;
    945 
    946         }
    947         // Now we know that there is no clashing node at the destination,
    948         // make a new direntry at the destination and delete the old entry
    949         // at the source.
    950 
    951         err = -jffs2_rename(ds1.dir, ds1.node, ds1.name, ds2.dir, ds2.name);
    952 
    953         // Update directory times
    954         if (!err)
    955                 ds1.dir->i_ctime =
    956                     ds1.dir->i_mtime =
    957                     ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();
    958  out:
    959         jffs2_iput(ds1.dir);
    960         if (S_ISDIR(ds1.node->i_mode)) {
    961                 /* Renamed a directory to elsewhere... so fix up its
    962                    i_parent pointer and the i_counts of its old and
    963                    new parents. */
    964                 jffs2_iput(ds1.node->i_parent);
    965                 ds1.node->i_parent = ds2.dir;
    966                 /* We effectively increase its use count by not... */
    967         } else {
    968                 jffs2_iput(ds2.dir); /* ... doing this */
    969         }
    970         jffs2_iput(ds1.node);
    971         if (ds2.node)
    972                 jffs2_iput(ds2.node);
    973  
    974         return err;
    975 }
    976 
    977 // -------------------------------------------------------------------------
    978 // jffs2_ops_link()
    979 // Make a new directory entry for a file.
    980 
    981 static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1,
    982                           cyg_dir dir2, const char *name2, int type)
    983 {
    984         jffs2_dirsearch ds1, ds2;
    985         int err;
    986 
    987         D2(printf("jffs2_ops_link\n"));
    988 
    989         // Only do hard links for now in this filesystem
    990         if (type != CYG_FSLINK_HARD)
    991                 return EINVAL;
    992 
    993         init_dirsearch(&ds1, (struct _inode *) dir1,
    994                        (const unsigned char *) name1);
    995 
    996         err = jffs2_find(&ds1);
    997 
    998         if (err != ENOERR) {
    999                 jffs2_iput(ds1.dir);
    1000                 return err;
    1001         }
    1002 
    1003         init_dirsearch(&ds2, (struct _inode *) dir2,
    1004                        (const unsigned char *) name2);
    1005 
    1006         err = jffs2_find(&ds2);
    1007 
    1008         // Don't allow links to existing objects
    1009         if (err == ENOERR) {
    1010                 jffs2_iput(ds1.dir);
    1011                 jffs2_iput(ds1.node);
    1012                 jffs2_iput(ds2.dir);
    1013                 jffs2_iput(ds2.node);
    1014                 return EEXIST;
    1015         }
    1016 
    1017         // Allow through links to non-existing terminal objects
    1018         if (ds2.last && err == ENOENT) {
    1019                 ds2.node = NULL;
    1020                 err = ENOERR;
    1021         }
    1022 
    1023         if (err != ENOERR) {
    1024                 jffs2_iput(ds1.dir);
    1025                 jffs2_iput(ds1.node);
    1026                 jffs2_iput(ds2.dir);
    1027                 return err;
    1028         }
    1029 
    1030         // Now we know that there is no existing node at the destination,
    1031         // make a new direntry at the destination.
    1032 
    1033         err = jffs2_link(ds1.node, ds2.dir, ds2.name);
    1034 
    1035         if (err == 0)
    1036                 ds1.node->i_ctime =
    1037                     ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();
    1038 
    1039         jffs2_iput(ds1.dir);
    1040         jffs2_iput(ds1.node);
    1041         jffs2_iput(ds2.dir);
    1042 
    1043         return -err;
    1044 }
    1045 #endif /* CYGOPT_FS_JFFS2_WRITE */
    1046 // -------------------------------------------------------------------------
    1047 // jffs2_opendir()
    1048 // Open a directory for reading.
    1049 
    1050 static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    1051                          cyg_file * file)
    1052 {
    1053         jffs2_dirsearch ds;
    1054         int err;
    1055 
    1056         D2(printf("jffs2_opendir\n"));
    1057 
    1058         init_dirsearch(&ds, (struct _inode *) dir,
    1059                        (const unsigned char *) name);
    1060 
    1061         err = jffs2_find(&ds);
    1062 
    1063         jffs2_iput(ds.dir);
    1064 
    1065         if (err != ENOERR)
    1066                 return err;
    1067 
    1068         // check it is really a directory.
    1069         if (!S_ISDIR(ds.node->i_mode)) {
    1070                 jffs2_iput(ds.node);
    1071                 return ENOTDIR;
    1072         }
    1073 
    1074         // Initialize the file object, setting the f_ops field to a
    1075         // special set of file ops.
    1076 
    1077         file->f_type = CYG_FILE_TYPE_FILE;
    1078         file->f_ops = &jffs2_dirops;
    1079         file->f_offset = 0;
    1080         file->f_data = (CYG_ADDRWORD) ds.node;
    1081         file->f_xops = 0;
    1082 
    1083         return ENOERR;
    1084 
    1085 }
    1086 
    1087 // -------------------------------------------------------------------------
    1088 // jffs2_chdir()
    1089 // Change directory support.
    1090 
    1091 static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    1092                        cyg_dir * dir_out)
    1093 {
    1094         D2(printf("jffs2_chdir\n"));
    1095 
    1096         if (dir_out != NULL) {
    1097                 // This is a request to get a new directory pointer in
    1098                 // *dir_out.
    1099 
    1100                 jffs2_dirsearch ds;
    1101                 int err;
    1102 
    1103                 init_dirsearch(&ds, (struct _inode *) dir,
    1104                                (const unsigned char *) name);
    1105 
    1106                 err = jffs2_find(&ds);
    1107                 jffs2_iput(ds.dir);
    1108 
    1109                 if (err != ENOERR)
    1110                         return err;
    1111 
    1112                 // check it is a directory
    1113                 if (!S_ISDIR(ds.node->i_mode)) {
    1114                         jffs2_iput(ds.node);
    1115                         return ENOTDIR;
    1116                 }
    1117                
    1118                 // Pass it out
    1119                 *dir_out = (cyg_dir) ds.node;
    1120         } else {
    1121                 // If no output dir is required, this means that the mte and
    1122                 // dir arguments are the current cdir setting and we should
    1123                 // forget this fact.
    1124 
    1125                 struct _inode *node = (struct _inode *) dir;
    1126 
    1127                 // Just decrement directory reference count.
    1128                 jffs2_iput(node);
    1129         }
    1130 
    1131         return ENOERR;
    1132 }
    1133 
    1134 // -------------------------------------------------------------------------
    1135 // jffs2_stat()
    1136 // Get struct stat info for named object.
    1137 
    1138 static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    1139                       struct stat *buf)
    1140 {
    1141         jffs2_dirsearch ds;
    1142         int err;
    1143 
    1144         D2(printf("jffs2_stat\n"));
    1145 
    1146         init_dirsearch(&ds, (struct _inode *) dir,
    1147                        (const unsigned char *) name);
    1148 
    1149         err = jffs2_find(&ds);
    1150         jffs2_iput(ds.dir);
    1151 
    1152         if (err != ENOERR)
    1153                 return err;
    1154 
    1155         // Fill in the status
    1156         buf->st_mode = ds.node->i_mode;
    1157         buf->st_ino = ds.node->i_ino;
    1158         buf->st_dev = 0;
    1159         buf->st_nlink = ds.node->i_nlink;
    1160         buf->st_uid = ds.node->i_uid;
    1161         buf->st_gid = ds.node->i_gid;
    1162         buf->st_size = ds.node->i_size;
    1163         buf->st_atime = ds.node->i_atime;
    1164         buf->st_mtime = ds.node->i_mtime;
    1165         buf->st_ctime = ds.node->i_ctime;
    1166 
    1167         jffs2_iput(ds.node);
    1168 
    1169         return ENOERR;
    1170 }
    1171 
    1172 // -------------------------------------------------------------------------
    1173 // jffs2_getinfo()
    1174 // Getinfo. Currently only support pathconf().
    1175 
    1176 static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    1177                          int key, void *buf, int len)
    1178 {
    1179         jffs2_dirsearch ds;
    1180         int err;
    1181 
    1182         D2(printf("jffs2_getinfo\n"));
    1183 
    1184         init_dirsearch(&ds, (struct _inode *) dir,
    1185                        (const unsigned char *) name);
    1186 
    1187         err = jffs2_find(&ds);
    1188         jffs2_iput(ds.dir);
    1189 
    1190         if (err != ENOERR)
    1191                 return err;
    1192 
    1193         switch (key) {
    1194         case FS_INFO_CONF:
    1195                 err = jffs2_pathconf(ds.node, (struct cyg_pathconf_info *) buf);
    1196                 break;
    1197 
    1198         default:
    1199                 err = EINVAL;
    1200         }
    1201 
    1202         jffs2_iput(ds.node);
    1203         return err;
    1204 }
    1205 
    1206 // -------------------------------------------------------------------------
    1207 // jffs2_setinfo()
    1208 // Setinfo. Nothing to support here at present.
    1209 
    1210 static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
    1211                          int key, void *buf, int len)
    1212 {
    1213         // No setinfo keys supported at present
    1214 
    1215         D2(printf("jffs2_setinfo\n"));
    1216 
    1217         return EINVAL;
    1218 }
    1219 
    1220 //==========================================================================
    1221 // File operations
    1222 
    1223 // -------------------------------------------------------------------------
    1224 // jffs2_fo_read()
    1225 // Read data from the file.
    1226 
    1227 static int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
    1228 {
    1229         struct _inode *inode = (struct _inode *) fp->f_data;
    1230         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
    1231         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
    1232         int i;
    1233         ssize_t resid = uio->uio_resid;
    1234         off_t pos = fp->f_offset;
    1235 
    1236         down(&f->sem);
    1237 
    1238         // Loop over the io vectors until there are none left
    1239         for (i = 0; i < uio->uio_iovcnt && pos < inode->i_size; i++) {
    1240                 int ret;
    1241                 cyg_iovec *iov = &uio->uio_iov[i];
    1242                 off_t len = min(iov->iov_len, inode->i_size - pos);
    1243 
    1244                 D2(printf("jffs2_fo_read inode size %d\n", inode->i_size));
    1245 
    1246                 ret =
    1247                     jffs2_read_inode_range(c, f,
    1248                                            (unsigned char *) iov->iov_base, pos,
    1249                                            len);
    1250                 if (ret) {
    1251                         D1(printf
    1252                            ("jffs2_fo_read(): read_inode_range failed %d\n",
    1253                             ret));
    1254                         uio->uio_resid = resid;
    1255                         up(&f->sem);
    1256                         return -ret;
    1257                 }
    1258                 resid -= len;
    1259                 pos += len;
    1260         }
    1261 
    1262         // We successfully read some data, update the node's access time
    1263         // and update the file offset and transfer residue.
    1264 
    1265         inode->i_atime = cyg_timestamp();
    1266 
    1267         uio->uio_resid = resid;
    1268         fp->f_offset = pos;
    1269 
    1270         up(&f->sem);
    1271 
    1272         return ENOERR;
    1273 }
    1274 
    1275 
    1276 #ifdef CYGOPT_FS_JFFS2_WRITE
    127796// -------------------------------------------------------------------------
    127897// jffs2_fo_write()
     
    1284103        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
    1285104        struct jffs2_full_dnode *fn;
    1286         uint32_t phys_ofs, alloc_len;
     105        uint32_t alloc_len;
    1287106        int ret = 0;
    1288107
     
    1291110                  (unsigned int)inode->i_size, offset));
    1292111
    1293         ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloc_len, ALLOC_NORMAL);
     112        ret = jffs2_reserve_space(c, sizeof(*ri), &alloc_len, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
    1294113        if (ret)
    1295114                return ret;
    1296115
    1297         down(&f->sem);
     116        mutex_lock(&f->sem);
    1298117
    1299118        ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
     
    1312131        ri->data_crc = cpu_to_je32(0);
    1313132               
    1314         fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
     133        fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
    1315134        jffs2_complete_reservation(c);
    1316135        if (IS_ERR(fn)) {
    1317136                ret = PTR_ERR(fn);
    1318                 up(&f->sem);
     137                mutex_unlock(&f->sem);
    1319138                return ret;
    1320139        }
     
    1329148                jffs2_mark_node_obsolete(c, fn->raw);
    1330149                jffs2_free_full_dnode(fn);
    1331                 up(&f->sem);
     150                mutex_unlock(&f->sem);
    1332151                return ret;
    1333152        }
    1334153        inode->i_size = offset;
    1335         up(&f->sem);
     154        mutex_unlock(&f->sem);
    1336155        return 0;
    1337156}
    1338157
    1339 // jffs2_fo_open()
    1340 // Truncate a file
    1341 static int jffs2_truncate_file (struct _inode *inode)
    1342 {
    1343      struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
    1344      struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
    1345      struct jffs2_full_dnode *new_metadata, * old_metadata;
    1346      struct jffs2_raw_inode *ri;
    1347      uint32_t phys_ofs, alloclen;
    1348      int err;
    1349      
    1350      ri = jffs2_alloc_raw_inode();
    1351      if (!ri) {
    1352           return ENOMEM;
    1353      }
    1354      err = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
    1355      
    1356      if (err) {
    1357           jffs2_free_raw_inode(ri);
    1358           return err;
    1359      }
    1360      down(&f->sem);
    1361      ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
    1362      ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
    1363      ri->totlen = cpu_to_je32(sizeof(*ri));
    1364      ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
    1365      
    1366      ri->ino = cpu_to_je32(inode->i_ino);
    1367      ri->version = cpu_to_je32(++f->highest_version);
    1368      
    1369      ri->uid = cpu_to_je16(inode->i_uid);
    1370      ri->gid = cpu_to_je16(inode->i_gid);
    1371      ri->mode = cpu_to_jemode(inode->i_mode);
    1372      ri->isize = cpu_to_je32(0);
    1373      ri->atime = cpu_to_je32(inode->i_atime);
    1374      ri->mtime = cpu_to_je32(cyg_timestamp());
    1375      ri->offset = cpu_to_je32(0);
    1376      ri->csize = ri->dsize = cpu_to_je32(0);
    1377      ri->compr = JFFS2_COMPR_NONE;
    1378      ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
    1379      ri->data_crc = cpu_to_je32(0);
    1380      new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0,
    1381                                       phys_ofs, ALLOC_NORMAL);
    1382      if (IS_ERR(new_metadata)) {
    1383           jffs2_complete_reservation(c);
    1384           jffs2_free_raw_inode(ri);
    1385           up(&f->sem);
    1386           return PTR_ERR(new_metadata);
    1387      }
    1388      
    1389      /* It worked. Update the inode */
    1390      inode->i_mtime = cyg_timestamp();
    1391      inode->i_size = 0;
    1392      old_metadata = f->metadata;
    1393      jffs2_truncate_fragtree (c, &f->fragtree, 0);
    1394      f->metadata = new_metadata;
    1395      if (old_metadata) {
    1396           jffs2_mark_node_obsolete(c, old_metadata->raw);
    1397           jffs2_free_full_dnode(old_metadata);
    1398      }
    1399      jffs2_free_raw_inode(ri);
    1400      
    1401      up(&f->sem);
    1402      jffs2_complete_reservation(c);
    1403      
    1404      return 0;
    1405 }
    1406 
    1407 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
    1408 {
    1409         struct _inode *inode = (struct _inode *) fp->f_data;
    1410         off_t pos = fp->f_offset;
    1411         ssize_t resid = uio->uio_resid;
    1412         struct jffs2_raw_inode ri;
     158static int jffs2_do_setattr (struct _inode *inode, struct iattr *iattr)
     159{
     160        struct jffs2_full_dnode *old_metadata, *new_metadata;
    1413161        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
    1414162        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
    1415         int i;
    1416 
    1417         // If the APPEND mode bit was supplied, force all writes to
    1418         // the end of the file.
    1419         if (fp->f_flag & CYG_FAPPEND)
    1420                 pos = fp->f_offset = inode->i_size;
    1421 
    1422         if (pos < 0)
    1423                 return EINVAL;
     163        struct jffs2_raw_inode *ri;
     164        unsigned char *mdata = NULL;
     165        int mdatalen = 0;
     166        unsigned int ivalid;
     167        uint32_t alloclen;
     168        int ret;
     169        int alloc_type = ALLOC_NORMAL;
     170
     171        jffs2_dbg(1, "%s(): ino #%lu\n", __func__, inode->i_ino);
     172
     173        /* Special cases - we don't want more than one data node
     174           for these types on the medium at any time. So setattr
     175           must read the original data associated with the node
     176           (i.e. the device numbers or the target name) and write
     177           it out again with the appropriate data attached */
     178        if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
     179                return -EIO;
     180        } else if (S_ISLNK(inode->i_mode)) {
     181                mutex_lock(&f->sem);
     182                mdatalen = f->metadata->size;
     183                mdata = kmalloc(f->metadata->size, GFP_USER);
     184                if (!mdata) {
     185                        mutex_unlock(&f->sem);
     186                        return -ENOMEM;
     187                }
     188                ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
     189                if (ret) {
     190                        mutex_unlock(&f->sem);
     191                        kfree(mdata);
     192                        return ret;
     193                }
     194                mutex_unlock(&f->sem);
     195                jffs2_dbg(1, "%s(): Writing %d bytes of symlink target\n",
     196                          __func__, mdatalen);
     197        }
     198
     199        ri = jffs2_alloc_raw_inode();
     200        if (!ri) {
     201                if (S_ISLNK(inode->i_mode))
     202                        kfree(mdata);
     203                return -ENOMEM;
     204        }
     205
     206        ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
     207                                  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
     208        if (ret) {
     209                jffs2_free_raw_inode(ri);
     210                if (S_ISLNK(inode->i_mode))
     211                         kfree(mdata);
     212                return ret;
     213        }
     214        mutex_lock(&f->sem);
     215        ivalid = iattr->ia_valid;
     216
     217        ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
     218        ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
     219        ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen);
     220        ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
     221
     222        ri->ino = cpu_to_je32(inode->i_ino);
     223        ri->version = cpu_to_je32(++f->highest_version);
     224
     225        ri->uid = cpu_to_je16((ivalid & ATTR_UID)?
     226                from_kuid(&init_user_ns, iattr->ia_uid):i_uid_read(inode));
     227        ri->gid = cpu_to_je16((ivalid & ATTR_GID)?
     228                from_kgid(&init_user_ns, iattr->ia_gid):i_gid_read(inode));
     229
     230        if (ivalid & ATTR_MODE)
     231                ri->mode = cpu_to_jemode(iattr->ia_mode);
     232        else
     233                ri->mode = cpu_to_jemode(inode->i_mode);
     234
     235
     236        ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size);
     237        ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime));
     238        ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime));
     239        ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime));
     240
     241        ri->offset = cpu_to_je32(0);
     242        ri->csize = ri->dsize = cpu_to_je32(mdatalen);
     243        ri->compr = JFFS2_COMPR_NONE;
     244        if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
     245                /* It's an extension. Make it a hole node */
     246                ri->compr = JFFS2_COMPR_ZERO;
     247                ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
     248                ri->offset = cpu_to_je32(inode->i_size);
     249        } else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
     250                /* For truncate-to-zero, treat it as deletion because
     251                   it'll always be obsoleting all previous nodes */
     252                alloc_type = ALLOC_DELETION;
     253        }
     254        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
     255        if (mdatalen)
     256                ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
     257        else
     258                ri->data_crc = cpu_to_je32(0);
     259
     260        new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
     261        if (S_ISLNK(inode->i_mode))
     262                kfree(mdata);
     263
     264        if (IS_ERR(new_metadata)) {
     265                jffs2_complete_reservation(c);
     266                jffs2_free_raw_inode(ri);
     267                mutex_unlock(&f->sem);
     268                return PTR_ERR(new_metadata);
     269        }
     270        /* It worked. Update the inode */
     271        inode->i_atime = ITIME(je32_to_cpu(ri->atime));
     272        inode->i_ctime = ITIME(je32_to_cpu(ri->ctime));
     273        inode->i_mtime = ITIME(je32_to_cpu(ri->mtime));
     274        inode->i_mode = jemode_to_cpu(ri->mode);
     275        i_uid_write(inode, je16_to_cpu(ri->uid));
     276        i_gid_write(inode, je16_to_cpu(ri->gid));
     277
     278
     279        old_metadata = f->metadata;
     280
     281        if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
     282                jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size);
     283
     284        if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
     285                jffs2_add_full_dnode_to_inode(c, f, new_metadata);
     286                inode->i_size = iattr->ia_size;
     287                f->metadata = NULL;
     288        } else {
     289                f->metadata = new_metadata;
     290        }
     291        if (old_metadata) {
     292                jffs2_mark_node_obsolete(c, old_metadata->raw);
     293                jffs2_free_full_dnode(old_metadata);
     294        }
     295        jffs2_free_raw_inode(ri);
     296
     297        mutex_unlock(&f->sem);
     298        jffs2_complete_reservation(c);
     299
     300        /* We have to do the truncate_setsize() without f->sem held, since
     301           some pages may be locked and waiting for it in readpage().
     302           We are protected from a simultaneous write() extending i_size
     303           back past iattr->ia_size, because do_truncate() holds the
     304           generic inode semaphore. */
     305        if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
     306                truncate_setsize(inode, iattr->ia_size);
     307        }       
     308
     309        return 0;
     310}
     311
     312typedef struct {
     313        struct super_block sb;
     314        struct jffs2_inode_cache *inode_cache[];
     315} rtems_jffs2_fs_info;
     316
     317static void rtems_jffs2_do_lock(const struct super_block *sb)
     318{
     319        rtems_status_code sc = rtems_semaphore_obtain(sb->s_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     320        assert(sc == RTEMS_SUCCESSFUL);
     321}
     322
     323static void rtems_jffs2_do_unlock(const struct super_block *sb)
     324{
     325        rtems_status_code sc = rtems_semaphore_release(sb->s_mutex);
     326        assert(sc == RTEMS_SUCCESSFUL);
     327}
     328
     329static void rtems_jffs2_free_directory_entries(struct _inode *inode)
     330{
     331        struct jffs2_full_dirent *current = inode->jffs2_i.dents;
     332
     333        while (current != NULL) {
     334                struct jffs2_full_dirent *victim = current;
     335
     336                current = victim->next;
     337                jffs2_free_full_dirent(victim);
     338        }
     339}
     340
     341static void rtems_jffs2_flash_control_destroy(rtems_jffs2_flash_control *fc)
     342{
     343        if (fc->destroy != NULL) {
     344                (*fc->destroy)(fc);
     345        }
     346}
     347static void rtems_jffs2_compressor_control_destroy(rtems_jffs2_compressor_control *cc)
     348{
     349        if (cc != NULL && cc->destroy != NULL) {
     350                (*cc->destroy)(cc);
     351        }
     352}
     353
     354
     355static void rtems_jffs2_free_fs_info(rtems_jffs2_fs_info *fs_info, bool do_mount_fs_was_successful)
     356{
     357        struct super_block *sb = &fs_info->sb;
     358        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
     359
     360        if (do_mount_fs_was_successful) {
     361                jffs2_free_ino_caches(c);
     362                jffs2_free_raw_node_refs(c);
     363                free(c->blocks);
     364        }
     365
     366        if (sb->s_mutex != 0) {
     367                rtems_status_code sc = rtems_semaphore_delete(sb->s_mutex);
     368                assert(sc == RTEMS_SUCCESSFUL);
     369        }
     370
     371        rtems_jffs2_flash_control_destroy(fs_info->sb.s_flash_control);
     372        rtems_jffs2_compressor_control_destroy(fs_info->sb.s_compressor_control);
     373
     374        free(fs_info);
     375}
     376
     377static int rtems_jffs2_eno_to_rv_and_errno(int eno)
     378{
     379        if (eno == 0) {
     380                return 0;
     381        } else {
     382                errno = eno;
     383
     384                return -1;
     385        }
     386}
     387
     388static struct _inode *rtems_jffs2_get_inode_by_location(
     389        const rtems_filesystem_location_info_t *loc
     390)
     391{
     392        return loc->node_access;
     393}
     394
     395static struct _inode *rtems_jffs2_get_inode_by_iop(
     396        const rtems_libio_t *iop
     397)
     398{
     399        return iop->pathinfo.node_access;
     400}
     401
     402static int rtems_jffs2_fstat(
     403        const rtems_filesystem_location_info_t *loc,
     404        struct stat *buf
     405)
     406{
     407        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     408
     409        rtems_jffs2_do_lock(inode->i_sb);
     410
     411        buf->st_blksize = PAGE_SIZE;
     412        buf->st_mode = inode->i_mode;
     413        buf->st_ino = inode->i_ino;
     414        buf->st_nlink = inode->i_nlink;
     415        buf->st_uid = inode->i_uid;
     416        buf->st_gid = inode->i_gid;
     417        buf->st_size = inode->i_size;
     418        buf->st_atime = inode->i_atime;
     419        buf->st_mtime = inode->i_mtime;
     420        buf->st_ctime = inode->i_ctime;
     421
     422        rtems_jffs2_do_unlock(inode->i_sb);
     423
     424        return 0;
     425}
     426
     427static int rtems_jffs2_fill_dirent(struct dirent *de, off_t off, uint32_t ino, const char *name)
     428{
     429        int eno = 0;
     430        size_t len;
     431
     432        memset(de, 0, sizeof(*de));
     433
     434        de->d_off = off * sizeof(*de);
     435        de->d_reclen = sizeof(*de);
     436        de->d_ino = ino;
     437
     438        len = strlen(name);
     439        de->d_namlen = len;
     440
     441        if (len < sizeof(de->d_name) - 1) {
     442                memcpy(&de->d_name[0], name, len);
     443        } else {
     444                eno = EOVERFLOW;
     445        }
     446
     447        return eno;
     448}
     449
     450static ssize_t rtems_jffs2_dir_read(rtems_libio_t *iop, void *buf, size_t len)
     451{
     452        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
     453        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
     454        struct dirent *de = buf;
     455        off_t fd_off = 2;
     456        int eno = 0;
     457        struct jffs2_full_dirent *fd;
     458        off_t begin;
     459        off_t end;
     460        off_t off;
     461
     462        rtems_jffs2_do_lock(inode->i_sb);
     463
     464        fd = f->dents;
     465        begin = iop->offset;
     466        end = begin + len / sizeof(*de);
     467        off = begin;
     468
     469        if (off == 0 && off < end) {
     470                eno = rtems_jffs2_fill_dirent(de, off, inode->i_ino, ".");
     471                assert(eno == 0);
     472                ++off;
     473                ++de;
     474        }
     475
     476        if (off == 1 && off < end) {
     477                eno = rtems_jffs2_fill_dirent(de, off, inode->i_parent->i_ino, "..");
     478                assert(eno == 0);
     479                ++off;
     480                ++de;
     481        }
     482
     483        while (eno == 0 && off < end && fd != NULL) {
     484                if (fd->ino != 0) {
     485                        if (off == fd_off) {
     486                                eno = rtems_jffs2_fill_dirent(de, off, fd->ino, fd->name);
     487                                ++off;
     488                                ++de;
     489                        }
     490
     491                        ++fd_off;
     492                }
     493
     494                fd = fd->next;
     495        }
     496
     497        rtems_jffs2_do_unlock(inode->i_sb);
     498
     499        if (eno == 0) {
     500                iop->offset = off;
     501
     502                return (off - begin) * sizeof(*de);
     503        } else {
     504                return rtems_jffs2_eno_to_rv_and_errno(eno);
     505        }
     506}
     507
     508static const rtems_filesystem_file_handlers_r rtems_jffs2_directory_handlers = {
     509        .open_h = rtems_filesystem_default_open,
     510        .close_h = rtems_filesystem_default_close,
     511        .read_h = rtems_jffs2_dir_read,
     512        .write_h = rtems_filesystem_default_write,
     513        .ioctl_h = rtems_filesystem_default_ioctl,
     514        .lseek_h = rtems_filesystem_default_lseek_directory,
     515        .fstat_h = rtems_jffs2_fstat,
     516        .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
     517        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
     518        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
     519        .fcntl_h = rtems_filesystem_default_fcntl
     520};
     521
     522static ssize_t rtems_jffs2_file_read(rtems_libio_t *iop, void *buf, size_t len)
     523{
     524        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
     525        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
     526        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
     527        int err = 0;
     528        off_t pos;
     529
     530        rtems_jffs2_do_lock(inode->i_sb);
     531
     532        pos = iop->offset;
     533
     534        if (pos >= inode->i_size) {
     535                len = 0;
     536        } else {
     537                uint32_t pos_32 = (uint32_t) pos;
     538                uint32_t max_available = inode->i_size - pos_32;
     539
     540                if (len > max_available) {
     541                        len = max_available;
     542                }
     543
     544                err = jffs2_read_inode_range(c, f, buf, pos_32, len);
     545        }
     546
     547        if (err == 0) {
     548                iop->offset += len;
     549        }
     550
     551        rtems_jffs2_do_unlock(inode->i_sb);
     552
     553        if (err == 0) {
     554                return (ssize_t) len;
     555        } else {
     556                errno = -err;
     557
     558                return -1;
     559        }
     560}
     561
     562static ssize_t rtems_jffs2_file_write(rtems_libio_t *iop, const void *buf, size_t len)
     563{
     564        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
     565        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
     566        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
     567        struct jffs2_raw_inode ri;
     568        uint32_t writtenlen;
     569        off_t pos;
     570        int eno = 0;
    1424571
    1425572        memset(&ri, 0, sizeof(ri));
     
    1429576        ri.uid = cpu_to_je16(inode->i_uid);
    1430577        ri.gid = cpu_to_je16(inode->i_gid);
    1431         ri.atime = ri.ctime = ri.mtime = cpu_to_je32(cyg_timestamp());
     578        ri.atime = ri.ctime = ri.mtime = cpu_to_je32(get_seconds());
     579
     580        rtems_jffs2_do_lock(inode->i_sb);
     581
     582        if ((iop->flags & LIBIO_FLAGS_APPEND) == 0) {
     583                pos = iop->offset;
     584        } else {
     585                pos = inode->i_size;
     586        }
    1432587
    1433588        if (pos > inode->i_size) {
    1434                 int err;
    1435589                ri.version = cpu_to_je32(++f->highest_version);
    1436                 err = jffs2_extend_file(inode, &ri, pos);
    1437                 if (err)
    1438                         return -err;
    1439         }
    1440         ri.isize = cpu_to_je32(inode->i_size);
    1441 
    1442         // Now loop over the iovecs until they are all done, or
    1443         // we get an error.
    1444         for (i = 0; i < uio->uio_iovcnt; i++) {
    1445                 cyg_iovec *iov = &uio->uio_iov[i];
    1446                 unsigned char *buf = iov->iov_base;
    1447                 off_t len = iov->iov_len;
    1448 
    1449                 uint32_t writtenlen;
    1450                 int err;
    1451 
    1452                 D2(printf("jffs2_fo_write page_start_pos %d\n", pos));
    1453                 D2(printf("jffs2_fo_write transfer size %d\n", len));
    1454 
    1455                 err = jffs2_write_inode_range(c, f, &ri, buf,
    1456                                               pos, len, &writtenlen);
    1457                 if (err)
    1458                         return -err;
    1459                
    1460                 if (writtenlen != len)
    1461                         return ENOSPC;
    1462 
    1463                 pos += len;
    1464                 resid -= len;
    1465         }
    1466 
    1467         // We wrote some data successfully, update the modified and access
    1468         // times of the inode, increase its size appropriately, and update
    1469         // the file offset and transfer residue.
    1470         inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
    1471         if (pos > inode->i_size)
    1472                 inode->i_size = pos;
    1473 
    1474         uio->uio_resid = resid;
    1475         fp->f_offset = pos;
    1476 
    1477         return ENOERR;
    1478 }
    1479 #endif /* CYGOPT_FS_JFFS2_WRITE */
    1480 
    1481 // -------------------------------------------------------------------------
    1482 // jffs2_fo_lseek()
    1483 // Seek to a new file position.
    1484 
    1485 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * apos, int whence)
    1486 {
    1487         struct _inode *node = (struct _inode *) fp->f_data;
    1488         off_t pos = *apos;
    1489 
    1490         D2(printf("jffs2_fo_lseek\n"));
    1491 
    1492         switch (whence) {
    1493         case SEEK_SET:
    1494                 // Pos is already where we want to be.
    1495                 break;
    1496 
    1497         case SEEK_CUR:
    1498                 // Add pos to current offset.
    1499                 pos += fp->f_offset;
    1500                 break;
    1501 
    1502         case SEEK_END:
    1503                 // Add pos to file size.
    1504                 pos += node->i_size;
    1505                 break;
    1506 
    1507         default:
    1508                 return EINVAL;
    1509         }
    1510 
    1511         if (pos < 0 )
    1512                 return EINVAL;
    1513 
    1514         // All OK, set fp offset and return new position.
    1515         *apos = fp->f_offset = pos;
    1516 
    1517         return ENOERR;
    1518 }
    1519 
    1520 // -------------------------------------------------------------------------
    1521 // jffs2_fo_ioctl()
    1522 // Handle ioctls. Currently none are defined.
    1523 
    1524 static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
    1525                           CYG_ADDRWORD data)
    1526 {
    1527         // No Ioctls currenly defined.
    1528 
    1529         D2(printf("jffs2_fo_ioctl\n"));
    1530 
    1531         return EINVAL;
    1532 }
    1533 
    1534 // -------------------------------------------------------------------------
    1535 // jffs2_fo_fsync().
    1536 // Force the file out to data storage.
    1537 
    1538 static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
    1539 {
    1540         // Data is always permanently where it belongs, nothing to do
    1541         // here.
    1542 
    1543         D2(printf("jffs2_fo_fsync\n"));
    1544 
    1545         return ENOERR;
    1546 }
    1547 
    1548 // -------------------------------------------------------------------------
    1549 // jffs2_fo_close()
    1550 // Close a file. We just decrement the refcnt and let it go away if
    1551 // that is all that is keeping it here.
    1552 
    1553 static int jffs2_fo_close(struct CYG_FILE_TAG *fp)
    1554 {
    1555         struct _inode *node = (struct _inode *) fp->f_data;
    1556 
    1557         D2(printf("jffs2_fo_close\n"));
    1558 
    1559         jffs2_iput(node);
    1560 
    1561         fp->f_data = 0;         // zero data pointer
    1562 
    1563         return ENOERR;
    1564 }
    1565 
    1566 // -------------------------------------------------------------------------
    1567 //jffs2_fo_fstat()
    1568 // Get file status.
    1569 
    1570 static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf)
    1571 {
    1572         struct _inode *node = (struct _inode *) fp->f_data;
    1573 
    1574         D2(printf("jffs2_fo_fstat\n"));
    1575 
    1576         // Fill in the status
    1577         buf->st_mode = node->i_mode;
    1578         buf->st_ino = node->i_ino;
    1579         buf->st_dev = 0;
    1580         buf->st_nlink = node->i_nlink;
    1581         buf->st_uid = node->i_uid;
    1582         buf->st_gid = node->i_gid;
    1583         buf->st_size = node->i_size;
    1584         buf->st_atime = node->i_atime;
    1585         buf->st_mtime = node->i_mtime;
    1586         buf->st_ctime = node->i_ctime;
    1587 
    1588         return ENOERR;
    1589 }
    1590 
    1591 // -------------------------------------------------------------------------
    1592 // jffs2_fo_getinfo()
    1593 // Get info. Currently only supports fpathconf().
    1594 
    1595 static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
    1596                             int len)
    1597 {
    1598         struct _inode *node = (struct _inode *) fp->f_data;
     590                eno = -jffs2_extend_file(inode, &ri, pos);
     591        }
     592
     593        if (eno == 0) {
     594                ri.isize = cpu_to_je32(inode->i_size);
     595
     596                eno = -jffs2_write_inode_range(c, f, &ri, (void *) buf, pos, len, &writtenlen);
     597        }
     598
     599        if (eno == 0) {
     600                pos += writtenlen;
     601
     602                inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
     603
     604                if (pos > inode->i_size) {
     605                        inode->i_size = pos;
     606                }
     607
     608                iop->offset = pos;
     609
     610                if (writtenlen != len) {
     611                        eno = ENOSPC;
     612                }
     613        }
     614
     615        rtems_jffs2_do_unlock(inode->i_sb);
     616
     617        if (eno == 0) {
     618                return writtenlen;
     619        } else {
     620                errno = eno;
     621
     622                return -1;
     623        }
     624}
     625
     626static int rtems_jffs2_file_ftruncate(rtems_libio_t *iop, off_t length)
     627{
     628        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
     629        struct iattr iattr;
     630        int eno;
     631
     632        iattr.ia_valid = ATTR_SIZE | ATTR_MTIME | ATTR_CTIME;
     633        iattr.ia_size = length;
     634        iattr.ia_mtime = get_seconds();
     635        iattr.ia_ctime = iattr.ia_mtime;
     636
     637        rtems_jffs2_do_lock(inode->i_sb);
     638
     639        eno = -jffs2_do_setattr(inode, &iattr);
     640
     641        rtems_jffs2_do_unlock(inode->i_sb);
     642
     643        return rtems_jffs2_eno_to_rv_and_errno(eno);
     644}
     645
     646static const rtems_filesystem_file_handlers_r rtems_jffs2_file_handlers = {
     647        .open_h = rtems_filesystem_default_open,
     648        .close_h = rtems_filesystem_default_close,
     649        .read_h = rtems_jffs2_file_read,
     650        .write_h = rtems_jffs2_file_write,
     651        .ioctl_h = rtems_filesystem_default_ioctl,
     652        .lseek_h = rtems_filesystem_default_lseek_file,
     653        .fstat_h = rtems_jffs2_fstat,
     654        .ftruncate_h = rtems_jffs2_file_ftruncate,
     655        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
     656        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
     657        .fcntl_h = rtems_filesystem_default_fcntl
     658};
     659
     660static const rtems_filesystem_file_handlers_r rtems_jffs2_link_handlers = {
     661        .open_h = rtems_filesystem_default_open,
     662        .close_h = rtems_filesystem_default_close,
     663        .read_h = rtems_filesystem_default_read,
     664        .write_h = rtems_filesystem_default_write,
     665        .ioctl_h = rtems_filesystem_default_ioctl,
     666        .lseek_h = rtems_filesystem_default_lseek,
     667        .fstat_h = rtems_jffs2_fstat,
     668        .ftruncate_h = rtems_filesystem_default_ftruncate,
     669        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
     670        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
     671        .fcntl_h = rtems_filesystem_default_fcntl
     672};
     673
     674static void rtems_jffs2_set_location(rtems_filesystem_location_info_t *loc, struct _inode *inode)
     675{
     676        loc->node_access = inode;
     677
     678        switch (inode->i_mode & S_IFMT) {
     679                case S_IFREG:
     680                        loc->handlers = &rtems_jffs2_file_handlers;
     681                        break;
     682                case S_IFDIR:
     683                        loc->handlers = &rtems_jffs2_directory_handlers;
     684                        break;
     685                case S_IFLNK:
     686                        loc->handlers = &rtems_jffs2_link_handlers;
     687                        break;
     688                default:
     689                        loc->handlers = &rtems_filesystem_null_handlers;
     690                        break;
     691        };
     692}
     693
     694static bool rtems_jffs2_eval_is_directory(
     695        rtems_filesystem_eval_path_context_t *ctx,
     696        void *arg
     697)
     698{
     699        rtems_filesystem_location_info_t *currentloc =
     700                rtems_filesystem_eval_path_get_currentloc(ctx);
     701        struct _inode *inode = rtems_jffs2_get_inode_by_location(currentloc);
     702
     703        return S_ISDIR(inode->i_mode);
     704}
     705
     706static rtems_filesystem_eval_path_generic_status rtems_jffs2_eval_token(
     707        rtems_filesystem_eval_path_context_t *ctx,
     708        void *arg,
     709        const char *token,
     710        size_t tokenlen
     711)
     712{
     713        rtems_filesystem_eval_path_generic_status status =
     714                RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
     715        rtems_filesystem_location_info_t *currentloc =
     716                rtems_filesystem_eval_path_get_currentloc(ctx);
     717        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(currentloc);
     718        bool access_ok = rtems_filesystem_eval_path_check_access(
     719                ctx,
     720                RTEMS_FS_PERMS_EXEC,
     721                dir_i->i_mode,
     722                dir_i->i_uid,
     723                dir_i->i_gid
     724        );
     725
     726        if (access_ok) {
     727                struct _inode *entry_i;
     728
     729                if (rtems_filesystem_is_current_directory(token, tokenlen)) {
     730                        entry_i = dir_i;
     731                        ++entry_i->i_count;
     732                } else if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
     733                        entry_i = dir_i->i_parent;
     734                        ++entry_i->i_count;
     735                } else {
     736                        entry_i = jffs2_lookup(dir_i, token, (int) tokenlen);
     737                }
     738
     739                if (IS_ERR(entry_i)) {
     740                        rtems_filesystem_eval_path_error(ctx, PTR_ERR(entry_i));
     741                } else if (entry_i != NULL) {
     742                        bool terminal = !rtems_filesystem_eval_path_has_path(ctx);
     743                        int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
     744                        bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
     745
     746                        rtems_filesystem_eval_path_clear_token(ctx);
     747
     748                        if (S_ISLNK(entry_i->i_mode) && (follow_sym_link || !terminal)) {
     749                                struct jffs2_inode_info *f = JFFS2_INODE_INFO(entry_i);
     750                                const char *target = f->target;
     751
     752                                rtems_filesystem_eval_path_recursive(ctx, target, strlen(target));
     753
     754                                jffs2_iput(entry_i);
     755                        } else {
     756                                if (S_ISDIR(entry_i->i_mode) && entry_i->i_parent == NULL) {
     757                                        entry_i->i_parent = dir_i;
     758                                        ++dir_i->i_count;
     759                                }
     760
     761                                jffs2_iput(dir_i);
     762                                rtems_jffs2_set_location(currentloc, entry_i);
     763
     764                                if (rtems_filesystem_eval_path_has_path(ctx)) {
     765                                        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
     766                                }
     767                        }
     768                } else {
     769                        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
     770                }
     771        }
     772
     773        return status;
     774}
     775
     776static const rtems_filesystem_eval_path_generic_config rtems_jffs2_eval_config = {
     777        .is_directory = rtems_jffs2_eval_is_directory,
     778        .eval_token = rtems_jffs2_eval_token
     779};
     780
     781static void rtems_jffs2_lock(const rtems_filesystem_mount_table_entry_t *mt_entry)
     782{
     783        const rtems_jffs2_fs_info *fs_info = mt_entry->fs_info;
     784        const struct super_block *sb = &fs_info->sb;
     785
     786        rtems_jffs2_do_lock(sb);
     787}
     788
     789static void rtems_jffs2_unlock(const rtems_filesystem_mount_table_entry_t *mt_entry)
     790{
     791        const rtems_jffs2_fs_info *fs_info = mt_entry->fs_info;
     792        const struct super_block *sb = &fs_info->sb;
     793
     794        rtems_jffs2_do_unlock(sb);
     795}
     796
     797static void rtems_jffs2_eval_path(rtems_filesystem_eval_path_context_t *ctx)
     798{
     799        rtems_filesystem_eval_path_generic(ctx, NULL, &rtems_jffs2_eval_config);
     800}
     801
     802static int rtems_jffs2_link(
     803        const rtems_filesystem_location_info_t *parentloc,
     804        const rtems_filesystem_location_info_t *targetloc,
     805        const char *name,
     806        size_t namelen
     807)
     808{
     809        struct _inode *old_d_inode = rtems_jffs2_get_inode_by_location(targetloc);
     810        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
     811        int eno;
     812
     813        eno = -jffs2_link(old_d_inode, dir_i, name, namelen);
     814
     815        return rtems_jffs2_eno_to_rv_and_errno(eno);
     816}
     817
     818static bool rtems_jffs2_are_nodes_equal(
     819        const rtems_filesystem_location_info_t *a,
     820        const rtems_filesystem_location_info_t *b
     821)
     822{
     823        struct _inode *inode_a = rtems_jffs2_get_inode_by_location(a);
     824        struct _inode *inode_b = rtems_jffs2_get_inode_by_location(b);
     825
     826        return inode_a->i_ino == inode_b->i_ino;
     827}
     828
     829static rtems_filesystem_node_types_t rtems_jffs2_node_type(
     830        const rtems_filesystem_location_info_t *loc
     831)
     832{
     833        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     834        rtems_filesystem_node_types_t type;
     835
     836        switch (inode->i_mode & S_IFMT) {
     837                case S_IFDIR:
     838                        type = RTEMS_FILESYSTEM_DIRECTORY;
     839                        break;
     840                case S_IFREG:
     841                        type = RTEMS_FILESYSTEM_MEMORY_FILE;
     842                        break;
     843                case S_IFLNK:
     844                        type = RTEMS_FILESYSTEM_SYM_LINK;
     845                        break;
     846                default:
     847                        type = RTEMS_FILESYSTEM_INVALID_NODE_TYPE;
     848                        break;
     849        }
     850
     851        return type;
     852}
     853
     854static int rtems_jffs2_mknod(
     855        const rtems_filesystem_location_info_t *parentloc,
     856        const char *name,
     857        size_t namelen,
     858        mode_t mode,
     859        dev_t dev
     860)
     861{
     862        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
     863        int eno;
     864
     865        switch (mode & S_IFMT) {
     866                case S_IFDIR:
     867                        eno = -jffs2_mknod(dir_i, name, namelen, mode, NULL, 0);
     868                        break;
     869                case S_IFREG:
     870                        eno = -jffs2_create(dir_i, name, namelen, mode);
     871                        break;
     872                default:
     873                        eno = EINVAL;
     874                        break;
     875        }
     876
     877        return rtems_jffs2_eno_to_rv_and_errno(eno);
     878}
     879
     880static int rtems_jffs2_cache_fd_name(struct _inode *inode, char **name, size_t *namelen)
     881{
     882        struct super_block *sb = inode->i_sb;
     883        char *fd_name = inode->i_fd->name;
     884        size_t fd_namelen = strlen(fd_name);
     885        int eno = 0;
     886
     887        if (fd_namelen <= sizeof(sb->s_name_buf)) {
     888                *namelen = fd_namelen;
     889                *name = memcpy(&sb->s_name_buf[0], fd_name, fd_namelen);
     890        } else {
     891                eno = ENOMEM;
     892        }
     893
     894        return eno;
     895}
     896
     897static int rtems_jffs2_rmnod(
     898        const rtems_filesystem_location_info_t *parentloc,
     899        const rtems_filesystem_location_info_t *loc
     900)
     901{
     902        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
     903        struct _inode *entry_i = rtems_jffs2_get_inode_by_location(loc);
     904        char *name;
     905        size_t namelen;
     906        int eno = rtems_jffs2_cache_fd_name(entry_i, &name, &namelen);
     907
     908        if (eno == 0) {
     909                switch (dir_i->i_mode & S_IFMT) {
     910                        case S_IFDIR:
     911                                eno = -jffs2_rmdir(dir_i, entry_i, name, namelen);
     912                                break;
     913                        case S_IFREG:
     914                                eno = -jffs2_unlink(dir_i, entry_i, name, namelen);
     915                                break;
     916                        default:
     917                                eno = EINVAL;
     918                                break;
     919                }
     920        }
     921
     922        return rtems_jffs2_eno_to_rv_and_errno(eno);
     923}
     924
     925static int rtems_jffs2_fchmod(
     926        const rtems_filesystem_location_info_t *loc,
     927        mode_t mode
     928)
     929{
     930        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     931        struct iattr iattr;
     932        int eno;
     933
     934        iattr.ia_valid = ATTR_MODE | ATTR_CTIME;
     935        iattr.ia_mode = mode;
     936        iattr.ia_ctime = get_seconds();
     937
     938        eno = -jffs2_do_setattr(inode, &iattr);
     939
     940        return rtems_jffs2_eno_to_rv_and_errno(eno);
     941}
     942
     943static int rtems_jffs2_chown(
     944        const rtems_filesystem_location_info_t *loc,
     945        uid_t owner,
     946        gid_t group
     947)
     948{
     949        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     950        struct iattr iattr;
     951        int eno;
     952
     953        iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
     954        iattr.ia_uid = owner;
     955        iattr.ia_gid = group;
     956        iattr.ia_ctime = get_seconds();
     957
     958        eno = -jffs2_do_setattr(inode, &iattr);
     959
     960        return rtems_jffs2_eno_to_rv_and_errno(eno);
     961}
     962
     963static int rtems_jffs2_clonenode(rtems_filesystem_location_info_t *loc)
     964{
     965        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     966
     967        ++inode->i_count;
     968
     969        return 0;
     970}
     971
     972static void rtems_jffs2_freenode(const rtems_filesystem_location_info_t *loc)
     973{
     974        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     975
     976        jffs2_iput(inode);
     977}
     978
     979static void rtems_jffs2_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry)
     980{
     981        rtems_jffs2_fs_info *fs_info = mt_entry->fs_info;
     982        struct _inode *root_i = mt_entry->mt_fs_root->location.node_access;
     983
     984        icache_evict(root_i, NULL);
     985        assert(root_i->i_cache_next == NULL);
     986        assert(root_i->i_count == 1);
     987        jffs2_iput(root_i);
     988
     989        rtems_jffs2_free_directory_entries(root_i);
     990        free(root_i);
     991
     992        rtems_jffs2_free_fs_info(fs_info, true);
     993}
     994
     995static int rtems_jffs2_rename(
     996        const rtems_filesystem_location_info_t *oldparentloc,
     997        const rtems_filesystem_location_info_t *oldloc,
     998        const rtems_filesystem_location_info_t *newparentloc,
     999        const char *name,
     1000        size_t namelen
     1001)
     1002{
     1003        struct _inode *old_dir_i = rtems_jffs2_get_inode_by_location(oldparentloc);
     1004        struct _inode *new_dir_i = rtems_jffs2_get_inode_by_location(newparentloc);
     1005        struct _inode *d_inode = rtems_jffs2_get_inode_by_location(oldloc);
     1006        char *oldname;
     1007        size_t oldnamelen;
     1008        int eno = rtems_jffs2_cache_fd_name(d_inode, &oldname, &oldnamelen);
     1009
     1010        if (eno == 0) {
     1011                eno = -jffs2_rename(old_dir_i, d_inode, oldname, oldnamelen, new_dir_i, name, namelen);
     1012        }
     1013
     1014        return rtems_jffs2_eno_to_rv_and_errno(eno);
     1015}
     1016
     1017static int rtems_jffs2_statvfs(
     1018        const rtems_filesystem_location_info_t *loc,
     1019        struct statvfs *buf
     1020)
     1021{
     1022        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     1023        struct super_block *sb = inode->i_sb;
     1024        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
     1025        unsigned long avail;
     1026
     1027        spin_lock(&c->erase_completion_lock);
     1028        avail = c->dirty_size + c->free_size;
     1029        if (avail > c->sector_size * c->resv_blocks_write) {
     1030                avail -= c->sector_size * c->resv_blocks_write;
     1031        } else {
     1032                avail = 0;
     1033        }
     1034        spin_unlock(&c->erase_completion_lock);
     1035
     1036        buf->f_bavail = avail >> PAGE_SHIFT;
     1037        buf->f_blocks = c->flash_size >> PAGE_SHIFT;
     1038        buf->f_bsize = 1UL << PAGE_SHIFT;
     1039        buf->f_fsid = JFFS2_SUPER_MAGIC;
     1040        buf->f_namemax = JFFS2_MAX_NAME_LEN;
     1041
     1042        buf->f_bfree = buf->f_bavail;
     1043        buf->f_frsize = buf->f_bsize;
     1044
     1045        return 0;
     1046}
     1047
     1048static int rtems_jffs2_utime(
     1049        const rtems_filesystem_location_info_t *loc,
     1050        time_t actime,
     1051        time_t modtime
     1052)
     1053{
     1054        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     1055        struct iattr iattr;
     1056        int eno;
     1057
     1058        iattr.ia_valid = ATTR_ATIME | ATTR_MTIME | ATTR_CTIME;
     1059        iattr.ia_atime = actime;
     1060        iattr.ia_mtime = modtime;
     1061        iattr.ia_ctime = get_seconds();
     1062
     1063        eno = -jffs2_do_setattr(inode, &iattr);
     1064
     1065        return rtems_jffs2_eno_to_rv_and_errno(eno);
     1066}
     1067
     1068static int rtems_jffs2_symlink(
     1069        const rtems_filesystem_location_info_t *parentloc,
     1070        const char *name,
     1071        size_t namelen,
     1072        const char *target
     1073)
     1074{
     1075        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
     1076        int eno;
     1077
     1078        eno = -jffs2_mknod(dir_i, name, namelen, S_IFLNK | S_IRWXUGO, target, strlen(target));
     1079
     1080        return rtems_jffs2_eno_to_rv_and_errno(eno);
     1081}
     1082
     1083static ssize_t rtems_jffs2_readlink(
     1084        const rtems_filesystem_location_info_t *loc,
     1085        char *buf,
     1086        size_t bufsize
     1087)
     1088{
     1089        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
     1090        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
     1091        const char *target = f->target;
     1092        ssize_t i;
     1093
     1094        for (i = 0; i < (ssize_t) bufsize && target[i] != '\0'; ++i) {
     1095                buf[i] = target[i];
     1096        }
     1097
     1098        return i;
     1099}
     1100
     1101static const rtems_filesystem_operations_table rtems_jffs2_ops = {
     1102        .lock_h = rtems_jffs2_lock,
     1103        .unlock_h = rtems_jffs2_unlock,
     1104        .eval_path_h = rtems_jffs2_eval_path,
     1105        .link_h = rtems_jffs2_link,
     1106        .are_nodes_equal_h = rtems_jffs2_are_nodes_equal,
     1107        .node_type_h = rtems_jffs2_node_type,
     1108        .mknod_h = rtems_jffs2_mknod,
     1109        .rmnod_h = rtems_jffs2_rmnod,
     1110        .fchmod_h = rtems_jffs2_fchmod,
     1111        .chown_h = rtems_jffs2_chown,
     1112        .clonenod_h = rtems_jffs2_clonenode,
     1113        .freenod_h = rtems_jffs2_freenode,
     1114        .mount_h = rtems_filesystem_default_mount,
     1115        .fsmount_me_h = rtems_jffs2_initialize,
     1116        .unmount_h = rtems_filesystem_default_unmount,
     1117        .fsunmount_me_h = rtems_jffs2_fsunmount,
     1118        .utime_h = rtems_jffs2_utime,
     1119        .symlink_h = rtems_jffs2_symlink,
     1120        .readlink_h = rtems_jffs2_readlink,
     1121        .rename_h = rtems_jffs2_rename,
     1122        .statvfs_h = rtems_jffs2_statvfs
     1123};
     1124
     1125static int calculate_inocache_hashsize(uint32_t flash_size)
     1126{
     1127        /*
     1128         * Pick a inocache hash size based on the size of the medium.
     1129         * Count how many megabytes we're dealing with, apply a hashsize twice
     1130         * that size, but rounding down to the usual big powers of 2. And keep
     1131         * to sensible bounds.
     1132         */
     1133
     1134        int size_mb = flash_size / 1024 / 1024;
     1135        int hashsize = (size_mb * 2) & ~0x3f;
     1136
     1137        if (hashsize < INOCACHE_HASHSIZE_MIN)
     1138                return INOCACHE_HASHSIZE_MIN;
     1139        if (hashsize > INOCACHE_HASHSIZE_MAX)
     1140                return INOCACHE_HASHSIZE_MAX;
     1141
     1142        return hashsize;
     1143}
     1144
     1145int rtems_jffs2_initialize(
     1146        rtems_filesystem_mount_table_entry_t *mt_entry,
     1147        const void *data
     1148)
     1149{
     1150        const rtems_jffs2_mount_data *jffs2_mount_data = data;
     1151        rtems_jffs2_flash_control *fc = jffs2_mount_data->flash_control;
     1152        int inocache_hashsize = calculate_inocache_hashsize(fc->flash_size);
     1153        rtems_jffs2_fs_info *fs_info = calloc(
     1154                1,
     1155                sizeof(*fs_info) + (size_t) inocache_hashsize * sizeof(fs_info->inode_cache[0])
     1156        );
     1157        bool do_mount_fs_was_successful = false;
     1158        struct super_block *sb;
     1159        struct jffs2_sb_info *c;
    15991160        int err;
    16001161
    1601         D2(printf("jffs2_fo_getinfo\n"));
    1602 
    1603         switch (key) {
    1604         case FS_INFO_CONF:
    1605                 err = jffs2_pathconf(node, (struct cyg_pathconf_info *) buf);
    1606                 break;
    1607 
    1608         default:
    1609                 err = EINVAL;
    1610         }
    1611         return err;
    1612 
    1613         return ENOERR;
    1614 }
    1615 
    1616 // -------------------------------------------------------------------------
    1617 // jffs2_fo_setinfo()
    1618 // Set info. Nothing supported here.
    1619 
    1620 static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
    1621                             int len)
    1622 {
    1623         // No setinfo key supported at present
    1624 
    1625         D2(printf("jffs2_fo_setinfo\n"));
    1626 
    1627         return ENOERR;
    1628 }
    1629 
    1630 //==========================================================================
    1631 // Directory operations
    1632 
    1633 // -------------------------------------------------------------------------
    1634 // jffs2_fo_dirread()
    1635 // Read a single directory entry from a file.
    1636 
    1637 static __inline void filldir(char *nbuf, int nlen, const unsigned char *name, int namlen)
    1638 {
    1639         int len = nlen < namlen ? nlen : namlen;
    1640         memcpy(nbuf, name, len);
    1641         nbuf[len] = '\0';
    1642 }
    1643 
    1644 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
    1645 {
    1646         struct _inode *d_inode = (struct _inode *) fp->f_data;
    1647         struct dirent *ent = (struct dirent *) uio->uio_iov[0].iov_base;
    1648         char *nbuf = ent->d_name;
    1649 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE
    1650         struct _inode *c_ino;
    1651 #endif
    1652         int nlen = sizeof (ent->d_name) - 1;
    1653         off_t len = uio->uio_iov[0].iov_len;
    1654         struct jffs2_inode_info *f;
    1655         struct jffs2_sb_info *c;
    1656         struct _inode *inode = d_inode;
    1657         struct jffs2_full_dirent *fd;
    1658         unsigned long offset, curofs;
    1659         int found = 1;
    1660 
    1661         if (len < sizeof (struct dirent))
    1662                 return EINVAL;
    1663 
    1664         D1(printk
    1665            (KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino));
    1666 
    1667         f = JFFS2_INODE_INFO(inode);
    1668         c = JFFS2_SB_INFO(inode->i_sb);
    1669 
    1670         offset = fp->f_offset;
    1671 
    1672         if (offset == 0) {
    1673                 D1(printk
    1674                    (KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino));
    1675                 filldir(nbuf, nlen, (const unsigned char *) ".", 1);
    1676 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE
    1677                 // Flags here are the same as jffs2_mkdir. Make sure
    1678                 // d_type is the same as st_mode of calling stat.
    1679                 ent->d_type =
    1680                   jemode_to_cpu(cpu_to_jemode(S_IRUGO|S_IXUGO|S_IWUSR|S_IFDIR));
    1681 #endif
    1682                 goto out;
    1683         }
    1684         if (offset == 1) {
    1685                 filldir(nbuf, nlen, (const unsigned char *) "..", 2);
    1686 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE
    1687                 // Flags here are the same as jffs2_mkdir. Make sure
    1688                 // d_type is the same as st_mode of calling stat.
    1689                 ent->d_type =
    1690                   jemode_to_cpu(cpu_to_jemode(S_IRUGO|S_IXUGO|S_IWUSR|S_IFDIR));
    1691 #endif
    1692                 goto out;
    1693         }
    1694 
    1695         curofs = 1;
    1696         down(&f->sem);
    1697         for (fd = f->dents; fd; fd = fd->next) {
    1698 
    1699                 curofs++;
    1700                 /* First loop: curofs = 2; offset = 2 */
    1701                 if (curofs < offset) {
    1702                         D2(printk
    1703                            (KERN_DEBUG
    1704                             "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n",
    1705                             fd->name, fd->ino, fd->type, curofs, offset));
    1706                         continue;
    1707                 }
    1708                 if (!fd->ino) {
    1709                         D2(printk
    1710                            (KERN_DEBUG "Skipping deletion dirent \"%s\"\n",
    1711                             fd->name));
    1712                         offset++;
    1713                         continue;
    1714                 }
    1715                 D2(printk
    1716                    (KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset,
    1717                     fd->name, fd->ino, fd->type));
    1718                 filldir(nbuf, nlen, fd->name, strlen((char *)fd->name));
    1719 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE
    1720                 c_ino = jffs2_iget(inode->i_sb, fd->ino);
    1721                 if(IS_ERR(c_ino)) {
    1722                         D1(printk(KERN_WARNING "get entry inode failed\n"));
    1723                         // fileio already set it to zero, so not needed here
    1724                         // ent->d_type = 0;
    1725                 }
    1726                 else {
    1727                         ent->d_type = c_ino->i_mode;
    1728                         jffs2_iput(c_ino);
    1729                 }
    1730 #endif
    1731                 goto out_sem;
    1732         }
    1733         /* Reached the end of the directory */
    1734         found = 0;
    1735       out_sem:
    1736         up(&f->sem);
    1737       out:
    1738         fp->f_offset = ++offset;
    1739         if (found) {
    1740                 uio->uio_resid -= sizeof (struct dirent);
    1741         }
    1742         return ENOERR;
    1743 }
    1744 
    1745 // -------------------------------------------------------------------------
    1746 // jffs2_fo_dirlseek()
    1747 // Seek directory to start.
    1748 
    1749 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence)
    1750 {
    1751         // Only allow SEEK_SET to zero
    1752 
    1753         D2(printf("jffs2_fo_dirlseek\n"));
    1754 
    1755         if (whence != SEEK_SET || *pos != 0)
    1756                 return EINVAL;
    1757 
    1758         *pos = fp->f_offset = 0;
    1759 
    1760         return ENOERR;
     1162        if (fs_info != NULL) {
     1163                err = 0;
     1164        } else {
     1165                err = -ENOMEM;
     1166        }
     1167
     1168        sb = &fs_info->sb;
     1169        c = JFFS2_SB_INFO(sb);
     1170
     1171        if (err == 0) {
     1172                uint32_t blocks = fc->flash_size / fc->block_size;
     1173
     1174                if ((fc->block_size * blocks) != fc->flash_size) {
     1175                        fc->flash_size = fc->block_size * blocks;
     1176                        pr_info("Flash size not aligned to erasesize, reducing to %dKiB\n",
     1177                                fc->flash_size / 1024);
     1178                }
     1179
     1180                if (fc->flash_size < 5*fc->block_size) {
     1181                        pr_err("Too few erase blocks (%d)\n",
     1182                               fc->flash_size / fc->block_size);
     1183                        err = -EINVAL;
     1184                }
     1185        }
     1186
     1187        if (err == 0) {
     1188                rtems_status_code sc = rtems_semaphore_create(
     1189                        rtems_build_name('J', 'F', 'F', 'S'),
     1190                        1,
     1191                        RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY | RTEMS_BINARY_SEMAPHORE,
     1192                        0,
     1193                        &sb->s_mutex
     1194                );
     1195
     1196                err = sc == RTEMS_SUCCESSFUL ? 0 : -ENOMEM;
     1197        }
     1198
     1199        if (err == 0) {
     1200                sb->s_is_readonly = !mt_entry->writeable;
     1201                sb->s_flash_control = fc;
     1202                sb->s_compressor_control = jffs2_mount_data->compressor_control;
     1203
     1204                c->inocache_hashsize = inocache_hashsize;
     1205                c->inocache_list = &fs_info->inode_cache[0];
     1206                c->sector_size = fc->block_size;
     1207                c->flash_size = fc->flash_size;
     1208                c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
     1209
     1210                err = jffs2_do_mount_fs(c);
     1211        }
     1212
     1213        if (err == 0) {
     1214                do_mount_fs_was_successful = true;
     1215
     1216                sb->s_root = jffs2_iget(sb, 1);
     1217                if (IS_ERR(sb->s_root)) {
     1218                        err = PTR_ERR(sb->s_root);
     1219                }
     1220        }
     1221
     1222        if (err == 0) {
     1223                sb->s_root->i_parent = sb->s_root;
     1224
     1225                if (!jffs2_is_readonly(c)) {
     1226                        jffs2_erase_pending_blocks(c, 0);
     1227                }
     1228
     1229                mt_entry->fs_info = fs_info;
     1230                mt_entry->ops = &rtems_jffs2_ops;
     1231                mt_entry->mt_fs_root->location.node_access = sb->s_root;
     1232                mt_entry->mt_fs_root->location.handlers = &rtems_jffs2_directory_handlers;
     1233
     1234                return 0;
     1235        } else {
     1236                if (fs_info != NULL) {
     1237                        rtems_jffs2_free_fs_info(fs_info, do_mount_fs_was_successful);
     1238                } else {
     1239                        rtems_jffs2_flash_control_destroy(fc);
     1240                        rtems_jffs2_compressor_control_destroy(jffs2_mount_data->compressor_control);
     1241                }
     1242
     1243                errno = -err;
     1244
     1245                return -1;
     1246        }
    17611247}
    17621248
     
    17741260                                   unsigned long *priv)
    17751261{
    1776         /* FIXME: This works only with one file system mounted at a time */
    17771262        int ret;
     1263        struct super_block *sb = OFNI_BS_2SFFJ(c);
     1264        unsigned char *gc_buffer = &sb->s_gc_buffer[0];
    17781265
    17791266        ret = jffs2_read_inode_range(c, f, gc_buffer,
     
    18711358        err = jffs2_read_inode(inode);
    18721359        if (err) {
    1873                 printf("jffs2_read_inode() failed\n");
     1360                printk("jffs2_read_inode() failed\n");
    18741361                inode->i_nlink = 0; // free _this_ bad inode right now
    18751362                jffs2_iput(inode);
     
    18911378        // and gc.c jffs2_garbage_collect_pass
    18921379 recurse:
    1893         if (!i) {
    1894                 printf("jffs2_iput() called with NULL inode\n");
    1895                 // and let it fault...
    1896         }
     1380        assert(i != NULL);
    18971381
    18981382        i->i_count--;
     
    19381422{
    19391423        memset(f, 0, sizeof(*f));
    1940         init_MUTEX_LOCKED(&f->sem);
    19411424}
    19421425
     
    19791462        memset(ri, 0, sizeof(*ri));
    19801463        /* Set OS-specific defaults for new inodes */
    1981         ri->uid = ri->gid = cpu_to_je16(0);
     1464        ri->uid = cpu_to_je16(geteuid());
     1465        ri->gid = cpu_to_je16(getegid());
    19821466        ri->mode =  cpu_to_jemode(mode);
    19831467        ret = jffs2_do_new_inode (c, f, mode, ri);
     
    19891473                if (inode->i_cache_next)
    19901474                       inode->i_cache_next->i_cache_prev = inode->i_cache_prev;
    1991                 up(&(f->sem));
     1475                mutex_unlock(&(f->sem));
    19921476                jffs2_clear_inode(inode);
    19931477                memset(inode, 0x6a, sizeof(*inode));
     
    20001484        inode->i_gid = je16_to_cpu(ri->gid);
    20011485        inode->i_uid = je16_to_cpu(ri->uid);
    2002         inode->i_atime = inode->i_ctime = inode->i_mtime = cyg_timestamp();
     1486        inode->i_atime = inode->i_ctime = inode->i_mtime = get_seconds();
    20031487        ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
    20041488
     
    20261510
    20271511        if (ret) {
    2028                 up(&f->sem);
     1512                mutex_unlock(&f->sem);
    20291513                return ret;
    20301514        }
     
    20371521        inode->i_ctime = je32_to_cpu(latest_node.ctime);
    20381522
    2039         inode->i_nlink = f->inocache->nlink;
    2040         up(&f->sem);
     1523        inode->i_nlink = f->inocache->pino_nlink;
     1524        mutex_unlock(&f->sem);
    20411525
    20421526        D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
     
    20521536
    20531537struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
    2054                                                      int inum, int nlink)
     1538                                              int inum, int unlinked)
    20551539{
    20561540        struct _inode *inode;
    20571541        struct jffs2_inode_cache *ic;
    2058         if (!nlink) {
     1542
     1543        if (unlinked) {
    20591544                /* The inode has zero nlink but its nodes weren't yet marked
    2060                    obsolete. This has to be because we're still waiting for 
    2061                    the final (close() and) jffs2_iput() to happen.
    2062 
    2063                    There's a possibility that the final jffs2_iput() could have
     1545                   obsolete. This has to be because we're still waiting for
     1546                   the final (close() and) iput() to happen.
     1547
     1548                   There's a possibility that the final iput() could have
    20641549                   happened while we were contemplating. In order to ensure
    20651550                   that we don't cause a new read_inode() (which would fail)
    20661551                   for the inode in question, we use ilookup() in this case
    2067                    instead of jffs2_iget().
    2068 
    2069                    The nlink can't _become_ zero at this point because we're 
     1552                   instead of iget().
     1553
     1554                   The nlink can't _become_ zero at this point because we're
    20701555                   holding the alloc_sem, and jffs2_do_unlink() would also
    20711556                   need that while decrementing nlink on any inode.
     
    20731558                inode = ilookup(OFNI_BS_2SFFJ(c), inum);
    20741559                if (!inode) {
    2075                         D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n",
    2076                                   inum));
     1560                        jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.\n",
     1561                                  inum);
    20771562
    20781563                        spin_lock(&c->inocache_lock);
    20791564                        ic = jffs2_get_ino_cache(c, inum);
    20801565                        if (!ic) {
    2081                                 D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum));
     1566                                jffs2_dbg(1, "Inode cache for ino #%u is gone\n",
     1567                                          inum);
    20821568                                spin_unlock(&c->inocache_lock);
    20831569                                return NULL;
     
    20851571                        if (ic->state != INO_STATE_CHECKEDABSENT) {
    20861572                                /* Wait for progress. Don't just loop */
    2087                                 D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n",
    2088                                           ic->ino, ic->state));
     1573                                jffs2_dbg(1, "Waiting for ino #%u in state %d\n",
     1574                                          ic->ino, ic->state);
    20891575                                sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
    20901576                        } else {
     
    20971583                /* Inode has links to it still; they're not going away because
    20981584                   jffs2_do_unlink() would need the alloc_sem and we have it.
    2099                    Just jffs2_iget() it, and if read_inode() is necessary that's OK.
     1585                   Just iget() it, and if read_inode() is necessary that's OK.
    21001586                */
    21011587                inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
    21021588                if (IS_ERR(inode))
    2103                         return (void *)inode;
     1589                        return ERR_CAST(inode);
    21041590        }
    21051591
    21061592        return JFFS2_INODE_INFO(inode);
    21071593}
    2108 
    2109 
    2110 
    2111 uint32_t jffs2_from_os_mode(uint32_t osmode)
    2112 {
    2113         uint32_t jmode = ((osmode & S_IRUSR)?00400:0) |
    2114                 ((osmode & S_IWUSR)?00200:0) |
    2115                 ((osmode & S_IXUSR)?00100:0) |
    2116                 ((osmode & S_IRGRP)?00040:0) |
    2117                 ((osmode & S_IWGRP)?00020:0) |
    2118                 ((osmode & S_IXGRP)?00010:0) |
    2119                 ((osmode & S_IROTH)?00004:0) |
    2120                 ((osmode & S_IWOTH)?00002:0) |
    2121                 ((osmode & S_IXOTH)?00001:0);
    2122 
    2123         switch (osmode & S_IFMT) {
    2124         case S_IFSOCK:
    2125                 return jmode | 0140000;
    2126         case S_IFLNK:
    2127                 return jmode | 0120000;
    2128         case S_IFREG:
    2129                 return jmode | 0100000;
    2130         case S_IFBLK:
    2131                 return jmode | 0060000;
    2132         case S_IFDIR:
    2133                 return jmode | 0040000;
    2134         case S_IFCHR:
    2135                 return jmode | 0020000;
    2136         case S_IFIFO:
    2137                 return jmode | 0010000;
    2138         case S_ISUID:
    2139                 return jmode | 0004000;
    2140         case S_ISGID:
    2141                 return jmode | 0002000;
    2142 #ifdef S_ISVTX
    2143         case S_ISVTX:
    2144                 return jmode | 0001000;
    2145 #endif
    2146         }
    2147         printf("os_to_jffs2_mode() cannot convert 0x%x\n", osmode);
    2148         BUG();
    2149         return 0;
    2150 }
    2151 
    2152 uint32_t jffs2_to_os_mode (uint32_t jmode)
    2153 {
    2154         uint32_t osmode = ((jmode & 00400)?S_IRUSR:0) |
    2155                 ((jmode & 00200)?S_IWUSR:0) |
    2156                 ((jmode & 00100)?S_IXUSR:0) |
    2157                 ((jmode & 00040)?S_IRGRP:0) |
    2158                 ((jmode & 00020)?S_IWGRP:0) |
    2159                 ((jmode & 00010)?S_IXGRP:0) |
    2160                 ((jmode & 00004)?S_IROTH:0) |
    2161                 ((jmode & 00002)?S_IWOTH:0) |
    2162                 ((jmode & 00001)?S_IXOTH:0);
    2163 
    2164         switch(jmode & 00170000) {
    2165         case 0140000:
    2166                 return osmode | S_IFSOCK;
    2167         case 0120000:
    2168                 return osmode | S_IFLNK;
    2169         case 0100000:
    2170                 return osmode | S_IFREG;
    2171         case 0060000:
    2172                 return osmode | S_IFBLK;
    2173         case 0040000:
    2174                 return osmode | S_IFDIR;
    2175         case 0020000:
    2176                 return osmode | S_IFCHR;
    2177         case 0010000:
    2178                 return osmode | S_IFIFO;
    2179         case 0004000:
    2180                 return osmode | S_ISUID;
    2181         case 0002000:
    2182                 return osmode | S_ISGID;
    2183 #ifdef S_ISVTX
    2184         case 0001000:
    2185                 return osmode | S_ISVTX;
    2186 #endif
    2187         }
    2188         printf("jffs2_to_os_mode() cannot convert 0x%x\n", osmode);
    2189         BUG();
    2190         return 0;
    2191 }
  • cpukit/libfs/src/jffs2/src/gc.c

    r78b85286 r3c96bee  
    742742        struct jffs2_raw_inode ri;
    743743        struct jffs2_node_frag *last_frag;
     744#ifndef __rtems__
    744745        union jffs2_device_node dev;
     746#endif /* __rtems__ */
    745747        char *mdata = NULL;
    746748        int mdatalen = 0;
     
    750752        if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
    751753            S_ISCHR(JFFS2_F_I_MODE(f)) ) {
     754#ifndef __rtems__
    752755                /* For these, we don't actually need to read the old node */
    753756                mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
     
    755758                jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n",
    756759                          __func__, mdatalen);
     760#else /* __rtems__ */
     761                return -EIO;
     762#endif /* __rtems__ */
    757763        } else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
    758764                mdatalen = fn->size;
  • cpukit/libfs/src/jffs2/src/jffs2_fs_i.h

    r78b85286 r3c96bee  
    5151        uint16_t flags;
    5252        uint8_t usercompr;
     53#if !defined (__ECOS)
    5354        struct inode vfs_inode;
     55#endif
    5456};
    5557
  • cpukit/libfs/src/jffs2/src/malloc-rtems.c

    r78b85286 r3c96bee  
    1313
    1414#include <linux/kernel.h>
    15 #include <cyg/hal/drv_api.h>
    1615#include "nodelist.h"
    17 
    18 #if !defined(CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE)
    19 # define CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE 0
    20 #endif
    2116
    2217struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
     
    7065}
    7166
     67static struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
     68{
     69        struct jffs2_raw_node_ref *ret;
     70
     71        ret = malloc((REFS_PER_BLOCK + 1) * sizeof(*ret));
     72        if (ret) {
     73                int i = 0;
     74                for (i=0; i < REFS_PER_BLOCK; i++) {
     75                        ret[i].flash_offset = REF_EMPTY_NODE;
     76                        ret[i].next_in_ino = NULL;
     77                }
     78                ret[i].flash_offset = REF_LINK_NODE;
     79                ret[i].next_in_ino = NULL;
     80        }
     81        return ret;
     82}
     83
     84int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
     85                                 struct jffs2_eraseblock *jeb, int nr)
     86{
     87        struct jffs2_raw_node_ref **p, *ref;
     88        int i = nr;
     89
     90        p = &jeb->last_node;
     91        ref = *p;
     92
     93        /* If jeb->last_node is really a valid node then skip over it */
     94        if (ref && ref->flash_offset != REF_EMPTY_NODE)
     95                ref++;
     96
     97        while (i) {
     98                if (!ref) {
     99                        ref = *p = jffs2_alloc_refblock();
     100                        if (!ref)
     101                                return -ENOMEM;
     102                }
     103                if (ref->flash_offset == REF_LINK_NODE) {
     104                        p = &ref->next_in_ino;
     105                        ref = *p;
     106                        continue;
     107                }
     108                i--;
     109                ref++;
     110        }
     111        jeb->allocated_refs = nr;
     112
     113        return 0;
     114}
     115
     116void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
     117{
     118        free(x);
     119}
     120
    72121struct jffs2_node_frag *jffs2_alloc_node_frag(void)
    73122{
     
    79128        free(x);
    80129}
    81 
    82 #if CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
    83 
    84 int jffs2_create_slab_caches(void)
    85 {
    86         return 0;
    87 }
    88 
    89 void jffs2_destroy_slab_caches(void)
    90 {
    91 }
    92 
    93 struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
    94 {
    95         return malloc(sizeof(struct jffs2_raw_node_ref));
    96 }
    97 
    98 void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
    99 {
    100         free(x);
    101 }
    102 
    103 #else // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
    104 
    105 static struct jffs2_raw_node_ref
    106         rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE] __attribute__ ((aligned (4))),
    107         * first = NULL;
    108 static cyg_drv_mutex_t mutex;
    109 
    110 int jffs2_create_slab_caches(void)
    111 {
    112         struct jffs2_raw_node_ref * p;
    113         cyg_drv_mutex_init(&mutex);
    114         for (
    115                 p = rnr_pool;
    116                 p < rnr_pool + CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1;
    117                 p++
    118         )
    119                 p->next_phys = p + 1;
    120         rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1].next_phys = NULL;
    121         first = &rnr_pool[0];
    122         return 0;
    123 }
    124 
    125 void jffs2_destroy_slab_caches(void)
    126 {
    127 }
    128 
    129 struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
    130 {
    131         struct jffs2_raw_node_ref * p;
    132        
    133         cyg_drv_mutex_lock(&mutex);
    134         p = first;
    135         if (p != NULL)
    136                 first = p->next_phys;
    137         cyg_drv_mutex_unlock(&mutex);
    138         return p;
    139 }
    140 
    141 void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
    142 {
    143         cyg_drv_mutex_lock(&mutex);
    144         x->next_phys = first;
    145         first = x;
    146         cyg_drv_mutex_unlock(&mutex);
    147 }
    148 
    149 #endif // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
    150130
    151131struct jffs2_inode_cache *jffs2_alloc_inode_cache(void)
  • cpukit/libfs/src/jffs2/src/nodelist.h

    r78b85286 r3c96bee  
    2222#include "summary.h"
    2323
    24 #ifdef __ECOS
    25 #include "os-ecos.h"
     24#ifdef __rtems__
     25#include "os-rtems.h"
    2626#else
    2727#include "os-linux.h"
     
    310310#define PAD(x) (((x)+3)&~3)
    311311
     312#ifndef __rtems__
    312313static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
    313314{
     
    320321        }
    321322}
     323#endif /* __rtems__ */
    322324
    323325static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
  • cpukit/libfs/src/jffs2/src/os-rtems.h

    r78b85286 r3c96bee  
    22 * JFFS2 -- Journalling Flash File System, Version 2.
    33 *
    4  * Copyright (C) 2002-2003 Free Software Foundation, Inc.
     4 * Copyright © 2002-2003 Free Software Foundation, Inc.
     5 * Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
    56 *
    67 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
    78 *
     9 * Port to the RTEMS by embedded brains GmbH.
     10 *
    811 * For licensing information, see the file 'LICENCE' in this directory.
    912 *
     
    1215 */
    1316
    14 #ifndef __JFFS2_OS_ECOS_H__
    15 #define __JFFS2_OS_ECOS_H__
    16 
    17 #include <pkgconf/fs_jffs2.h>
    18 #include <cyg/io/io.h>
    19 #include <sys/types.h>
     17#ifndef __JFFS2_OS_RTEMS_H__
     18#define __JFFS2_OS_RTEMS_H__
     19
    2020#include <asm/atomic.h>
     21#include <asm/bug.h>
     22#include <linux/compiler.h>
     23#include <linux/list.h>
     24#include <linux/pagemap.h>
    2125#include <linux/stat.h>
    22 #include <linux/compiler.h>
    23 
    24 #include <pkgconf/system.h>
    25 #include <pkgconf/hal.h>
    26 #include <pkgconf/io_fileio.h>
    27 
    28 #include <cyg/infra/cyg_trac.h>        // tracing macros
    29 #include <cyg/infra/cyg_ass.h>         // assertion macros
    30 
    31 #include <unistd.h>
    32 #include <sys/types.h>
     26#include <linux/types.h>
     27#include <dirent.h>
     28#include <errno.h>
    3329#include <fcntl.h>
    34 #include <sys/stat.h>
    35 #include <errno.h>
    36 #include <dirent.h>
    37 
    38 #include <stdlib.h>
    3930#include <string.h>
    40 
    41 #include <cyg/fileio/fileio.h>
    42 
    43 #include <cyg/hal/drv_api.h>
    44 #include <cyg/infra/diag.h>
    45 
    46 #include <cyg/io/flash.h>
    47 
    48 #include <linux/types.h>
    49 #include <linux/list.h>
    50 #include <asm/bug.h>
    51 
    52 #define printf diag_printf
     31#include <time.h>
     32
     33#include <rtems/jffs2.h>
     34
     35#define CONFIG_JFFS2_RTIME
     36
     37#define CONFIG_JFFS2_ZLIB
    5338
    5439struct _inode;
     
    6045};
    6146
    62 static inline unsigned int full_name_hash(const unsigned char * name, unsigned int len) {
     47static inline unsigned int full_name_hash(const unsigned char * name, size_t len) {
    6348
    6449        unsigned hash = 0;
     
    7055}
    7156
    72 #ifdef CYGOPT_FS_JFFS2_WRITE
    73 #define jffs2_is_readonly(c) (0)
    74 #else
    75 #define jffs2_is_readonly(c) (1)
    76 #endif
    77 
    78 /* NAND flash not currently supported on eCos */
     57/* NAND flash not currently supported on RTEMS */
    7958#define jffs2_can_mark_obsolete(c) (1)
    8059
    8160#define JFFS2_INODE_INFO(i) (&(i)->jffs2_i)
    8261#define OFNI_EDONI_2SFFJ(f)  ((struct _inode *) ( ((char *)f) - ((char *)(&((struct _inode *)NULL)->jffs2_i)) ) )
     62
     63#define ITIME(sec) (sec)
     64#define I_SEC(tv) (tv)
    8365 
    8466#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size)
     
    9072#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime)
    9173
    92 /* FIXME: eCos doesn't hav a concept of device major/minor numbers */
    93 #define JFFS2_F_I_RDEV_MIN(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)&0xff)
    94 #define JFFS2_F_I_RDEV_MAJ(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)>>8)
    95 
    96 #define get_seconds cyg_timestamp
     74#define get_seconds() time(NULL)
    9775
    9876struct _inode {
     
    11391//      };
    11492        struct super_block *    i_sb;
     93        struct jffs2_full_dirent * i_fd;
    11594
    11695        struct jffs2_inode_info jffs2_i;
     
    126105        struct jffs2_sb_info    jffs2_sb;
    127106        struct _inode *         s_root;
    128         unsigned long           s_mount_count;
    129         cyg_io_handle_t         s_dev;
    130 
    131 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
    132         cyg_mutex_t s_lock;             // Lock the inode cache
    133         cyg_flag_t  s_gc_thread_flags;  // Communication with the gcthread
    134         cyg_handle_t s_gc_thread_handle;
    135         cyg_thread s_gc_thread;
    136 #if (CYGNUM_JFFS2_GC_THREAD_STACK_SIZE >= CYGNUM_HAL_STACK_SIZE_MINIMUM)
    137         char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE];
    138 #else
    139         char s_gc_thread_stack[CYGNUM_HAL_STACK_SIZE_MINIMUM];
    140 #endif
    141        cyg_mtab_entry *mte;
    142 #endif
     107        rtems_jffs2_flash_control       *s_flash_control;
     108        rtems_jffs2_compressor_control  *s_compressor_control;
     109        bool                    s_is_readonly;
     110        unsigned char           s_gc_buffer[PAGE_CACHE_SIZE]; // Avoids malloc when user may be under memory pressure
     111        rtems_id                s_mutex;
     112        char                    s_name_buf[JFFS2_MAX_NAME_LEN];
    143113};
    144114
     
    146116#define EBADFD 32767
    147117
    148 /* background.c */
    149 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
    150 void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
    151 void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
    152 void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
    153 #else
     118static inline bool jffs2_is_readonly(struct jffs2_sb_info *c)
     119{
     120        struct super_block *sb = OFNI_BS_2SFFJ(c);
     121
     122        return sb->s_is_readonly;
     123}
     124
    154125static inline void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
    155126{
    156         /* We don't have a GC thread in eCos (yet) */
    157 }
    158 #endif
    159 
    160 /* fs-ecos.c */
     127       /* We don't have a GC thread in RTEMS (yet) */
     128}
     129
     130/* fs-rtems.c */
    161131struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri);
    162132struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino);
     
    168138void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv);
    169139
    170 /* Avoid polluting eCos namespace with names not starting in jffs2_ */
     140/* Avoid polluting RTEMS namespace with names not starting in jffs2_ */
    171141#define os_to_jffs2_mode(x) jffs2_from_os_mode(x)
    172 uint32_t jffs2_from_os_mode(uint32_t osmode);
    173 uint32_t jffs2_to_os_mode (uint32_t jmode);
     142static inline uint32_t jffs2_from_os_mode(uint32_t osmode)
     143{
     144  return osmode & (S_IFMT | S_IRWXU | S_IRWXG | S_IRWXO);
     145}
     146
     147static inline uint32_t jffs2_to_os_mode (uint32_t jmode)
     148{
     149  return jmode & (S_IFMT | S_IRWXU | S_IRWXG | S_IRWXO);
     150}
    174151
    175152
    176153/* flashio.c */
    177 cyg_bool jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset,
     154int jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset,
    178155                          const size_t size, size_t * return_size, unsigned char * write_buffer);
    179 cyg_bool jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset,
     156int jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset,
    180157                           const size_t size, size_t * return_size, unsigned char * read_buffer);
    181158int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
    182159                              unsigned long count, loff_t to, size_t *retlen);
    183 cyg_bool jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
    184 
    185 // dir-ecos.c
    186 struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, int namelen);
    187 int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode, struct _inode **new_i);
    188 int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode);
    189 int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name);
    190 int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
    191 int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
    192 int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
    193                   struct _inode *new_dir_i, const unsigned char *new_d_name);
     160int jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
     161
     162// dir-rtems.c
     163struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, size_t namelen);
     164int jffs2_create(struct _inode *dir_i, const char *d_name, size_t d_namelen, int mode);
     165int jffs2_mknod(struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen, int mode, const unsigned char *data, size_t datalen);
     166int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen);
     167int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen);
     168int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen);
     169int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, size_t old_d_namelen,
     170                  struct _inode *new_dir_i, const unsigned char *new_d_name, size_t new_d_namelen);
    194171
    195172/* erase.c */
     
    200177#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) )
    201178#define jffs2_can_mark_obsolete(c) (1)
     179#define jffs2_is_writebuffered(c) (0)
    202180#define jffs2_cleanmarker_oob(c) (0)
    203181#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO)
     
    224202#define __init
    225203
    226 #endif /* __JFFS2_OS_ECOS_H__ */
     204#endif /* __JFFS2_OS_RTEMS_H__ */
  • cpukit/libfs/src/jffs2/src/readinode.c

    r78b85286 r3c96bee  
    417417        *link = node->rb_left;
    418418        if (node->rb_left)
     419#ifndef __rtems__
    419420                node->rb_left->__rb_parent_color = node->__rb_parent_color;
     421#else /* __rtems__ */
     422        {
     423                node->rb_left->rb_parent = node->rb_parent;
     424                node->rb_left->rb_color = node->rb_color;
     425        }
     426#endif /* __rtems__ */
    420427}
    421428
  • cpukit/libfs/src/jffs2/src/scan.c

    r78b85286 r3c96bee  
    9696        uint32_t buf_size = 0;
    9797        struct jffs2_summary *s = NULL; /* summary info collected by the scan process */
     98        size_t try_size;
    9899#ifndef __ECOS
    99         size_t pointlen, try_size;
     100        size_t pointlen;
    100101
    101102        ret = mtd_point(c->mtd, 0, c->mtd->size, &pointlen,
  • cpukit/preinstall.am

    r78b85286 r3c96bee  
    258258PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rfs/rtems-rfs-trace.h
    259259
     260$(PROJECT_INCLUDE)/rtems/jffs2.h: libfs/src/jffs2/include/rtems/jffs2.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
     261        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/jffs2.h
     262PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/jffs2.h
     263
    260264$(PROJECT_INCLUDE)/rtems/bdbuf.h: libblock/include/rtems/bdbuf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
    261265        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bdbuf.h
  • cpukit/sapi/include/confdefs.h

    r78b85286 r3c96bee  
    238238 *     CONFIGURE_FILESYSTEM_DOSFS    - DOS File System, uses libblock
    239239 *     CONFIGURE_FILESYSTEM_RFS      - RTEMS File System (RFS), uses libblock
     240 *     CONFIGURE_FILESYSTEM_JFFS2    - Journalling Flash File System, Version 2
    240241 *
    241242 *   Combinations:
     
    265266    #define CONFIGURE_FILESYSTEM_DOSFS
    266267    #define CONFIGURE_FILESYSTEM_RFS
     268    #define CONFIGURE_FILESYSTEM_JFFS2
    267269  #endif
    268270
     
    284286        defined(CONFIGURE_FILESYSTEM_NFS) || \
    285287        defined(CONFIGURE_FILESYSTEM_DOSFS) || \
    286         defined(CONFIGURE_FILESYSTEM_RFS)
     288        defined(CONFIGURE_FILESYSTEM_RFS) || \
     289        defined(CONFIGURE_FILESYSTEM_JFFS2)
    287290        #error "Configured filesystems but root filesystem was not IMFS!"
    288291        #error "Filesystems could be disabled, DEVFS is root, or"
     
    439442  #define CONFIGURE_FILESYSTEM_ENTRY_RFS \
    440443    { RTEMS_FILESYSTEM_TYPE_RFS, rtems_rfs_rtems_initialise }
     444#endif
     445
     446/**
     447 * JFFS2
     448 */
     449#if !defined(CONFIGURE_FILESYSTEM_ENTRY_JFFS2) && \
     450    defined(CONFIGURE_FILESYSTEM_JFFS2)
     451  #include <rtems/jffs2.h>
     452  #define CONFIGURE_FILESYSTEM_ENTRY_JFFS2 \
     453    { RTEMS_FILESYSTEM_TYPE_JFFS2, rtems_jffs2_initialize }
    441454#endif
    442455
     
    514527        CONFIGURE_FILESYSTEM_ENTRY_RFS,
    515528      #endif
     529      #if defined(CONFIGURE_FILESYSTEM_JFFS2) && \
     530          defined(CONFIGURE_FILESYSTEM_ENTRY_JFFS2)
     531        CONFIGURE_FILESYSTEM_ENTRY_JFFS2,
     532      #endif
    516533      CONFIGURE_FILESYSTEM_NULL
    517534    };
  • cpukit/wrapup/Makefile.am

    r78b85286 r3c96bee  
    2828TMP_LIBS += ../libfs/libimfs.a
    2929TMP_LIBS += ../libfs/librfs.a
     30TMP_LIBS += ../libfs/libjffs2.a
    3031
    3132TMP_LIBS += ../libmisc/libmonitor.a
Note: See TracChangeset for help on using the changeset viewer.