source: rtems/cpukit/libfs/src/rfs/rtems-rfs-block.c @ 06e04f8

4.115
Last change on this file since 06e04f8 was 06e04f8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 06/15/10 at 13:35:28

2010-06-15 Ralf Corsépius <ralf.corsepius@…>

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