Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:34

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2012 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <fcntl.h>
0033 #include <rtems/blkdev.h>
0034 #include "rtems/sparse-disk.h"
0035 
0036 #include "tmacros.h"
0037 
0038 const char rtems_test_name[] = "SPARSEDISK 1";
0039 
0040 /* Number of bytes for test pattern within a sparse disk container */
0041 #define STATIC_PATTERN_SIZE 4096
0042 
0043 /* Block size used for the sparse disk in a sparse disk container */
0044 #define STATIC_BLOCK_SIZE 4096
0045 
0046 /* Number of block allocated for the sparse disk in a sparse disk container */
0047 #define STATIC_ALLOCATED_BLOCK_COUNT 1
0048 
0049 /* Blocks simulated by the sparse disk in a disk container */
0050 #define STATIC_SIMULATED_BLOCK_COUNT 4096
0051 
0052 /*
0053  * Container which cotains a sparse disk + memory for key table and data as would get
0054  * allocated by rtems_sparse_disk_create() + memory for a memory test pattern
0055  * By using this container white box testing of a sparse disk becomes possible
0056  */
0057 typedef struct {
0058   rtems_sparse_disk sparse_disk;
0059   rtems_sparse_disk_key keytable[STATIC_ALLOCATED_BLOCK_COUNT];
0060   uint8_t data[STATIC_BLOCK_SIZE * STATIC_ALLOCATED_BLOCK_COUNT];
0061   uint8_t pattern[STATIC_PATTERN_SIZE];
0062 } sparse_disk_container;
0063 
0064 /*
0065  * Black box test the disk parameters of a sparse disk
0066  */
0067 static void test_disk_params(
0068   const int               file_descriptor,
0069   const uint32_t          block_size,
0070   const uint32_t          media_block_size,
0071   const rtems_blkdev_bnum block_number )
0072 {
0073   int                rv;
0074   uint32_t           value       = 0;
0075   rtems_disk_device *fd_dd       = NULL;
0076   rtems_blkdev_bnum  block_count = 0;
0077 
0078 
0079   rv = rtems_disk_fd_get_media_block_size( file_descriptor, &value );
0080   rtems_test_assert( 0 == rv );
0081   rtems_test_assert( media_block_size == value );
0082 
0083   value = 0;
0084   rv    = rtems_disk_fd_get_block_size( file_descriptor, &value );
0085   rtems_test_assert( 0 == rv );
0086   rtems_test_assert( block_size == value );
0087 
0088   block_count = 0;
0089   rv          = rtems_disk_fd_get_block_count( file_descriptor, &block_count );
0090   rtems_test_assert( 0 == rv );
0091   rtems_test_assert( block_number == block_count );
0092 
0093   rv = rtems_disk_fd_get_disk_device( file_descriptor, &fd_dd );
0094   rtems_test_assert( 0 == rv );
0095   rtems_test_assert( NULL != fd_dd );
0096 }
0097 
0098 /*
0099  * Verify that writing to a sparse disk delivers expected results
0100  */
0101 static void test_writing(
0102   const int               file_descriptor,
0103   const uint32_t          block_size,
0104   const rtems_blkdev_bnum blocks_allocated )
0105 {
0106   int               rv;
0107   rtems_blkdev_bnum block_count = 0;
0108   unsigned int      byte_count;
0109   off_t             file_pos;
0110   uint8_t           buff[block_size];
0111 
0112 
0113   /* Write a pattern to all allocated blocks */
0114   for ( block_count = 0; block_count < blocks_allocated; block_count++ ) {
0115     file_pos = (off_t) block_count * block_size;
0116     rv       = lseek( file_descriptor, file_pos, SEEK_SET );
0117     rtems_test_assert( file_pos == rv );
0118 
0119     rv = read( file_descriptor, buff, block_size );
0120     rtems_test_assert( block_size == rv );
0121 
0122     for ( byte_count = 0;
0123           byte_count < ( block_size / sizeof( byte_count ) );
0124           byte_count++ ) {
0125       memcpy( buff + ( byte_count * sizeof( byte_count ) ), &byte_count,
0126               sizeof( byte_count ) );
0127     }
0128 
0129     rv = lseek( file_descriptor, file_pos, SEEK_SET );
0130     rtems_test_assert( file_pos == rv );
0131 
0132     rv = write( file_descriptor, buff, block_size );
0133     rtems_test_assert( block_size == rv );
0134   }
0135 }
0136 
0137 /*
0138  * Verify that black box reading for a sparse disk delivers expected results
0139  */
0140 static void test_reading(
0141   const int               file_descriptor,
0142   const uint32_t          block_size,
0143   const rtems_blkdev_bnum blocks_allocated,
0144   const uint8_t           fill_pattern )
0145 {
0146   int               rv;
0147   rtems_blkdev_bnum block_count = 0;
0148   unsigned int      byte_count;
0149   off_t             file_pos;
0150   uint8_t           buff[block_size];
0151   uint32_t          value = 0;
0152 
0153 
0154   rv = fsync( file_descriptor );
0155   rtems_test_assert( 0 == rv );
0156 
0157   /* Read back the patterns */
0158   for ( block_count = 0; block_count < blocks_allocated; block_count++ ) {
0159     file_pos = (off_t) block_count * block_size;
0160     value    = lseek( file_descriptor, file_pos, SEEK_SET );
0161     rtems_test_assert( file_pos == value );
0162 
0163     rv = read( file_descriptor, &buff, block_size );
0164     rtems_test_assert( block_size <= rv );
0165 
0166     for ( byte_count = 0;
0167           byte_count < ( block_size / sizeof( byte_count ) );
0168           byte_count++ ) {
0169       rv = memcmp( buff + ( byte_count * sizeof( byte_count ) ),
0170                    &byte_count,
0171                    sizeof( byte_count ) );
0172       rtems_test_assert( 0 == rv );
0173     }
0174   }
0175 
0176   /* Try to read from unallocated block */
0177   file_pos = (off_t) block_count * block_size;
0178   rv       = lseek( file_descriptor, file_pos, SEEK_SET );
0179   rtems_test_assert( file_pos == rv );
0180 
0181   rv = read( file_descriptor, buff, block_size );
0182   rtems_test_assert( block_size == rv );
0183 
0184   for ( byte_count = 0; byte_count < block_size; ++byte_count )
0185     rtems_test_assert( fill_pattern == buff[byte_count] );
0186 }
0187 
0188 /*
0189  * Do black box io testing on a sparse disk
0190  */
0191 static void test_device_io( const char *device_name,
0192   const uint32_t                        block_size,
0193   const uint32_t                        media_block_size,
0194   const rtems_blkdev_bnum               block_number,
0195   const rtems_blkdev_bnum               blocks_allocated,
0196   const uint8_t                         fill_pattern )
0197 {
0198   int rv;
0199   int file_descriptor;
0200 
0201 
0202   file_descriptor = open( device_name, O_RDWR );
0203   rtems_test_assert( 0 <= file_descriptor );
0204 
0205   test_disk_params(
0206     file_descriptor,
0207     block_size,
0208     media_block_size,
0209     block_number
0210     );
0211 
0212   test_writing(
0213     file_descriptor,
0214     block_size,
0215     blocks_allocated
0216     );
0217 
0218   test_reading(
0219     file_descriptor,
0220     block_size,
0221     blocks_allocated,
0222     fill_pattern
0223     );
0224 
0225   rv = close( file_descriptor );
0226   rtems_test_assert( 0 == rv );
0227 }
0228 
0229 /*
0230  * In white box testing verify the key table of the sparse disk is correct
0231  */
0232 static void test_static_key_table(
0233   const sparse_disk_container *disk_container,
0234   const rtems_blkdev_bnum      blocks_allocated,
0235   const uint32_t               block_size )
0236 {
0237   unsigned int i;
0238 
0239 
0240   for ( i = 0; i < blocks_allocated; ++i ) {
0241     rtems_test_assert( i == disk_container->keytable[i].block );
0242     rtems_test_assert(
0243       &disk_container->data[i * block_size]
0244       == disk_container->keytable[i].data );
0245   }
0246 }
0247 
0248 /*
0249  * Verify the test pattern used in white box testing is as expected
0250  */
0251 static void test_static_pattern(
0252   const unsigned int pattern_size,
0253   const uint8_t     *pattern )
0254 {
0255   unsigned int i;
0256 
0257 
0258   for ( i = 0; i < pattern_size; ++i )
0259     rtems_test_assert( ( (uint8_t) ( pattern_size - 1 - i ) ) == pattern[i] );
0260 }
0261 
0262 /*
0263  * Read write testing with a statically allocated disk. Thus white box testing can be done
0264  */
0265 static void test_with_whitebox( const char *device_name )
0266 {
0267   rtems_status_code     sc;
0268   int                   rv;
0269   unsigned int          i;
0270   sparse_disk_container disk_container;
0271   int                   file_descriptor;
0272   rtems_blkdev_bnum     block_count  = 0;
0273   unsigned int          byte_count;
0274   uint8_t               fill_pattern = 0;
0275 
0276 
0277   memset( disk_container.data, 0, sizeof( disk_container.data ) );
0278   memset( disk_container.keytable, 0, sizeof( disk_container.keytable ) );
0279 
0280   for ( i = 0; i < STATIC_PATTERN_SIZE; ++i )
0281     disk_container.pattern[i] = (uint8_t) ( STATIC_PATTERN_SIZE - 1 - i );
0282 
0283   sc = rtems_sparse_disk_register(
0284     "/dev/sda1",
0285     &disk_container.sparse_disk,
0286     STATIC_BLOCK_SIZE,
0287     STATIC_ALLOCATED_BLOCK_COUNT,
0288     STATIC_SIMULATED_BLOCK_COUNT,
0289     fill_pattern,
0290     NULL
0291     );
0292   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0293 
0294   test_static_key_table(
0295     &disk_container,
0296     STATIC_ALLOCATED_BLOCK_COUNT,
0297     STATIC_BLOCK_SIZE
0298     );
0299 
0300   for ( i = 0; i < ( STATIC_BLOCK_SIZE * STATIC_ALLOCATED_BLOCK_COUNT ); ++i )
0301     rtems_test_assert( 0 == disk_container.data[i] );
0302 
0303   test_static_pattern(
0304     STATIC_PATTERN_SIZE,
0305     &disk_container.pattern[0]
0306     );
0307 
0308   file_descriptor = open( device_name, O_RDWR );
0309   rtems_test_assert( 0 <= file_descriptor );
0310 
0311   test_disk_params(
0312     file_descriptor,
0313     STATIC_BLOCK_SIZE,
0314     STATIC_BLOCK_SIZE,
0315     STATIC_SIMULATED_BLOCK_COUNT
0316     );
0317 
0318   test_writing(
0319     file_descriptor,
0320     STATIC_BLOCK_SIZE,
0321     STATIC_ALLOCATED_BLOCK_COUNT
0322     );
0323 
0324   test_reading(
0325     file_descriptor,
0326     STATIC_BLOCK_SIZE,
0327     STATIC_ALLOCATED_BLOCK_COUNT,
0328     fill_pattern
0329     );
0330 
0331   rv = close( file_descriptor );
0332   rtems_test_assert( 0 == rv );
0333 
0334   test_static_key_table(
0335     &disk_container,
0336     STATIC_ALLOCATED_BLOCK_COUNT,
0337     STATIC_BLOCK_SIZE
0338     );
0339 
0340   for ( block_count = 0;
0341         block_count < STATIC_ALLOCATED_BLOCK_COUNT;
0342         block_count++ ) {
0343     for ( byte_count = 0;
0344           byte_count < ( STATIC_BLOCK_SIZE / sizeof( byte_count ) );
0345           byte_count++ ) {
0346       rv = memcmp( &disk_container.data[byte_count * sizeof( byte_count )],
0347                    &byte_count,
0348                    sizeof( byte_count ) );
0349       rtems_test_assert( 0 == rv );
0350     }
0351   }
0352 
0353   test_static_pattern(
0354     STATIC_PATTERN_SIZE,
0355     &disk_container.pattern[0]
0356     );
0357 }
0358 
0359 /*
0360  * The test sequence
0361  */
0362 static
0363 void test( void )
0364 {
0365   rtems_status_code sc;
0366   int               rv;
0367   char              device_name[] = "/dev/sda1";
0368   uint32_t          block_size;
0369   rtems_blkdev_bnum block_number;
0370   rtems_blkdev_bnum blocks_allocated;
0371   int               file_descriptor;
0372   uint8_t           fill_pattern = 0;
0373 
0374   block_size       = 512;
0375   block_number     = 4 * 2 * 1024;
0376   blocks_allocated = 8;
0377   sc               = rtems_sparse_disk_create_and_register(
0378     "/dev/sda1",
0379     block_size,
0380     blocks_allocated,
0381     block_number,
0382     fill_pattern
0383     );
0384   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0385 
0386   /* Test reading and writing with sector size 512 and 8 such sectors
0387    * allocated. Block size will default to 512 */
0388   test_device_io(
0389     device_name,
0390     block_size,
0391     block_size,
0392     block_number,
0393     blocks_allocated,
0394     fill_pattern
0395     );
0396 
0397   file_descriptor = open( device_name, O_RDWR );
0398   rtems_test_assert( 0 <= file_descriptor );
0399 
0400   rv = rtems_disk_fd_set_block_size( file_descriptor,
0401                                      blocks_allocated * block_size );
0402   rtems_test_assert( 0 == rv );
0403 
0404   rv = close( file_descriptor );
0405   rtems_test_assert( 0 == rv );
0406 
0407   /* Block size was increased to 4k. Thus all to allocated disk space
0408    * corresponds to one block. Repeat the read write tests */
0409   test_device_io(
0410     device_name,
0411     block_size * blocks_allocated,
0412     block_size,
0413     block_number,
0414     1,
0415     fill_pattern
0416     );
0417 
0418   rv = unlink( device_name );
0419   rtems_test_assert( 0 == rv );
0420 
0421   /* Do testing with a statically allocated disk. This permits white box
0422    * testing */
0423   test_with_whitebox( device_name );
0424 }
0425 
0426 static void Init( rtems_task_argument arg )
0427 {
0428   (void) arg;
0429   TEST_BEGIN();
0430 
0431   test();
0432 
0433   TEST_END();
0434 
0435   rtems_test_exit( 0 );
0436 }
0437 
0438 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0439 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0440 #define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
0441 
0442 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
0443 
0444 #define CONFIGURE_MAXIMUM_TASKS 1
0445 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0446 
0447 #define CONFIGURE_INIT_TASK_STACK_SIZE ( 16 * 1024 )
0448 
0449 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0450 
0451 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0452 
0453 #define CONFIGURE_INIT
0454 
0455 #include <rtems/confdefs.h>