source: rtems/cpukit/libfs/src/rfs/rtems-rfs-block.c @ 3cfa636

4.104.115
Last change on this file since 3cfa636 was 3cfa636, checked in by Chris Johns <chrisj@…>, on 02/26/10 at 05:54:59

010-02-26 Chris Johns <chrisj@…>

  • libfs/src/rfs/rtems-rfs-block.c: Reset a buffer handle after moving down an indirection level.
  • libfs/src/rfs/rtems-rfs-dir.c: Move directory entry validation into a macro and use the macro. Fix the range check on the ino so all inodes can be used.
  • libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-file-system.h
Add a version number to the superblock. Use RTEMS_RFS_INODE_SIZE.
  • libfs/src/rfs/rtems-rfs-file.c: Fix the size offset on partial block lengths. Set the size in the file handle on a truncate to 0.
  • libfs/src/rfs/rtems-rfs-format.c: Add a version number to the superblock. Use RTEMS_RFS_INODE_SIZE. A better set of defaults for small disks.
  • libfs/src/rfs/rtems-rfs-inode.c: Use RTEMS_RFS_INODE_SIZE. Free the allocated inode if it cannot be opened.
  • libfs/src/rfs/rtems-rfs-inode.h: Add RTEMS_RFS_INODE_SIZE.
  • libfs/src/rfs/rtems-rfs-rtems-file.c: Move some of the iop acceses inside the fs lock.
  • libfs/src/rfs/rtems-rfs-shell.c: Use RTEMS_RFS_INODE_SIZE.
  • Property mode set to 100644
