source: rtems/cpukit/libfs/src/rfs/rtems-rfs-block.c @ 0ec9bbc

5
Last change on this file since 0ec9bbc was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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