source: rtems/cpukit/libfs/src/rfs/rtems-rfs-block.c @ 099cdd5

4.11
Last change on this file since 099cdd5 was 099cdd5, checked in by Chris Johns <chrisj@…>, on Jun 17, 2010 at 10:04:51 PM

2010-06-18 Chris Johns <chrisj@…>

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