diff --git a/cpukit/include/rtems/confdefs/libio.h b/cpukit/include/rtems/confdefs/libio.h index c14941dabd..bf07452176 100644 --- a/cpukit/include/rtems/confdefs/libio.h +++ b/cpukit/include/rtems/confdefs/libio.h @@ -200,6 +200,15 @@ extern "C" { const int imfs_memfile_bytes_per_block = CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK; +/* + * Using the default ops if user doesn't configure ops + */ +#ifndef CONFIGURE_IMFS_MEMFILE_OPS + #define CONFIGURE_IMFS_MEMFILE_OPS IMFS_MEMFILE_DEFAULT_OPS +#endif + +IMFS_memfile_ops_t imfs_memfile_ops = CONFIGURE_IMFS_MEMFILE_OPS; + static IMFS_fs_info_t IMFS_root_fs_info; static const rtems_filesystem_operations_table IMFS_root_ops = { diff --git a/cpukit/include/rtems/imfs.h b/cpukit/include/rtems/imfs.h index 114795403c..7645f869da 100644 --- a/cpukit/include/rtems/imfs.h +++ b/cpukit/include/rtems/imfs.h @@ -61,6 +61,9 @@ extern "C" { struct IMFS_jnode_tt; typedef struct IMFS_jnode_tt IMFS_jnode_t; +typedef struct IMFS_memfile_ops_t IMFS_memfile_ops_t; +extern IMFS_memfile_ops_t imfs_memfile_ops; + /** * IMFS "memfile" information * @@ -283,6 +286,65 @@ struct IMFS_jnode_tt { const IMFS_node_control *control; }; +/** + * @brief The type of allocator function pointer. + */ +typedef void *(*IMFS_memfile_allocator)(void); + +/** + * @brief The type of deallocator function pointer. + */ +typedef void (*IMFS_memfile_deallocator)( + void *memory +); + +/** + * @brief The get_free_space function pointer. + */ +typedef size_t (*IMFS_memfile_free_space)(void); + +/** + * @brief The ops table for user defined allocator-deallocator for + * IMFS memfile data blocks. + * + * @param allocate The function which will be used to allocate IMFS blocks. + * @param deallocate The function to deallocate the allocated data blocks. + * @param get_free_space The function used by kernel to get the free space. + */ +struct IMFS_memfile_ops_t { + IMFS_memfile_allocator allocate_block; + IMFS_memfile_deallocator free_block; + IMFS_memfile_free_space get_free_space; +}; + +/** + * @brief The default imfs block allocator + * + * @details The allocator uses the memory from the heap. + */ +void *IMFS_default_allocate_block(void); + +/** + * @brief The default imfs block deallocator + * + * @details The deallocator frees the memory which was taken from heap. + */ +void IMFS_default_deallocate_block(void *); + +/** + * @brief The default free space calculator + * + * @details The free_space function calculates the free space in heap. + */ +size_t IMFS_default_free_space(void); + +#define IMFS_MEMFILE_DEFAULT_OPS \ +{ \ + .allocate_block = IMFS_default_allocate_block, \ + .free_block = IMFS_default_deallocate_block, \ + .get_free_space = IMFS_default_free_space \ +} + typedef struct { IMFS_jnode_t Node; rtems_chain_control Entries; diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c index b9a83d130e..df008d36b0 100644 --- a/cpukit/libfs/src/imfs/imfs_initsupp.c +++ b/cpukit/libfs/src/imfs/imfs_initsupp.c @@ -40,6 +40,7 @@ #include +#include #include int IMFS_initialize_support( @@ -52,6 +53,10 @@ int IMFS_initialize_support( const IMFS_node_control *node_control; IMFS_jnode_t *root_node; + _Assert(imfs_memfile_ops.allocate_block != NULL); + _Assert(imfs_memfile_ops.free_block != NULL); + _Assert(imfs_memfile_ops.get_free_space != NULL); + mount_data = data; fs_info = mount_data->fs_info; diff --git a/cpukit/libfs/src/imfs/imfs_memfile.c b/cpukit/libfs/src/imfs/imfs_memfile.c index 3930fd6ae5..f9a576a294 100644 --- a/cpukit/libfs/src/imfs/imfs_memfile.c +++ b/cpukit/libfs/src/imfs/imfs_memfile.c @@ -38,6 +38,7 @@ #include "config.h" #endif +#include #include #include @@ -831,7 +832,7 @@ void *memfile_alloc_block(void) { void *memory; - memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK); + memory = imfs_memfile_ops.allocate_block(); if ( memory ) memfile_blocks_allocated++; @@ -847,10 +848,25 @@ void memfile_free_block( void *memory ) { - free(memory); + imfs_memfile_ops.free_block(memory); memfile_blocks_allocated--; } +void *IMFS_default_allocate_block(void) +{ + return (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK); +} + +void IMFS_default_deallocate_block(void *memory) +{ + free(memory); +} + +size_t IMFS_default_free_space(void) +{ + return malloc_free_space(); +} + static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = { .open_h = rtems_filesystem_default_open, .close_h = rtems_filesystem_default_close, diff --git a/cpukit/libfs/src/imfs/imfs_statvfs.c b/cpukit/libfs/src/imfs/imfs_statvfs.c index 65787da277..24206cb767 100644 --- a/cpukit/libfs/src/imfs/imfs_statvfs.c +++ b/cpukit/libfs/src/imfs/imfs_statvfs.c @@ -47,8 +47,8 @@ int IMFS_statvfs( buf->f_bsize = IMFS_MEMFILE_BYTES_PER_BLOCK; buf->f_frsize = IMFS_MEMFILE_BYTES_PER_BLOCK; buf->f_blocks = UINT_MAX / IMFS_MEMFILE_BYTES_PER_BLOCK; - buf->f_bfree = malloc_free_space() / IMFS_MEMFILE_BYTES_PER_BLOCK; - buf->f_bavail = malloc_free_space() / IMFS_MEMFILE_BYTES_PER_BLOCK; + buf->f_bfree = imfs_memfile_ops.get_free_space() / IMFS_MEMFILE_BYTES_PER_BLOCK; + buf->f_bavail = imfs_memfile_ops.get_free_space() / IMFS_MEMFILE_BYTES_PER_BLOCK; buf->f_files = fs_info->jnode_count; buf->f_fsid = 1; buf->f_flag = loc->mt_entry->writeable; diff --git a/spec/build/testsuites/psxtests/grp.yml b/spec/build/testsuites/psxtests/grp.yml index 4a58494ae1..82c64cbb7f 100644 --- a/spec/build/testsuites/psxtests/grp.yml +++ b/spec/build/testsuites/psxtests/grp.yml @@ -141,6 +141,8 @@ links: uid: psximfs01 - role: build-dependency uid: psximfs02 +- role: build-dependency + uid: psximfs03 - role: build-dependency uid: psxintrcritical01 - role: build-dependency diff --git a/spec/build/testsuites/psxtests/psximfs01.yml b/spec/build/testsuites/psxtests/psximfs01.yml index ac1d88bc00..9272ed43f4 100644 --- a/spec/build/testsuites/psxtests/psximfs01.yml +++ b/spec/build/testsuites/psxtests/psximfs01.yml @@ -12,6 +12,7 @@ ldflags: [] links: [] source: - testsuites/psxtests/psximfs01/init.c +- testsuites/psxtests/psximfs/init.c stlib: [] target: testsuites/psxtests/psximfs01.exe type: build diff --git a/spec/build/testsuites/psxtests/psximfs03.yml b/spec/build/testsuites/psxtests/psximfs03.yml new file mode 100644 index 0000000000..e67bd9947c --- /dev/null +++ b/spec/build/testsuites/psxtests/psximfs03.yml @@ -0,0 +1,21 @@ + +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +build-type: test-program +cflags: [] +copyrights: +- Copyright (C) 2025 Bhavya Shah +cppflags: [] +cxxflags: [] +enabled-by: true +features: c cprogram +includes: [] +ldflags: [] +links: [] +source: +- testsuites/psxtests/psximfs/init.c +- testsuites/psxtests/psximfs03/init.c +stlib: [] +target: testsuites/psxtests/psximfs03.exe +type: build +use-after: [] +use-before: [] diff --git a/testsuites/psxtests/psximfs/init.c b/testsuites/psxtests/psximfs/init.c new file mode 100644 index 0000000000..692b815931 --- /dev/null +++ b/testsuites/psxtests/psximfs/init.c @@ -0,0 +1,321 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "system.h" +#define BLOCK_SIZE 16 + +/* forward declarations to avoid warnings */ +rtems_task Init(rtems_task_argument argument); +void open_it(bool readOnly, bool create); +void write_helper(void); +void read_helper(void); +void truncate_helper(void); +void extend_helper(int eno); +void close_it(void); +void unlink_it(void); +void statvfs_helper(void); +__attribute__((weak)) void init_memory(void); +__attribute__((weak)) void validate_data_blocks_count(void); + +int TestFd; +uint8_t Buffer[256]; +ssize_t TotalWritten; + +#define FILE_NAME "biggie" + +void open_it(bool readOnly, bool create) +{ + int flag = 0; + + if ( readOnly ) + flag |= O_RDONLY; + else { + if ( create ) + flag |= O_CREAT; + flag |= O_RDWR; + } + + /* open the file */ + puts( "open(" FILE_NAME ") - OK " ); + TestFd = open( FILE_NAME, flag, 0777 ); + rtems_test_assert( TestFd != -1 ); +} + +void write_helper(void) +{ + ssize_t written; + + TotalWritten = 0; + puts( "write(" FILE_NAME ") - OK " ); + do { + written = write( TestFd, Buffer, sizeof(Buffer) ); + if ( written == -1 ) { + if ( errno == EFBIG ) { + printf( "Total written = %zd\n", TotalWritten ); + return; + } + printf( + "Unable to create largest IMFS file (error=%s)\n", + strerror(errno) + ); + rtems_test_exit(0); + } + TotalWritten += written; + } while (1); + +} + +void read_helper(void) +{ + uint8_t ch; + ssize_t sc; + int i=0; + + puts( "read(" FILE_NAME ") - OK " ); + do { + sc = read( TestFd, &ch, sizeof(ch) ); + if ( sc == 1 ) { + if ( ch != (i%256) ) { + printf( + "MISMATCH 0x%02x != 0x%02x at offset %d\n", + ch, + i % 256, + i + ); + rtems_test_exit(0); + } + i++; + } else if ( sc != 0 ) { + printf( + "ERROR - at offset %d - returned %zd and error=%s\n", + i, + sc, + strerror( errno ) + ); + rtems_test_exit(0); + } + } while ( sc > 0 ); + + if ( i == TotalWritten ) { + puts( "File correctly read until EOF returned\n" ); + } +} + +void truncate_helper(void) +{ + off_t position; + off_t new; + off_t sc; + int rc; + + position = lseek( TestFd, 0, SEEK_END ); + printf( "Seek to end .. returned %d\n", (int) position ); + rtems_test_assert( position == TotalWritten ); + + puts( "lseek/ftruncate loop.." ); + new = position; + do { + sc = lseek( TestFd, new, SEEK_SET ); + rtems_test_assert( sc == new ); + + rc = ftruncate( TestFd, new ); + if ( rc != 0 ) { + printf( + "ERROR - at offset %d - returned %d and error=%s\n", + (int) new, + rc, + strerror( errno ) + ); + } + rtems_test_assert( rc == 0 ); + --new; + } while (new > 0); +} + +void extend_helper(int eno) +{ + off_t position; + off_t new; + off_t sc; + int rc; + + position = lseek( TestFd, 0, SEEK_END ); + printf( "Seek to end .. returned %d\n", (int) position ); + + /* + * test case to ftruncate a file to a length > its size + */ + + rc = ftruncate( TestFd, 2 ); + rtems_test_assert( rc == 0 || errno == eno ); + + puts( "lseek/ftruncate loop.." ); + new = position; + do { + sc = lseek( TestFd, new, SEEK_SET ); + rtems_test_assert( sc == new ); + + rc = ftruncate( TestFd, new ); + if ( rc != 0 ) { + if( errno != eno ) { + printf( + "ERROR - at offset %d - returned %d and error=%s\n", + (int) new, + rc, + strerror( errno ) + ); + break; + } + else { + break; + } + } + rtems_test_assert( rc == 0 ); + ++new; + } while ( 1 ); +} + +void close_it(void) +{ + int rc; + + puts( "close(" FILE_NAME ") - OK " ); + rc = close( TestFd ); + rtems_test_assert( rc == 0 ); +} + +void unlink_it(void) +{ + int rc; + + puts( "unlink(" FILE_NAME ") - OK" ); + rc = unlink( FILE_NAME ); + rtems_test_assert( rc == 0 ); +} + +void statvfs_helper(void) +{ + struct statvfs imfs_statvfs; + puts( "statvfs(" FILE_NAME ") - OK " ); + int rc = statvfs(FILE_NAME, &imfs_statvfs); + rtems_test_assert(rc == 0); + //rtems_test_assert(imfs_statvfs.f_bsize == BLOCK_SIZE); + rtems_test_assert(imfs_statvfs.f_files == 2); +} + +rtems_task Init( + rtems_task_argument argument +) +{ + int i; + void *alloc_ptr = (void *)0; + off_t position; + off_t new_position; + char buf [1]; + ssize_t n; + + TEST_BEGIN(); + + if (init_memory) + { + init_memory(); + } + + for (i=0 ; i +/* end of file */ + diff --git a/testsuites/psxtests/psximfs/system.h b/testsuites/psxtests/psximfs/system.h new file mode 100644 index 0000000000..13a8790dd1 --- /dev/null +++ b/testsuites/psxtests/psximfs/system.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (c) 2025 On-Line Application Research Corporation (OAR) + * Copyright (c) 2025 Bhavya Shah + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PSXIMFS_SYSTEM_H +#define PSXIMFS_SYSTEM_H + +#include +#include "test_support.h" + +#include +#include +#include +#include +#include +#include +#include + + +/* macros */ +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + +#define CONFIGURE_MAXIMUM_TASKS 1 +#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4 +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +/* functions */ + +void *empty_space(void); +void fill_space(void *); + +rtems_task Init( + rtems_task_argument argument +); + +#include +#endif diff --git a/testsuites/psxtests/psximfs01/init.c b/testsuites/psxtests/psximfs01/init.c index 9f29f9d10a..c80944c694 100644 --- a/testsuites/psxtests/psximfs01/init.c +++ b/testsuites/psxtests/psximfs01/init.c @@ -44,279 +44,24 @@ #define BLOCK_SIZE 16 const char rtems_test_name[] = "PSXIMFS 1"; -/* forward declarations to avoid warnings */ -rtems_task Init(rtems_task_argument argument); -void open_it(bool readOnly, bool create); -void write_helper(void); -void read_helper(void); -void truncate_helper(void); -void extend_helper(int eno); -void close_it(void); -void unlink_it(void); -void statvfs_helper(void); +void *empty_space(void); +void fill_space(void *); -int TestFd; -uint8_t Buffer[256]; -ssize_t TotalWritten; - -#define FILE_NAME "biggie" - -void open_it(bool readOnly, bool create) +void *empty_space() { - int flag = 0; - - if ( readOnly ) - flag |= O_RDONLY; - else { - if ( create ) - flag |= O_CREAT; - flag |= O_RDWR; - } - - /* open the file */ - puts( "open(" FILE_NAME ") - OK " ); - TestFd = open( FILE_NAME, flag, 0777 ); - rtems_test_assert( TestFd != -1 ); + return malloc( malloc_free_space() - 4 ); } -void write_helper(void) +void fill_space(void *memory) { - ssize_t written; - - TotalWritten = 0; - puts( "write(" FILE_NAME ") - OK " ); - do { - written = write( TestFd, Buffer, sizeof(Buffer) ); - if ( written == -1 ) { - if ( errno == EFBIG ) { - printf( "Total written = %zd\n", TotalWritten ); - return; - } - printf( - "Unable to create largest IMFS file (error=%s)\n", - strerror(errno) - ); - rtems_test_exit(0); - } - TotalWritten += written; - } while (1); - -} - -void read_helper(void) -{ - uint8_t ch; - ssize_t sc; - int i=0; - - puts( "read(" FILE_NAME ") - OK " ); - do { - sc = read( TestFd, &ch, sizeof(ch) ); - if ( sc == 1 ) { - if ( ch != (i%256) ) { - printf( - "MISMATCH 0x%02x != 0x%02x at offset %d\n", - ch, - i % 256, - i - ); - rtems_test_exit(0); - } - i++; - } else if ( sc != 0 ) { - printf( - "ERROR - at offset %d - returned %zd and error=%s\n", - i, - sc, - strerror( errno ) - ); - rtems_test_exit(0); - } - } while ( sc > 0 ); - - if ( i == TotalWritten ) { - puts( "File correctly read until EOF returned\n" ); - } -} - -void truncate_helper(void) -{ - off_t position; - off_t new; - off_t sc; - int rc; - - position = lseek( TestFd, 0, SEEK_END ); - printf( "Seek to end .. returned %d\n", (int) position ); - rtems_test_assert( position == TotalWritten ); - - puts( "lseek/ftruncate loop.." ); - new = position; - do { - sc = lseek( TestFd, new, SEEK_SET ); - rtems_test_assert( sc == new ); - - rc = ftruncate( TestFd, new ); - if ( rc != 0 ) { - printf( - "ERROR - at offset %d - returned %d and error=%s\n", - (int) new, - rc, - strerror( errno ) - ); - } - rtems_test_assert( rc == 0 ); - --new; - } while (new > 0); -} - -void extend_helper(int eno) -{ - off_t position; - off_t new; - off_t sc; - int rc; - - position = lseek( TestFd, 0, SEEK_END ); - printf( "Seek to end .. returned %d\n", (int) position ); - - /* - * test case to ftruncate a file to a length > its size - */ - - rc = ftruncate( TestFd, 2 ); - rtems_test_assert( rc == 0 ); - - puts( "lseek/ftruncate loop.." ); - new = position; - do { - sc = lseek( TestFd, new, SEEK_SET ); - rtems_test_assert( sc == new ); - - rc = ftruncate( TestFd, new ); - if ( rc != 0 ) { - if( errno != eno ) { - printf( - "ERROR - at offset %d - returned %d and error=%s\n", - (int) new, - rc, - strerror( errno ) - ); - break; - } - else { - break; - } - } - rtems_test_assert( rc == 0 ); - ++new; - } while ( 1 ); -} - -void close_it(void) -{ - int rc; - - puts( "close(" FILE_NAME ") - OK " ); - rc = close( TestFd ); - rtems_test_assert( rc == 0 ); -} - -void unlink_it(void) -{ - int rc; - - puts( "unlink(" FILE_NAME ") - OK" ); - rc = unlink( FILE_NAME ); - rtems_test_assert( rc == 0 ); -} - -void statvfs_helper(void) -{ - struct statvfs imfs_statvfs; - puts( "statvfs(" FILE_NAME ") - OK " ); - int rc = statvfs(FILE_NAME, &imfs_statvfs); - rtems_test_assert(rc == 0); - rtems_test_assert(imfs_statvfs.f_bsize == BLOCK_SIZE); - rtems_test_assert(imfs_statvfs.f_files == 2); -} - -rtems_task Init( - rtems_task_argument argument -) -{ - (void) argument; - - int i; - void *alloc_ptr = (void *)0; - off_t position; - off_t new_position; - char buf [1]; - ssize_t n; - - TEST_BEGIN(); - - for (i=0 ; i +#include "../psximfs/system.h" /* end of file */ diff --git a/testsuites/psxtests/psximfs01/psximfs01.scn b/testsuites/psxtests/psximfs01/psximfs01.scn index 36c10afc76..41d2807449 100644 --- a/testsuites/psxtests/psximfs01/psximfs01.scn +++ b/testsuites/psxtests/psximfs01/psximfs01.scn @@ -7,7 +7,7 @@ close(biggie) - OK open(biggie) - OK read(biggie) - OK -File correctly read until ENOSPC returned +File correctly read until EOF returned close(biggie) - OK open(biggie) - OK diff --git a/testsuites/psxtests/psximfs03/init.c b/testsuites/psxtests/psximfs03/init.c new file mode 100644 index 0000000000..0a90e01e7d --- /dev/null +++ b/testsuites/psxtests/psximfs03/init.c @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (c) 2025 On-Line Application Research Corporation (OAR) + * Copyright (c) 2025 Bhavya Shah + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "test_support.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +const char rtems_test_name[] = "PSXIMFS 3"; +#define BLOCK_SIZE 16 + +typedef struct block{ + struct block * next; + char data[BLOCK_SIZE - sizeof(struct block*)]; +} block; + +/* forward declarations to avoid warnings */ + +void *allocator(void); +void deallocator(void *); +size_t free_space(void); +void init_memory(void); +void *empty_space(void); +void fill_space(void *); +void validate_data_blocks_count(void); + +#define MEMORY_SIZE 1000000000 + +char memory[MEMORY_SIZE]; +static int alloc_blocks_count = 0; +block *freelist = NULL; + +void *allocator(void) +{ + if (!freelist) { + return NULL; + } + block *blk = freelist; + freelist = blk->next; + memset(blk, 0, BLOCK_SIZE); + alloc_blocks_count ++; + return blk; +} + +void deallocator( + void *memory +) +{ + block *blk = (block *)memory; + + if (!blk) { + return; + } + + memset(blk, 0, BLOCK_SIZE); + blk->next = freelist; + freelist = blk; + alloc_blocks_count --; +} + +size_t free_space(void) +{ + return MEMORY_SIZE - alloc_blocks_count * BLOCK_SIZE; +} + +void init_memory(void) +{ + rtems_test_assert( sizeof(block) == BLOCK_SIZE ); + + block *first = (block *)memory; + const char *last = memory + sizeof(memory); + + while ( first + 1 <= (block *)last ) { + first->next = freelist; + freelist = first; + first += 1; + } + alloc_blocks_count = 0; +} + +void *empty_space() +{ + block *memory = freelist; + freelist = NULL; + return memory; +} + +void fill_space(void *memory) +{ + freelist = memory; +} + +void validate_data_blocks_count(void) +{ + int indirect_block_count = 1 + BLOCK_SIZE / sizeof(void *); + int double_indirect_block_count = 1 + (BLOCK_SIZE / sizeof(void *)) * indirect_block_count; + int triple_indirect_block_count = 1 + (BLOCK_SIZE / sizeof(void *)) * double_indirect_block_count; + int expected_data_blocks_counts = indirect_block_count; + expected_data_blocks_counts += double_indirect_block_count; + expected_data_blocks_counts += triple_indirect_block_count; + + rtems_test_assert( expected_data_blocks_counts == alloc_blocks_count ); +} + +/* configuration information */ + +#define CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK BLOCK_SIZE +#define CONFIGURE_IMFS_MEMFILE_OPS \ + { \ + .allocate_block = allocator, \ + .free_block = deallocator, \ + .get_free_space = free_space \ + } +#define CONFIGURE_INIT + +#include "../psximfs/system.h" +/* end of file */ diff --git a/testsuites/psxtests/psximfs03/psximfs03.doc b/testsuites/psxtests/psximfs03/psximfs03.doc new file mode 100644 index 0000000000..771148d01b --- /dev/null +++ b/testsuites/psxtests/psximfs03/psximfs03.doc @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: BSD-2-Clause + +# Copyright (c) 2025 On-Line Application Research Corporation (OAR) +# Copyright (c) 2025 Bhavya Shah +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +This file describes the directives and concepts tested by this test set. + +test set name: psximfs03 + +directives: + + + open + + close + + read + + write + + lseek + + ftruncate + + unlink + + statvfs + +concepts: + ++ Create an IMFS instance with the smallest possible block size. This +ensures the maximum file size is relatively small. + ++ Ensures the IMFS user allocator-deallocator plugin works. + ++ Ensures the IMFS block size is correctly configured. + ++ Create, write, and read a file of maximum size. + ++ Use ftruncate to shorten the file from the maximum size to 0. + ++ This should exercise much of the singly, doubly and triply indirect +block management code in the IMFS which uses static data blocks. + ++ Exercise unlink, and hence IMFS_memfile_remove diff --git a/testsuites/psxtests/psximfs03/psximfs03.scn b/testsuites/psxtests/psximfs03/psximfs03.scn new file mode 100644 index 0000000000..1dabf4c525 --- /dev/null +++ b/testsuites/psxtests/psximfs03/psximfs03.scn @@ -0,0 +1,24 @@ +*** BEGIN OF TEST PSXIMFS 3 *** + +open(biggie) - OK +statvfs(biggie) - OK +write(biggie) - OK +Total written = 1280 +close(biggie) - OK + +open(biggie) - OK +read(biggie) - OK +File correctly read until EOF returned + +close(biggie) - OK +open(biggie) - OK +Seek to end .. returned 1280 +lseek/ftruncate loop.. +Seek to end .. returned 1 +lseek/ftruncate loop.. +Seek to end .. returned 1295 +lseek/ftruncate loop.. +close(biggie) - OK +unlink(biggie) - OK + +*** END OF TEST PSXIMFS 3 ***