Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup rtems_rfs
0007  *
0008  * @brief RTEMS File Systems Group Routines
0009  *
0010  * These functions open and close a group as well as manage bit allocations
0011  * within a group.
0012  */
0013 
0014 /*
0015  *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 
0040 #ifdef HAVE_CONFIG_H
0041 #include "config.h"
0042 #endif
0043 
0044 #include <inttypes.h>
0045 #include <string.h>
0046 
0047 #include <rtems/rfs/rtems-rfs-file-system.h>
0048 #include <rtems/rfs/rtems-rfs-group.h>
0049 
0050 int
0051 rtems_rfs_group_open (rtems_rfs_file_system* fs,
0052                       rtems_rfs_buffer_block base,
0053                       size_t                 size,
0054                       size_t                 inodes,
0055                       rtems_rfs_group*       group)
0056 {
0057   int rc;
0058 
0059   if (base >= rtems_rfs_fs_blocks (fs))
0060   {
0061     if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
0062       printf ("rtems-rfs: group-open: base outside file system range: %d: %s\n",
0063               EIO, strerror (EIO));
0064     return EIO;
0065   }
0066 
0067   if ((base + size) >= rtems_rfs_fs_blocks (fs))
0068     size = rtems_rfs_fs_blocks (fs) - base;
0069 
0070   /*
0071    * Limit the inodes to the same size as the blocks. This is what the
0072    * format does and if this is not done the accounting of inodes does
0073    * not work. If we are so pushed for inodes that this makes a difference
0074    * the format configuration needs reviewing.
0075    */
0076   if (inodes > size)
0077     inodes = size;
0078 
0079   if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
0080     printf ("rtems-rfs: group-open: base=%" PRId32 ", blocks=%zd inodes=%zd\n",
0081             base, size, inodes);
0082 
0083   group->base = base;
0084   group->size = size;
0085 
0086   rc = rtems_rfs_buffer_handle_open (fs, &group->block_bitmap_buffer);
0087   if (rc > 0)
0088   {
0089     if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
0090       printf ("rtems-rfs: group-open: could not open block bitmap handle: %d: %s\n",
0091               rc, strerror (rc));
0092     return rc;
0093   }
0094 
0095   rc = rtems_rfs_bitmap_open (&group->block_bitmap, fs,
0096                               &group->block_bitmap_buffer, size,
0097                               group->base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
0098   if (rc > 0)
0099   {
0100     rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
0101     if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
0102       printf ("rtems-rfs: group-open: could not open block bitmap: %d: %s\n",
0103               rc, strerror (rc));
0104     return rc;
0105   }
0106 
0107   rc = rtems_rfs_buffer_handle_open (fs, &group->inode_bitmap_buffer);
0108   if (rc > 0)
0109   {
0110     rtems_rfs_bitmap_close (&group->block_bitmap);
0111     rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
0112     if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
0113       printf ("rtems-rfs: group-open: could not open inode bitmap handle: %d: %s\n",
0114               rc, strerror (rc));
0115     return rc;
0116   }
0117 
0118   rc = rtems_rfs_bitmap_open (&group->inode_bitmap, fs,
0119                               &group->inode_bitmap_buffer, inodes,
0120                               group->base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
0121   if (rc > 0)
0122   {
0123     rtems_rfs_buffer_handle_close (fs, &group->inode_bitmap_buffer);
0124     rtems_rfs_bitmap_close (&group->block_bitmap);
0125     rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
0126     if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
0127       printf ("rtems-rfs: group-open: could not open inode bitmap: %d: %s\n",
0128               rc, strerror (rc));
0129     return rc;
0130   }
0131 
0132   if (rtems_rfs_fs_release_bitmaps (fs))
0133   {
0134     rtems_rfs_bitmap_release_buffer (fs, &group->block_bitmap);
0135     rtems_rfs_bitmap_release_buffer (fs, &group->inode_bitmap);
0136   }
0137 
0138   return 0;
0139 }
0140 
0141 int
0142 rtems_rfs_group_close (rtems_rfs_file_system* fs, rtems_rfs_group* group)
0143 {
0144   int result = 0;
0145   int rc;
0146 
0147   if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_CLOSE))
0148     printf ("rtems-rfs: group-close: base=%" PRId32 "\n", group->base);
0149 
0150   /*
0151    * We need to close as much as possible and also return any error if one
0152    * occurs but this may result in one even more important error being lost but
0153    * we cannot OR the errors together so this is a reasonable compromise.
0154    */
0155   rc = rtems_rfs_bitmap_close (&group->inode_bitmap);
0156   if (rc > 0)
0157     result = rc;
0158   rc = rtems_rfs_buffer_handle_close (fs, &group->inode_bitmap_buffer);
0159   if (rc > 0)
0160     result = rc;
0161   rc = rtems_rfs_bitmap_close (&group->block_bitmap);
0162   if (rc > 0)
0163     result = rc;
0164   rc = rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
0165   if (rc > 0)
0166     result = rc;
0167 
0168   return result;
0169 }
0170 
0171 int
0172 rtems_rfs_group_bitmap_alloc (rtems_rfs_file_system* fs,
0173                               rtems_rfs_bitmap_bit   goal,
0174                               bool                   inode,
0175                               rtems_rfs_bitmap_bit*  result)
0176 {
0177   int                  group_start;
0178   size_t               size;
0179   rtems_rfs_bitmap_bit bit;
0180   int                  offset;
0181   bool                 updown;
0182   int                  direction;
0183 
0184   if (inode)
0185   {
0186     size = fs->group_inodes;
0187     goal -= RTEMS_RFS_ROOT_INO;
0188   }
0189   else
0190   {
0191     size = fs->group_blocks;
0192     /*
0193      * It is possible for 'goal' to be zero. Any newly created inode will have
0194      * its 'last_data_block' set to zero, which is then used as 'goal' to
0195      * allocate new blocks. When that happens, we simply set 'goal' to zero and
0196      * continue the search from there.
0197      */
0198     if (goal >= RTEMS_RFS_ROOT_INO)
0199         goal -= RTEMS_RFS_ROOT_INO;
0200   }
0201 
0202   group_start = goal / size;
0203   bit = (rtems_rfs_bitmap_bit) (goal % size);
0204   offset = 0;
0205   updown = true;
0206   direction = 1;
0207 
0208   /*
0209    * Try the goal group first and if that group fails try the groups either
0210    * side until the whole file system has be tried.
0211    */
0212   while (true)
0213   {
0214     rtems_rfs_bitmap_control* bitmap;
0215     int                       group;
0216     bool                      allocated = false;
0217     int                       rc;
0218 
0219     /*
0220      * We can start at any location and we move out from that point in each
0221      * direction. The offset grows until we find a free bit or we hit an end.
0222      */
0223     group = group_start + (direction * offset);
0224     if (offset)
0225       bit = direction > 0 ? 0 : size - 1;
0226 
0227     /*
0228      * If we are still looking up and down and if the group is out of range we
0229      * have reached one end. Stopping looking up and down and just move in the
0230      * one direction one group at a time.
0231      */
0232     if ((group < 0) || (group >= fs->group_count))
0233     {
0234       if (!updown)
0235         break;
0236       direction = direction > 0 ? -1 : 1;
0237       updown = false;
0238       continue;
0239     }
0240 
0241    if (inode)
0242       bitmap = &fs->groups[group].inode_bitmap;
0243     else
0244       bitmap = &fs->groups[group].block_bitmap;
0245 
0246     rc = rtems_rfs_bitmap_map_alloc (bitmap, bit, &allocated, &bit);
0247     if (rc > 0)
0248       return rc;
0249 
0250     if (rtems_rfs_fs_release_bitmaps (fs))
0251       rtems_rfs_bitmap_release_buffer (fs, bitmap);
0252 
0253     if (allocated)
0254     {
0255       if (inode)
0256         *result = rtems_rfs_group_inode (fs, group, bit);
0257       else
0258         *result = rtems_rfs_group_block (&fs->groups[group], bit);
0259       if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
0260         printf ("rtems-rfs: group-bitmap-alloc: %s allocated: %" PRId32 "\n",
0261                 inode ? "inode" : "block", *result);
0262       return 0;
0263     }
0264 
0265     /*
0266      * If we are still looking back and forth around the
0267      * group_start, then alternate the direction and
0268      * increment the offset on every other iteration.
0269      * Otherwise we are marching through the groups, so just
0270      * increment the offset.
0271      */
0272     if (updown)
0273     {
0274       direction = direction > 0 ? -1 : 1;
0275       if ( direction == -1 )
0276         offset++;
0277     }
0278     else
0279     {
0280        offset++;
0281     }
0282 
0283   }
0284 
0285   if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
0286     printf ("rtems-rfs: group-bitmap-alloc: no blocks available\n");
0287 
0288   return ENOSPC;
0289 }
0290 
0291 int
0292 rtems_rfs_group_bitmap_free (rtems_rfs_file_system* fs,
0293                              bool                   inode,
0294                              rtems_rfs_bitmap_bit   no)
0295 {
0296   rtems_rfs_bitmap_control* bitmap;
0297   unsigned int              group;
0298   rtems_rfs_bitmap_bit      bit;
0299   size_t                    size;
0300   int                       rc;
0301 
0302   if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
0303     printf ("rtems-rfs: group-bitmap-free: %s free: %" PRId32 "\n",
0304             inode ? "inode" : "block", no);
0305 
0306   if (inode)
0307   {
0308     no -= RTEMS_RFS_ROOT_INO;
0309     size = fs->group_inodes;
0310   }
0311   else
0312   {
0313     no -= RTEMS_RFS_SUPERBLOCK_SIZE;
0314     size = fs->group_blocks;
0315   }
0316 
0317   group = no / size;
0318   bit = (rtems_rfs_bitmap_bit) (no % size);
0319 
0320   if (inode)
0321     bitmap = &fs->groups[group].inode_bitmap;
0322   else
0323     bitmap = &fs->groups[group].block_bitmap;
0324 
0325   rc = rtems_rfs_bitmap_map_clear (bitmap, bit);
0326 
0327   rtems_rfs_bitmap_release_buffer (fs, bitmap);
0328 
0329   return rc;
0330 }
0331 
0332 int
0333 rtems_rfs_group_bitmap_test (rtems_rfs_file_system* fs,
0334                              bool                   inode,
0335                              rtems_rfs_bitmap_bit   no,
0336                              bool*                  state)
0337 {
0338   rtems_rfs_bitmap_control* bitmap;
0339   unsigned int              group;
0340   rtems_rfs_bitmap_bit      bit;
0341   size_t                    size;
0342   int                       rc;
0343 
0344   if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
0345     printf ("rtems-rfs: group-bitmap-test: %s test: %" PRId32 "\n",
0346             inode ? "inode" : "block", no);
0347 
0348   if (inode)
0349   {
0350     if ((no < RTEMS_RFS_ROOT_INO) || (no > rtems_rfs_fs_inodes (fs)))
0351         return EINVAL;
0352     no -= RTEMS_RFS_ROOT_INO;
0353     size = fs->group_inodes;
0354   }
0355   else
0356   {
0357     if ((no < RTEMS_RFS_ROOT_INO) || (no >= rtems_rfs_fs_blocks (fs)))
0358         return EINVAL;
0359     no -= RTEMS_RFS_ROOT_INO;
0360     size = fs->group_blocks;
0361   }
0362 
0363   group = no / size;
0364   bit = (rtems_rfs_bitmap_bit) (no % size);
0365 
0366   if (inode)
0367     bitmap = &fs->groups[group].inode_bitmap;
0368   else
0369     bitmap = &fs->groups[group].block_bitmap;
0370 
0371   rc = rtems_rfs_bitmap_map_test (bitmap, bit, state);
0372 
0373   rtems_rfs_bitmap_release_buffer (fs, bitmap);
0374 
0375   return rc;
0376 }
0377 
0378 int
0379 rtems_rfs_group_usage (rtems_rfs_file_system* fs,
0380                        size_t*                blocks,
0381                        size_t*                inodes)
0382 {
0383   int g;
0384 
0385   *blocks = 0;
0386   *inodes = 0;
0387 
0388   for (g = 0; g < fs->group_count; g++)
0389   {
0390     rtems_rfs_group* group = &fs->groups[g];
0391     *blocks +=
0392       rtems_rfs_bitmap_map_size(&group->block_bitmap) -
0393       rtems_rfs_bitmap_map_free (&group->block_bitmap);
0394     *inodes +=
0395       rtems_rfs_bitmap_map_size (&group->inode_bitmap) -
0396       rtems_rfs_bitmap_map_free (&group->inode_bitmap);
0397   }
0398 
0399   if (*blocks > rtems_rfs_fs_blocks (fs))
0400     *blocks = rtems_rfs_fs_blocks (fs);
0401   if (*inodes > rtems_rfs_fs_inodes (fs))
0402     *inodes = rtems_rfs_fs_inodes (fs);
0403 
0404   return 0;
0405 }
0406