imfs/user_allocator: Add user-configurable allocator support

- Extend IMFS and libio headers to define default allocator/deallocator ops
  and logic for configuring memfile_ops.
- Update imfs_memfile to use custom allocators for memory blocks.
- Fix imfs_statvfs.f_bfree calculation to respect user-defined ops.
- Add psximfs03 test case to validate custom allocator behavior.
- Refactor psximfs01 to share helper functions with psximfs03.
This commit is contained in:
Bhavya Shah
2025-12-11 17:45:13 -06:00
committed by Kinsey Moore
parent 05629d07e2
commit 6367099ec0
15 changed files with 747 additions and 267 deletions
+9
View File
@@ -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 = {
+62
View File
@@ -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;
+5
View File
@@ -40,6 +40,7 @@
#include <rtems/imfs.h>
#include <stdlib.h>
#include <errno.h>
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;
+18 -2
View File
@@ -38,6 +38,7 @@
#include "config.h"
#endif
#include <rtems/libcsupport.h>
#include <rtems/imfsimpl.h>
#include <stdlib.h>
@@ -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,
+2 -2
View File
@@ -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;
+2
View File
@@ -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
@@ -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
@@ -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 <bhavyashah8443@gmail.com>
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: []
+321
View File
@@ -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<sizeof(Buffer) ; i++ )
Buffer[i] = (uint8_t) i;
open_it(false, true);
statvfs_helper();
write_helper();
close_it();
puts( "" );
open_it(true, false);
read_helper();
close_it();
open_it(false, false);
truncate_helper();
/*
* empty the space, so that extend cannot be successful
*/
alloc_ptr = empty_space();
extend_helper(ENOSPC);
/*
* free the allocated memory
*/
fill_space(alloc_ptr);
extend_helper(EFBIG);
position = lseek( TestFd , 0, SEEK_END );
new_position = lseek( TestFd, position + 2, SEEK_SET );
rtems_test_assert( new_position == position + 2 );
n = write( TestFd, buf, sizeof(buf) );
rtems_test_assert( n == -1 );
rtems_test_assert( errno == EFBIG );
close_it();
if (validate_data_blocks_count)
{
validate_data_blocks_count();
}
unlink_it();
TEST_END();
rtems_test_exit(0);
}
/* configuration information */
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_MAXIMUM_TASKS 1
#define CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK BLOCK_SIZE
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_INIT
#include <rtems/confdefs.h>
/* end of file */
+63
View File
@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2025 On-Line Application Research Corporation (OAR)
* Copyright (c) 2025 Bhavya Shah <bhavyashah8443@gmail.com>
*
* 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 <tmacros.h>
#include "test_support.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <fcntl.h>
#include <errno.h>
#include <rtems/libcsupport.h>
/* 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 <rtems/confdefs.h>
#endif
+7 -262
View File
@@ -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<sizeof(Buffer) ; i++ )
Buffer[i] = (uint8_t) i;
open_it(false, true);
statvfs_helper();
write_helper();
close_it();
puts( "" );
open_it(true, false);
read_helper();
close_it();
open_it(false, false);
truncate_helper();
/*
* Allocate the heap, so that extend cannot be successful
*/
alloc_ptr = malloc( malloc_free_space() - 4 );
extend_helper(ENOSPC);
/*
* free the allocated heap memory
*/
free(alloc_ptr);
extend_helper(EFBIG);
position = lseek( TestFd , 0, SEEK_END );
new_position = lseek( TestFd, position + 2, SEEK_SET );
rtems_test_assert( new_position == position + 2 );
n = write( TestFd, buf, sizeof(buf) );
rtems_test_assert( n == -1 );
rtems_test_assert( errno == EFBIG );
close_it();
unlink_it();
TEST_END();
rtems_test_exit(0);
free(memory);
}
/* configuration information */
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_MAXIMUM_TASKS 1
#define CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK BLOCK_SIZE
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_INIT
#include <rtems/confdefs.h>
#include "../psximfs/system.h"
/* end of file */
+1 -1
View File
@@ -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
+153
View File
@@ -0,0 +1,153 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2025 On-Line Application Research Corporation (OAR)
* Copyright (c) 2025 Bhavya Shah <bhavyashah8443@gmail.com>
*
* 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 <tmacros.h>
#include "test_support.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <fcntl.h>
#include <errno.h>
#include <rtems/libcsupport.h>
#include <rtems/imfs.h>
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 */
@@ -0,0 +1,58 @@
# SPDX-License-Identifier: BSD-2-Clause
# Copyright (c) 2025 On-Line Application Research Corporation (OAR)
# Copyright (c) 2025 Bhavya Shah <bhavyashah8443@gmail.com>
#
# 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
@@ -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 ***