mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-23 08:54:31 +08:00
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:
committed by
Kinsey Moore
parent
05629d07e2
commit
6367099ec0
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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: []
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ***
|
||||
Reference in New Issue
Block a user