Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief RTEMS File Systems Block Management
0007  *
0008  * @ingroup rtems_rfs
0009  *
0010  * RTEMS File Systems Block Management.
0011  *
0012  * These functions manage the blocks used in the file system.
0013  */
0014 
0015 /*
0016  *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
0017  *
0018  * Redistribution and use in source and binary forms, with or without
0019  * modification, are permitted provided that the following conditions
0020  * are met:
0021  * 1. Redistributions of source code must retain the above copyright
0022  *    notice, this list of conditions and the following disclaimer.
0023  * 2. Redistributions in binary form must reproduce the above copyright
0024  *    notice, this list of conditions and the following disclaimer in the
0025  *    documentation and/or other materials provided with the distribution.
0026  *
0027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0028  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0030  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0031  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0032  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0033  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0034  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0035  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0037  * POSSIBILITY OF SUCH DAMAGE.
0038  */
0039 
0040 
0041 #if !defined (_RTEMS_RFS_BLOCK_H_)
0042 #define _RTEMS_RFS_BLOCK_H_
0043 
0044 #include <rtems/rfs/rtems-rfs-block-pos.h>
0045 #include <rtems/rfs/rtems-rfs-buffer.h>
0046 #include <rtems/rfs/rtems-rfs-data.h>
0047 #include <rtems/rfs/rtems-rfs-file-system.h>
0048 
0049 /**
0050  * Get a block number in the media format and return it in the host format.
0051  *
0052  * @param[in] _h is the buffer handle of the block.
0053  * @param[in] _b is the block number index.
0054  *
0055  * @retval block The block number.
0056  */
0057 #define rtems_rfs_block_get_number(_h, _b) \
0058   ((rtems_rfs_block_no) \
0059    (rtems_rfs_read_u32 (rtems_rfs_buffer_data (_h) + \
0060                         ((_b) * sizeof (rtems_rfs_block_no)))))
0061 
0062 /**
0063  * Set a block number in the media format given a number in the host format.
0064  *
0065  * @param[in] _h is the buffer handle of the block.
0066  * @param[in] _b is the block number index, ie the number of block number not the
0067  *           buffer offset.
0068  * @param[in] _n is the block number.
0069  */
0070 #define rtems_rfs_block_set_number(_h, _b, _n) \
0071   do { \
0072     rtems_rfs_write_u32 (rtems_rfs_buffer_data (_h) + \
0073                          ((_b) * sizeof (rtems_rfs_block_no)), (_n)); \
0074     rtems_rfs_buffer_mark_dirty (_h); \
0075   } while (0)
0076 
0077 /**
0078  * A block map manges the block lists that originate from an inode. The inode
0079  * contains a number of block numbers. A block map takes those block numbers
0080  * and manages them.
0081  *
0082  * The blocks cannot have all ones as a block number nor block 0. The block map
0083  * is series of block numbers in a blocks. The size of the map determines the
0084  * way the block numbers are stored. The map uses the following:
0085  *
0086  * @li @e Direct Access,
0087  * @li @e Single Indirect Access, and
0088  * @li @e Double Indirect Access.
0089  *
0090  * Direct access has the blocks numbers in the inode slots. The Single Indirect
0091  * Access has block numbers in the inode slots that pointer to a table of block
0092  * numbers that point to data blocks. The Double Indirect Access has block
0093  * numbers in the inode that point to Single Indirect block tables.
0094  *
0095  * The inode can hold a number of Direct, Single Indirect, and Double Indirect
0096  * block tables. The move from Direct to Single occurs then the block count in
0097  * the map is above the number of slots in the inode. The move from Single to
0098  * Double occurs when the map block count is greated than the block numbers per
0099  * block multipled by the slots in the inode. The move from Single to Double
0100  * occurs when the map block count is over the block numbers per block squared
0101  * multipled by the number of slots in the inode.
0102  *
0103  * The block map can managed files of the follow size verses block size with 5
0104  * inode slots:
0105  *
0106  *  @li 41,943,040 bytes for a 512 byte block size,
0107  *  @li 335,544,320 bytes for a 1024 byte block size,
0108  *  @li 2,684,354,560 bytes for a 2048 byte block size, and
0109  *  @li 21,474,836,480 bytes for a 4096 byte block size.
0110  */
0111 typedef struct rtems_rfs_block_map_s
0112 {
0113   /**
0114    * Is the map dirty ?
0115    */
0116   bool dirty;
0117 
0118   /**
0119    * The inode this map is attached to.
0120    */
0121   rtems_rfs_inode_handle* inode;
0122 
0123   /**
0124    * The size of the map.
0125    */
0126   rtems_rfs_block_size size;
0127 
0128   /**
0129    * The block map position. Used to navigate the map when seeking. The find
0130    * call is to a position in the file/directory and is a block number plus
0131    * offset. The block find only needs to locate a block and not worry about
0132    * the offset while a seek can be less than a block size yet move across a
0133    * block boundary. Therefore the position a block map has to maintain must
0134    * include the offset so seeks work.
0135    */
0136   rtems_rfs_block_pos bpos;
0137 
0138   /**
0139    * The last map block allocated. This is used as the goal when allocating a
0140    * new map block.
0141    */
0142   rtems_rfs_block_no last_map_block;
0143 
0144   /**
0145    * The last data block allocated. This is used as the goal when allocating a
0146    * new data block.
0147    */
0148   rtems_rfs_block_no last_data_block;
0149 
0150   /**
0151    * The block map.
0152    */
0153   uint32_t blocks[RTEMS_RFS_INODE_BLOCKS];
0154 
0155   /**
0156    * Singly Buffer handle.
0157    */
0158   rtems_rfs_buffer_handle singly_buffer;
0159 
0160   /**
0161    * Doubly Buffer handle.
0162    */
0163   rtems_rfs_buffer_handle doubly_buffer;
0164 
0165 } rtems_rfs_block_map;
0166 
0167 /**
0168  * Is the map dirty ?
0169  */
0170 #define rtems_rfs_block_map_is_dirty(_m) ((_m)->dirty)
0171 
0172 /**
0173  * Return the block count in the map.
0174  */
0175 #define rtems_rfs_block_map_count(_m) ((_m)->size.count)
0176 
0177 /**
0178  * Return the map's size element.
0179  */
0180 #define rtems_rfs_block_map_size(_m) (&((_m)->size))
0181 
0182 /**
0183  * Return the size offset for the map.
0184  */
0185 #define rtems_rfs_block_map_size_offset(_m) ((_m)->size.offset)
0186 
0187 /**
0188  * Are we at the last block in the map ?
0189  */
0190 #define rtems_rfs_block_map_last(_m) \
0191   rtems_rfs_block_pos_last_block (&(_m)->bpos, &(_m)->size)
0192 
0193 /**
0194  * Is the position past the end of the block ?
0195  */
0196 #define rtems_rfs_block_map_past_end(_m, _p) \
0197   rtems_rfs_block_pos_past_end (_p, &(_m)->size)
0198 
0199 /**
0200  * Return the current position in the map.
0201  */
0202 #define rtems_rfs_block_map_pos(_f, _m) \
0203   rtems_rfs_block_get_pos (_f, &(_m)->bpos)
0204 
0205 /**
0206  * Return the map's current block number.
0207  */
0208 #define rtems_rfs_block_map_block(_m) ((_m)->bpos.bno)
0209 
0210 /**
0211  * Return the map's current block offset.
0212  */
0213 #define rtems_rfs_block_map_block_offset(_m) ((_m)->bpos.boff)
0214 
0215 /**
0216  * Set the size offset for the map. The map is tagged as dirty.
0217  *
0218  * @param[in] map is a pointer to the open map to set the offset in.
0219  * @param[in] offset is the offset to set in the map's size.
0220  */
0221 static inline void
0222 rtems_rfs_block_map_set_size_offset (rtems_rfs_block_map* map,
0223                                      rtems_rfs_block_off  offset)
0224 {
0225   map->size.offset = offset;
0226   map->dirty = true;
0227 }
0228 
0229 /**
0230  * Set the map's size. The map is tagged as dirty.
0231  *
0232  * @param[in] map is a pointer to the open map to set the offset in.
0233  * @param[in] size is the size to set in the map's size.
0234  */
0235 static inline void
0236 rtems_rfs_block_map_set_size (rtems_rfs_block_map*  map,
0237                               rtems_rfs_block_size* size)
0238 {
0239   rtems_rfs_block_copy_size (&map->size, size);
0240   map->dirty = true;
0241 }
0242 /**
0243  * Open a block map. The block map data in the inode is copied into the
0244  * map. The buffer handles are opened. The block position is set to the start
0245  * so a seek of offset 0 will return the first block.
0246  *
0247  * @param[in] fs is the file system data.
0248  * @param[in] inode is a pointer to the inode the map belongs to.
0249  * @param[in] map is a pointer to the map that is opened.
0250  *
0251  * @retval 0 Successful operation.
0252  * @retval error_code An error occurred.
0253  */
0254 int rtems_rfs_block_map_open (rtems_rfs_file_system*  fs,
0255                               rtems_rfs_inode_handle* inode,
0256                               rtems_rfs_block_map*    map);
0257 
0258 /**
0259  * Close the map. The buffer handles are closed and any help buffers are
0260  * released.
0261  *
0262  * @param[in] fs is the file system data.
0263  * @param[in] map is a pointer to the map that is opened.
0264  *
0265  * @retval 0 Successful operation.
0266  * @retval error_code An error occurred.
0267  */
0268 int rtems_rfs_block_map_close (rtems_rfs_file_system* fs,
0269                                rtems_rfs_block_map*   map);
0270 
0271 /**
0272  * Find a block number in the map from the position provided.
0273  *
0274  * @param[in] fs is the file system data.
0275  * @param[in] map is a pointer to the map to search.
0276  * @param[in] bpos is a pointer to the block position to find.
0277  * @param[out] block will contain the block in when found.
0278  *
0279  * @retval 0 Successful operation.
0280  * @retval error_code An error occurred.
0281  */
0282 int rtems_rfs_block_map_find (rtems_rfs_file_system*  fs,
0283                               rtems_rfs_block_map*    map,
0284                               rtems_rfs_block_pos*    bpos,
0285                               rtems_rfs_buffer_block* block);
0286 
0287 /**
0288  * Seek around the map.
0289  *
0290  * @param[in] fs is the file system data.
0291  * @param[in] map is a pointer to the map to search.
0292  * @param[in] offset is the distance to seek. It is signed.
0293  * @param[out] block will contain the block in when found.
0294  *
0295  * @retval 0 Successful operation.
0296  * @retval ENXIO Failed to seek because it is outside the block map.
0297  * @retval error_code An error occurred.
0298  */
0299 int rtems_rfs_block_map_seek (rtems_rfs_file_system*  fs,
0300                               rtems_rfs_block_map*    map,
0301                               rtems_rfs_pos_rel       offset,
0302                               rtems_rfs_buffer_block* block);
0303 
0304 /**
0305  * Seek to the next block.
0306  *
0307  * @param[in] fs is the file system data.
0308  * @param[in] map is a pointer to the map to search.
0309  * @param[out] block will contain the block in when found.
0310  *
0311  * @retval 0 Successful operation.
0312  * @retval ENXIO Failed to seek because it is outside the block map.
0313  * @retval error_code An error occurred.
0314  */
0315 int rtems_rfs_block_map_next_block (rtems_rfs_file_system*  fs,
0316                                     rtems_rfs_block_map*    map,
0317                                     rtems_rfs_buffer_block* block);
0318 
0319 /**
0320  * Grow the block map by the specified number of blocks.
0321  *
0322  * @param[in] fs is the file system data.
0323  * @param[in] map is a pointer to the open map to grow.
0324  * @param[in] blocks is the number of blocks to grow the map by.
0325  * @param[out] new_block will contain first of the blocks allocated
0326  *                  to the map.
0327  *
0328  * @retval 0 Successful operation.
0329  * @retval error_code An error occurred.
0330  */
0331 int rtems_rfs_block_map_grow (rtems_rfs_file_system* fs,
0332                               rtems_rfs_block_map*   map,
0333                               size_t                 blocks,
0334                               rtems_rfs_block_no*    new_block);
0335 
0336 /**
0337  * Grow the block map by the specified number of blocks.
0338  *
0339  * @param[in] fs is the file system data.
0340  * @param[in] map is a pointer to the open map to shrink.
0341  * @param[in] blocks is the number of blocks to shrink the map by. If more
0342  *               than the number of blocks the map is emptied.
0343  *
0344  * @retval 0 Successful operation.
0345  * @retval error_code An error occurred.
0346  */
0347 int rtems_rfs_block_map_shrink (rtems_rfs_file_system* fs,
0348                                 rtems_rfs_block_map*   map,
0349                                 size_t                 blocks);
0350 
0351 /**
0352  * Free all blocks in the map.
0353  *
0354  * @param[in] fs is the file system data.
0355  * @param[in] map is a pointer to the open map to free all blocks from.
0356  *
0357  * @retval 0 Successful operation.
0358  * @retval error_code An error occurred.
0359  */
0360 int rtems_rfs_block_map_free_all (rtems_rfs_file_system* fs,
0361                                   rtems_rfs_block_map*   map);
0362 
0363 #endif