source: rtems/cpukit/libfs/src/rfs/rtems-rfs-block.c @ 66b8047

4.115
Last change on this file since 66b8047 was 66b8047, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/06/11 at 12:44:24

Remove stray whitespaces.

  • Property mode set to 100644
File size: 24.3 KB
Line 
1/*
2 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS File Systems Block Routines.
16 *
17 * These functions manage blocks in the RFS file system. A block is an area of
18 * the media and its size is set for a each specific media. The block size is
19 * set when the file system is set up and needs to be matched for it to be read
20 * correctly.
21 *
22 * Blocks are managed as groups. A block group or "group" is part of the total
23 * number of blocks being managed by the file system and exist to allow
24 * resources to localised. A file in a directory will be allocated blocks in
25 * the same group as the directory, and the blocks for the file will also be
26 * allocated in the same group.
27 *
28 * A group consist of a block bitmap, inodes and data blocks. The first block
29 * of the file system will hold the superblock. The block bitmap is a
30 * collection of blocks that hold a map of bits, one bit per block for each
31 * block in the group. When a file system is mounted the block bitmaps are read
32 * and a summary bit map is made. The summary bitmap has a single bit for 32
33 * bits in the bitmap and is set when all 32 bits it maps to are set. This
34 * speeds up the search for a free block by a factor of 32.
35 */
36
37#if HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include <inttypes.h>
42
43#include <rtems/rfs/rtems-rfs-block.h>
44#include <rtems/rfs/rtems-rfs-data.h>
45#include <rtems/rfs/rtems-rfs-group.h>
46#include <rtems/rfs/rtems-rfs-inode.h>
47
48void
49rtems_rfs_block_get_bpos (rtems_rfs_file_system* fs,
50                          rtems_rfs_pos          pos,
51                          rtems_rfs_block_pos*   bpos)
52{
53  bpos->bno  = pos / rtems_rfs_fs_block_size (fs);
54  bpos->boff = pos % rtems_rfs_fs_block_size (fs);
55}
56
57rtems_rfs_pos
58rtems_rfs_block_get_pos (rtems_rfs_file_system* fs,
59                         rtems_rfs_block_pos*   bpos)
60{
61  return (bpos->bno * rtems_rfs_fs_block_size (fs)) + bpos->boff;
62}
63
64void
65rtems_rfs_block_get_block_size (rtems_rfs_file_system* fs,
66                                rtems_rfs_pos          pos,
67                                rtems_rfs_block_size*  size)
68{
69  if (pos == 0)
70    rtems_rfs_block_set_size_zero (size);
71  else
72  {
73    size->count  = pos / rtems_rfs_fs_block_size (fs) + 1;
74    size->offset = pos % rtems_rfs_fs_block_size (fs);
75  }
76}
77
78rtems_rfs_pos
79rtems_rfs_block_get_size (rtems_rfs_file_system* fs,
80                          rtems_rfs_block_size*  size)
81{
82  uint32_t offset;
83  uint64_t block_size;
84  if (size->count == 0)
85    return 0;
86  if (size->offset == 0)
87    offset = rtems_rfs_fs_block_size (fs);
88  else
89    offset = size->offset;
90  block_size = rtems_rfs_fs_block_size (fs);
91  return (((uint64_t) (size->count - 1)) * block_size) + offset;
92}
93
94int
95rtems_rfs_block_map_open (rtems_rfs_file_system*  fs,
96                          rtems_rfs_inode_handle* inode,
97                          rtems_rfs_block_map*    map)
98{
99  int b;
100  int rc;
101
102  /*
103   * Set the count to 0 so at least find fails, then open the handle and make
104   * sure the inode has been loaded into memory. If we did not load the inode
105   * do not unload it. The caller may assume it is still loaded when we return.
106   */
107
108  map->dirty = false;
109  map->inode = NULL;
110  rtems_rfs_block_set_size_zero (&map->size);
111  rtems_rfs_block_set_bpos_zero (&map->bpos);
112
113  rc = rtems_rfs_buffer_handle_open (fs, &map->singly_buffer);
114  if (rc > 0)
115    return rc;
116  rc = rtems_rfs_buffer_handle_open (fs, &map->doubly_buffer);
117  if (rc > 0)
118    return rc;
119
120  rc = rtems_rfs_inode_load (fs, inode);
121  if (rc > 0)
122  {
123    rtems_rfs_buffer_handle_close (fs, &map->singly_buffer);
124    rtems_rfs_buffer_handle_close (fs, &map->doubly_buffer);
125    return rc;
126  }
127
128  /*
129   * Extract the block and block count data from the inode into the targets
130   * byte order.
131   */
132  map->inode = inode;
133  for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
134    map->blocks[b] = rtems_rfs_inode_get_block (inode, b);
135  map->size.count = rtems_rfs_inode_get_block_count (inode);
136  map->size.offset = rtems_rfs_inode_get_block_offset (inode);
137  map->last_map_block = rtems_rfs_inode_get_last_map_block (inode);
138  map->last_data_block = rtems_rfs_inode_get_last_data_block (inode);
139
140  rc = rtems_rfs_inode_unload (fs, inode, false);
141
142  return rc;
143}
144
145int
146rtems_rfs_block_map_close (rtems_rfs_file_system* fs,
147                           rtems_rfs_block_map*   map)
148{
149  int rc = 0;
150  int brc;
151
152  if (map->dirty && map->inode)
153  {
154    brc = rtems_rfs_inode_load (fs, map->inode);
155    if (brc > 0)
156      rc = brc;
157
158    if (rc == 0)
159    {
160      int b;
161
162      for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
163        rtems_rfs_inode_set_block (map->inode, b, map->blocks[b]);
164      rtems_rfs_inode_set_block_count (map->inode, map->size.count);
165      rtems_rfs_inode_set_block_offset (map->inode, map->size.offset);
166      rtems_rfs_inode_set_last_map_block (map->inode, map->last_map_block);
167      rtems_rfs_inode_set_last_data_block (map->inode, map->last_data_block);
168
169      brc = rtems_rfs_inode_unload (fs, map->inode, true);
170      if (brc > 0)
171        rc = brc;
172
173      map->dirty = false;
174    }
175  }
176
177  map->inode = NULL;
178
179  brc = rtems_rfs_buffer_handle_close (fs, &map->singly_buffer);
180  if ((brc > 0) && (rc == 0))
181    rc = brc;
182  brc = rtems_rfs_buffer_handle_close (fs, &map->doubly_buffer);
183  if ((brc > 0) && (rc == 0))
184    rc = brc;
185  return rc;
186}
187
188/**
189 * Find a block indirectly held in a table of block numbers.
190 *
191 * @param fs The file system.
192 * @param buffer The handle to access the block data by.
193 * @param block The block number of the table of block numbers.
194 * @param offset The offset in the table of the block number to return. This is
195 *               a block number offset not a byte offset into the table.
196 * @param result Pointer to the result of the search.
197 * @return int The error number (errno). No error if 0.
198 */
199static int
200rtems_rfs_block_find_indirect (rtems_rfs_file_system*   fs,
201                               rtems_rfs_buffer_handle* buffer,
202                               rtems_rfs_block_no       block,
203                               int                      offset,
204                               rtems_rfs_block_no*      result)
205{
206   int rc;
207
208  /*
209   * If the handle has a buffer and this request is a different block the current
210   * buffer is released.
211   */
212  rc = rtems_rfs_buffer_handle_request (fs, buffer, block, true);
213  if (rc > 0)
214    return rc;
215
216  *result = rtems_rfs_block_get_number (buffer, offset);
217  if ((*result + 1) == 0)
218    *result = 0;
219
220  if (*result >= rtems_rfs_fs_blocks (fs))
221  {
222    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BLOCK_FIND))
223      printf ("rtems-rfs: block-find: invalid block in table:"
224              " block=%" PRId32 ", indirect=%" PRId32 "/%d\n", *result, block, offset);
225    *result = 0;
226    rc = EIO;
227  }
228
229  return 0;
230}
231
232int
233rtems_rfs_block_map_find (rtems_rfs_file_system* fs,
234                          rtems_rfs_block_map*   map,
235                          rtems_rfs_block_pos*   bpos,
236                          rtems_rfs_block_no*    block)
237{
238  int rc = 0;
239
240  *block = 0;
241
242  /*
243   * Range checking here makes the remaining logic simpler.
244   */
245  if (rtems_rfs_block_pos_block_past_end (bpos, &map->size))
246    return ENXIO;
247
248  /*
249   * If the block position is the same and we have found the block just return it.
250   */
251  if ((bpos->bno == map->bpos.bno) && (map->bpos.block != 0))
252  {
253    *block = map->bpos.block;
254  }
255  else
256  {
257    /*
258     * Determine the type of access we need to perform. If the number of blocks
259     * is less than or equal to the number of slots in the inode the blocks are
260     * directly accessed.
261     */
262    if (map->size.count <= RTEMS_RFS_INODE_BLOCKS)
263    {
264      *block = map->blocks[bpos->bno];
265    }
266    else
267    {
268      /*
269       * The map is either singly or doubly indirect.
270       */
271      rtems_rfs_block_no direct;
272      rtems_rfs_block_no singly;
273
274      direct = bpos->bno % fs->blocks_per_block;
275      singly = bpos->bno / fs->blocks_per_block;
276
277      if (map->size.count <= fs->block_map_singly_blocks)
278      {
279        /*
280         * This is a single indirect table of blocks anchored off a slot in the
281         * inode.
282         */
283        rc = rtems_rfs_block_find_indirect (fs,
284                                            &map->singly_buffer,
285                                            map->blocks[singly],
286                                            direct, block);
287      }
288      else
289      {
290        /*
291         * The map is doubly indirect.
292         */
293        rtems_rfs_block_no doubly;
294
295        doubly  = singly / fs->blocks_per_block;
296        singly %= fs->blocks_per_block;
297
298        if (map->size.count < fs->block_map_doubly_blocks)
299        {
300          rc = rtems_rfs_block_find_indirect (fs,
301                                              &map->doubly_buffer,
302                                              map->blocks[doubly],
303                                              singly, &singly);
304          if (rc == 0)
305          {
306            rc = rtems_rfs_block_find_indirect (fs,
307                                                &map->singly_buffer,
308                                                singly, direct, block);
309          }
310        }
311        else
312        {
313          /*
314           * This should never happen. Here so Joel can remove once his coverage
315           * testing gets to the file systems.
316           */
317          rc = ENXIO;
318        }
319      }
320    }
321  }
322
323  if (rc == 0)
324  {
325    rtems_rfs_block_copy_bpos (&map->bpos, bpos);
326    map->bpos.block = *block;
327  }
328
329  return rc;
330}
331
332int
333rtems_rfs_block_map_seek (rtems_rfs_file_system* fs,
334                          rtems_rfs_block_map*   map,
335                          rtems_rfs_pos_rel      offset,
336                          rtems_rfs_block_no*    block)
337{
338  rtems_rfs_block_pos bpos;
339  rtems_rfs_block_copy_bpos (&bpos, &map->bpos);
340  rtems_rfs_block_add_pos (fs, offset, &bpos);
341  return rtems_rfs_block_map_find (fs, map, &bpos, block);
342}
343
344int
345rtems_rfs_block_map_next_block (rtems_rfs_file_system* fs,
346                                rtems_rfs_block_map*   map,
347                                rtems_rfs_block_no*    block)
348{
349  rtems_rfs_block_pos bpos;
350  bpos.bno = map->bpos.bno + 1;
351  bpos.boff = 0;
352  bpos.block = 0;
353  return rtems_rfs_block_map_find (fs, map, &bpos, block);
354}
355
356/**
357 * Allocate an indirect block to a map.
358 *
359 * @param fs The file system data.
360 * @param map The map the allocation is for.
361 * @param buffer The buffer the indirect block is accessed by.
362 * @param block The block number of the indirect block allocated.
363 * @param upping True is upping the map to the next indirect level.
364 * @return int The error number (errno). No error if 0.
365 */
366static int
367rtems_rfs_block_map_indirect_alloc (rtems_rfs_file_system*   fs,
368                                    rtems_rfs_block_map*     map,
369                                    rtems_rfs_buffer_handle* buffer,
370                                    rtems_rfs_block_no*      block,
371                                    bool                     upping)
372{
373  rtems_rfs_bitmap_bit new_block;
374  int                  rc;
375  /*
376   * Save the new block locally because upping can have *block pointing to the
377   * slots which are cleared when upping.
378   */
379  rc = rtems_rfs_group_bitmap_alloc (fs, map->last_map_block, false, &new_block);
380  if (rc > 0)
381    return rc;
382  rc = rtems_rfs_buffer_handle_request (fs, buffer, new_block, false);
383  if (rc > 0)
384  {
385    rtems_rfs_group_bitmap_free (fs, false, new_block);
386    return rc;
387  }
388  memset (rtems_rfs_buffer_data (buffer), 0xff, rtems_rfs_fs_block_size (fs));
389  if (upping)
390  {
391    int b;
392    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BLOCK_MAP_GROW))
393      printf ("rtems-rfs: block-map-grow: upping: block-count=%" PRId32 "\n",
394              map->size.count);
395    for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
396      rtems_rfs_block_set_number (buffer, b, map->blocks[b]);
397    memset (map->blocks, 0, sizeof (map->blocks));
398  }
399  rtems_rfs_buffer_mark_dirty (buffer);
400  *block = new_block;
401  map->last_map_block = new_block;
402  return 0;
403}
404
405int
406rtems_rfs_block_map_grow (rtems_rfs_file_system* fs,
407                          rtems_rfs_block_map*   map,
408                          size_t                 blocks,
409                          rtems_rfs_block_no*    new_block)
410{
411  int b;
412
413  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BLOCK_MAP_GROW))
414    printf ("rtems-rfs: block-map-grow: entry: blocks=%zd count=%" PRIu32 "\n",
415            blocks, map->size.count);
416
417  if ((map->size.count + blocks) >= rtems_rfs_fs_max_block_map_blocks (fs))
418    return EFBIG;
419
420  /*
421   * Allocate a block at a time. The buffer handles hold the blocks so adding
422   * this way does not thrash the cache with lots of requests.
423   */
424  for (b = 0; b < blocks; b++)
425  {
426    rtems_rfs_bitmap_bit block;
427    int                  rc;
428
429    /*
430     * Allocate the block. If an indirect block is needed and cannot be
431     * allocated free this block.
432     */
433
434    rc = rtems_rfs_group_bitmap_alloc (fs, map->last_data_block,
435                                       false, &block);
436    if (rc > 0)
437      return rc;
438
439    if (map->size.count < RTEMS_RFS_INODE_BLOCKS)
440      map->blocks[map->size.count] = block;
441    else
442    {
443      /*
444       * Single indirect access is occuring. It could still be doubly indirect.
445       */
446      rtems_rfs_block_no direct;
447      rtems_rfs_block_no singly;
448
449      direct = map->size.count % fs->blocks_per_block;
450      singly = map->size.count / fs->blocks_per_block;
451
452      if (map->size.count < fs->block_map_singly_blocks)
453      {
454        /*
455         * Singly indirect tables are being used. Allocate a new block for a
456         * mapping table if direct is 0 or we are moving up (upping). If upping
457         * move the direct blocks into the table and if not this is the first
458         * entry of a new block.
459         */
460        if ((direct == 0) ||
461            ((singly == 0) && (direct == RTEMS_RFS_INODE_BLOCKS)))
462        {
463          /*
464           * Upping is when we move from direct to singly indirect.
465           */
466          bool upping;
467          upping = map->size.count == RTEMS_RFS_INODE_BLOCKS;
468          rc = rtems_rfs_block_map_indirect_alloc (fs, map,
469                                                   &map->singly_buffer,
470                                                   &map->blocks[singly],
471                                                   upping);
472        }
473        else
474        {
475          rc = rtems_rfs_buffer_handle_request (fs,  &map->singly_buffer,
476                                                map->blocks[singly], true);
477        }
478
479        if (rc > 0)
480        {
481          rtems_rfs_group_bitmap_free (fs, false, block);
482          return rc;
483        }
484      }
485      else
486      {
487        /*
488         * Doubly indirect tables are being used.
489         */
490        rtems_rfs_block_no doubly;
491        rtems_rfs_block_no singly_block;
492
493        doubly  = singly / fs->blocks_per_block;
494        singly %= fs->blocks_per_block;
495
496        /*
497         * Allocate a new block for a singly indirect table if direct is 0 as
498         * it is the first entry of a new block. We may also need to allocate a
499         * doubly indirect block as well. Both always occur when direct is 0
500         * and the doubly indirect block when singly is 0.
501         */
502        if (direct == 0)
503        {
504          rc = rtems_rfs_block_map_indirect_alloc (fs, map,
505                                                   &map->singly_buffer,
506                                                   &singly_block,
507                                                   false);
508          if (rc > 0)
509          {
510            rtems_rfs_group_bitmap_free (fs, false, block);
511            return rc;
512          }
513
514          /*
515           * Allocate a new block for a doubly indirect table if singly is 0 as
516           * it is the first entry of a new singly indirect block.
517           */
518          if ((singly == 0) ||
519              ((doubly == 0) && (singly == RTEMS_RFS_INODE_BLOCKS)))
520          {
521            bool upping;
522            upping = map->size.count == fs->block_map_singly_blocks;
523            rc = rtems_rfs_block_map_indirect_alloc (fs, map,
524                                                     &map->doubly_buffer,
525                                                     &map->blocks[doubly],
526                                                     upping);
527            if (rc > 0)
528            {
529              rtems_rfs_group_bitmap_free (fs, false, singly_block);
530              rtems_rfs_group_bitmap_free (fs, false, block);
531              return rc;
532            }
533          }
534          else
535          {
536            rc = rtems_rfs_buffer_handle_request (fs, &map->doubly_buffer,
537                                                  map->blocks[doubly], true);
538            if (rc > 0)
539            {
540              rtems_rfs_group_bitmap_free (fs, false, singly_block);
541              rtems_rfs_group_bitmap_free (fs, false, block);
542              return rc;
543            }
544          }
545
546          rtems_rfs_block_set_number (&map->doubly_buffer,
547                                      singly,
548                                      singly_block);
549        }
550        else
551        {
552          rc = rtems_rfs_buffer_handle_request (fs,
553                                                &map->doubly_buffer,
554                                                map->blocks[doubly],
555                                                true);
556          if (rc > 0)
557          {
558            rtems_rfs_group_bitmap_free (fs, false, block);
559            return rc;
560          }
561
562          singly_block = rtems_rfs_block_get_number (&map->doubly_buffer,
563                                                     singly);
564
565          rc = rtems_rfs_buffer_handle_request (fs, &map->singly_buffer,
566                                                singly_block, true);
567          if (rc > 0)
568          {
569            rtems_rfs_group_bitmap_free (fs, false, block);
570            return rc;
571          }
572        }
573      }
574
575      rtems_rfs_block_set_number (&map->singly_buffer, direct, block);
576    }
577
578    map->size.count++;
579    map->size.offset = 0;
580
581    if (b == 0)
582      *new_block = block;
583    map->last_data_block = block;
584    map->dirty = true;
585  }
586
587  return 0;
588}
589
590/**
591 * Shrink an indirect block.
592 *
593 * @param fs The file system data.
594 * @param map The map the allocation is for.
595 * @param buffer The buffer the indirect block is accessed by.
596 * @param indirect The index index in the inode's block table.
597 * @param index The index in the indirect table of the block.
598 * @return int The error number (errno). No error if 0.
599 */
600static int
601rtems_rfs_block_map_indirect_shrink (rtems_rfs_file_system*   fs,
602                                     rtems_rfs_block_map*     map,
603                                     rtems_rfs_buffer_handle* buffer,
604                                     rtems_rfs_block_no       indirect,
605                                     rtems_rfs_block_no       index)
606{
607  int rc = 0;
608
609  /*
610   * If this is the first block in the indirect table (index == 0), ie the last
611   * block to be freed and the indirect block is now also free, or we have only
612   * one indirect table and we can fit the remaining blocks into the inode,
613   * then either move to the next indirect block or move the remaining blocks
614   * into the inode and free the indirect table's block.
615   */
616  if ((index == 0) ||
617      ((indirect == 0) && (index == RTEMS_RFS_INODE_BLOCKS)))
618  {
619    rtems_rfs_block_no block_to_free = map->blocks[indirect];
620
621    if ((indirect == 0) && (index == RTEMS_RFS_INODE_BLOCKS))
622    {
623      /*
624       * Move to direct inode access.
625       */
626      int b;
627      for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
628        map->blocks[b] = rtems_rfs_block_get_number (buffer, b);
629    }
630    else
631    {
632      /*
633       * One less singly indirect block in the inode.
634       */
635      map->blocks[indirect] = 0;
636    }
637
638    rc = rtems_rfs_group_bitmap_free (fs, false, block_to_free);
639    if (rc > 0)
640      return rc;
641
642    map->last_map_block = block_to_free;
643  }
644
645  return rc;
646}
647
648int
649rtems_rfs_block_map_shrink (rtems_rfs_file_system* fs,
650                            rtems_rfs_block_map*   map,
651                            size_t                 blocks)
652{
653  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BLOCK_MAP_SHRINK))
654    printf ("rtems-rfs: block-map-shrink: entry: blocks=%zd count=%" PRIu32 "\n",
655            blocks, map->size.count);
656
657  if (map->size.count == 0)
658    return 0;
659
660  if (blocks > map->size.count)
661    blocks = map->size.count;
662
663  while (blocks)
664  {
665    rtems_rfs_block_no block;
666    rtems_rfs_block_no block_to_free;
667    int                rc;
668
669    block = map->size.count - 1;
670
671    if (block < RTEMS_RFS_INODE_BLOCKS)
672    {
673      /*
674       * We have less than RTEMS_RFS_INODE_BLOCKS so they are held in the
675       * inode.
676       */
677      block_to_free = map->blocks[block];
678      map->blocks[block] = 0;
679    }
680    else
681    {
682      /*
683       * Single indirect access is occuring. It could still be doubly indirect.
684       *
685       * The 'direct' variable is the offset in to the indirect table of
686       * blocks, and 'singly' is the inode block index of the singly indirect
687       * table of block numbers.
688       */
689      rtems_rfs_block_no direct;
690      rtems_rfs_block_no singly;
691
692      direct = block % fs->blocks_per_block;
693      singly = block / fs->blocks_per_block;
694
695      if (block < fs->block_map_singly_blocks)
696      {
697        /*
698         * Request the indirect block and then obtain the block number from the
699         * indirect block.
700         */
701        rc = rtems_rfs_buffer_handle_request (fs, &map->singly_buffer,
702                                              map->blocks[singly], true);
703        if (rc > 0)
704          return rc;
705
706        block_to_free = rtems_rfs_block_get_number (&map->singly_buffer,
707                                                    direct);
708
709        rc = rtems_rfs_block_map_indirect_shrink (fs, map, &map->singly_buffer,
710                                                  singly, direct);
711        if (rc)
712          return rc;
713      }
714      else if (block < fs->block_map_doubly_blocks)
715      {
716        /*
717         * Doubly indirect tables are being used. The 'doubly' variable is the
718         * index in to the inode's block table and points to a singly indirect
719         * table of block numbers. The 'doubly_singly' variable is the index
720         * into the doubly indirect table pointing to the singly indirect table
721         * of block numbers that form the map. This is used later to determine
722         * if the current doubly indirect table needs to be freed. The 'direct'
723         * value is still valid for doubly indirect tables.
724         */
725        rtems_rfs_block_no doubly;
726        rtems_rfs_block_no doubly_singly;
727
728        doubly        = singly / fs->blocks_per_block;
729        doubly_singly = singly % fs->blocks_per_block;
730
731        rc = rtems_rfs_buffer_handle_request (fs, &map->doubly_buffer,
732                                              map->blocks[doubly], true);
733        if (rc > 0)
734          return rc;
735
736        singly = rtems_rfs_block_get_number (&map->doubly_buffer,
737                                             doubly_singly);
738
739        /*
740         * Read the singly indirect table and get the block number.
741         */
742        rc = rtems_rfs_buffer_handle_request (fs, &map->singly_buffer,
743                                              singly, true);
744        if (rc > 0)
745          return rc;
746
747        block_to_free = rtems_rfs_block_get_number (&map->singly_buffer,
748                                                    direct);
749
750        if (direct == 0)
751        {
752          rc = rtems_rfs_group_bitmap_free (fs, false, singly);
753          if (rc > 0)
754            return rc;
755
756          map->last_map_block = singly;
757
758          rc = rtems_rfs_block_map_indirect_shrink (fs, map, &map->doubly_buffer,
759                                                    doubly, doubly_singly);
760          if (rc)
761            return rc;
762        }
763      }
764      else
765      {
766        rc = EIO;
767        break;
768      }
769    }
770    rc = rtems_rfs_group_bitmap_free (fs, false, block_to_free);
771    if (rc > 0)
772      return rc;
773    map->size.count--;
774    map->size.offset = 0;
775    map->last_data_block = block_to_free;
776    map->dirty = true;
777    blocks--;
778  }
779
780  if (map->size.count == 0)
781  {
782    map->last_map_block = 0;
783    map->last_data_block = 0;
784  }
785
786  /*
787   * Keep the position inside the map.
788   */
789  if (rtems_rfs_block_pos_past_end (&map->bpos, &map->size))
790    rtems_rfs_block_size_get_bpos (&map->size, &map->bpos);
791
792  return 0;
793}
794
795int
796rtems_rfs_block_map_free_all (rtems_rfs_file_system* fs,
797                              rtems_rfs_block_map*   map)
798{
799  return rtems_rfs_block_map_shrink (fs, map, map->size.count);
800}
Note: See TracBrowser for help on using the repository browser.