File size: 24.5 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#include <rtems/rfs/rtems-rfs-block.h>
38#include <rtems/rfs/rtems-rfs-data.h>
39#include <rtems/rfs/rtems-rfs-group.h>
40#include <rtems/rfs/rtems-rfs-inode.h>
41
42void
43rtems_rfs_block_get_bpos (rtems_rfs_file_system*  fs,
44                          rtems_rfs_pos           pos,
45                          rtems_rfs_block_pos*    bpos)
46{
47  bpos->bno  = pos / rtems_rfs_fs_block_size (fs);
48  bpos->boff = pos % rtems_rfs_fs_block_size (fs);
49}
50
51rtems_rfs_pos
52rtems_rfs_block_get_pos (rtems_rfs_file_system*  fs,
53                         rtems_rfs_block_pos*    bpos)
54{
55  rtems_rfs_pos pos = 0;
56  if (bpos->bno)
57  {
58    pos = bpos->boff;
59    if (pos == 0)
60      pos = rtems_rfs_fs_block_size (fs);
61    pos += (bpos->bno - 1) * rtems_rfs_fs_block_size (fs);
62  }
63  return pos;
64}
65
66void
67rtems_rfs_block_get_block_size (rtems_rfs_file_system*  fs,
68                                rtems_rfs_pos           pos,
69                                rtems_rfs_block_size*   size)
70{
71  if (pos == 0)
72    rtems_rfs_block_set_size_zero (size);
73  else
74  {
75    size->count  = pos / rtems_rfs_fs_block_size (fs) + 1;
76    size->offset = pos % rtems_rfs_fs_block_size (fs);
77  }
78}
79
80rtems_rfs_pos
81rtems_rfs_block_get_size (rtems_rfs_file_system* fs,
82                          rtems_rfs_block_size*  size)
83{
84  uint32_t offset;
85  if (size->count == 0)
86    return 0;
87  if (size->offset == 0)
88    offset = rtems_rfs_fs_block_size (fs);
89  else
90    offset = size->offset;
91  return (((uint64_t) (size->count - 1)) * rtems_rfs_fs_block_size (fs)) + 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=%ld, indirect=%ld/%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=%ld\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=%ld count=%lu\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      rtems_rfs_buffer_handle_reset (buffer);
631    }
632    else
633    {
634      /*
635       * One less singly indirect block in the inode.
636       */
637      map->blocks[indirect] = 0;
638    }
639   
640    rc = rtems_rfs_group_bitmap_free (fs, false, block_to_free);
641    if (rc > 0)
642      return rc;
643   
644    map->last_map_block = block_to_free;
645  }
646 
647  return rc;
648}
649
650int
651rtems_rfs_block_map_shrink (rtems_rfs_file_system* fs,
652                            rtems_rfs_block_map*   map,
653                            size_t                 blocks)
654{
655  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BLOCK_MAP_SHRINK))
656    printf ("rtems-rfs: block-map-shrink: entry: blocks=%ld count=%lu\n",
657            blocks, map->size.count);
658           
659  if (map->size.count == 0)
660    return 0;
661   
662  if (blocks > map->size.count)
663    blocks = map->size.count;
664
665  while (blocks)
666  {
667    rtems_rfs_block_no block;
668    rtems_rfs_block_no block_to_free;
669    int                rc;
670
671    block = map->size.count - 1;
672   
673    if (block < RTEMS_RFS_INODE_BLOCKS)
674    {
675      /*
676       * We have less than RTEMS_RFS_INODE_BLOCKS so they are held in the
677       * inode.
678       */
679      block_to_free = map->blocks[block];
680      map->blocks[block] = 0;
681    }
682    else
683    {
684      /*
685       * Single indirect access is occuring. It could still be doubly indirect.
686       *
687       * The 'direct' variable is the offset in to the indirect table of
688       * blocks, and 'singly' is the inode block index of the singly indirect
689       * table of block numbers.
690       */
691      rtems_rfs_block_no direct;
692      rtems_rfs_block_no singly;
693
694      direct = block % fs->blocks_per_block;
695      singly = block / fs->blocks_per_block;
696
697      if (block < fs->block_map_singly_blocks)
698      {
699        /*
700         * Request the indirect block and then obtain the block number from the
701         * indirect block.
702         */
703        rc = rtems_rfs_buffer_handle_request (fs, &map->singly_buffer,
704                                              map->blocks[singly], true);
705        if (rc > 0)
706          return rc;
707       
708        block_to_free = rtems_rfs_block_get_number (&map->singly_buffer,
709                                                    direct);
710
711        rc = rtems_rfs_block_map_indirect_shrink (fs, map, &map->singly_buffer,
712                                                  singly, direct);
713        if (rc)
714          return rc;
715      }
716      else if (block < fs->block_map_doubly_blocks)
717      {
718        /*
719         * Doubly indirect tables are being used. The 'doubly' variable is the
720         * index in to the inode's block table and points to a singly indirect
721         * table of block numbers. The 'doubly_singly' variable is the index
722         * into the doubly indirect table pointing to the singly indirect table
723         * of block numbers that form the map. This is used later to determine
724         * if the current doubly indirect table needs to be freed. The 'direct'
725         * value is still valid for doubly indirect tables.
726         */
727        rtems_rfs_block_no doubly;
728        rtems_rfs_block_no doubly_singly;
729
730        doubly        = singly / fs->blocks_per_block;
731        doubly_singly = singly % fs->blocks_per_block;
732
733        rc = rtems_rfs_buffer_handle_request (fs, &map->doubly_buffer,
734                                              map->blocks[doubly], true);
735        if (rc > 0)
736          return rc;
737
738        singly = rtems_rfs_block_get_number (&map->doubly_buffer,
739                                             doubly_singly);
740
741        /*
742         * Read the singly indirect table and get the block number.
743         */
744        rc = rtems_rfs_buffer_handle_request (fs, &map->singly_buffer,
745                                              singly, true);
746        if (rc > 0)
747          return rc;
748
749        block_to_free = rtems_rfs_block_get_number (&map->singly_buffer,
750                                                    direct);
751
752        if (direct == 0)
753        {
754          rc = rtems_rfs_group_bitmap_free (fs, false, singly);
755          if (rc > 0)
756            return rc;
757         
758          map->last_map_block = singly;
759         
760          rc = rtems_rfs_block_map_indirect_shrink (fs, map, &map->doubly_buffer,
761                                                    doubly, doubly_singly);
762          if (rc)
763            return rc;
764        }       
765      }
766      else
767      {
768        rc = EIO;
769        break;
770      }
771    }
772    rc = rtems_rfs_group_bitmap_free (fs, false, block_to_free);
773    if (rc > 0)
774      return rc;
775    map->size.count--;
776    map->size.offset = 0;
777    map->last_data_block = block_to_free;
778    map->dirty = true;
779    blocks--;
780  }
781
782  if (map->size.count == 0)
783  {
784    map->last_map_block = 0;
785    map->last_data_block = 0;
786  }
787
788  /*
789   * Keep the position inside the map.
790   */
791  if (rtems_rfs_block_pos_past_end (&map->bpos, &map->size))
792    rtems_rfs_block_size_get_bpos (&map->size, &map->bpos);
793
794  return 0;
795}
796
797int
798rtems_rfs_block_map_free_all (rtems_rfs_file_system* fs,
799                              rtems_rfs_block_map*   map)
800{
801  return rtems_rfs_block_map_shrink (fs, map, map->size.count);
802}
Note: See TracBrowser for help on using the repository browser.