source: rtems/cpukit/libfs/src/rfs/rtems-rfs-group.c @ 0c2241c

5
Last change on this file since 0c2241c was 0c2241c, checked in by Fan Deng <enetor@…>, on 10/10/17 at 23:11:49

Make bit addressing consistent in rtems_rfs_group.c

This change fixes https://devel.rtems.org/ticket/3089.

Briefly, rtems_rfs_group.c contains conflicting conversions between
block numbers and group number and bit offset pairs. This caused the
actual bit stored on the bitmask to be one bit displaced from its
intended location.

For more details, please see the associated ticket.

Tested by inspecting the written bitmasks with and without this change.

  • Property mode set to 100644
File size: 10.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief RTEMS File Systems Group Routines
5 * @ingroup rtems_rfs
6 *
7 * These functions open and close a group as well as manage bit allocations
8 * within a group.
9 */
10
11/*
12 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <inttypes.h>
25#include <string.h>
26
27#include <rtems/rfs/rtems-rfs-file-system.h>
28#include <rtems/rfs/rtems-rfs-group.h>
29
30int
31rtems_rfs_group_open (rtems_rfs_file_system* fs,
32                      rtems_rfs_buffer_block base,
33                      size_t                 size,
34                      size_t                 inodes,
35                      rtems_rfs_group*       group)
36{
37  int rc;
38
39  if (base >= rtems_rfs_fs_blocks (fs))
40  {
41    if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
42      printf ("rtems-rfs: group-open: base outside file system range: %d: %s\n",
43              EIO, strerror (EIO));
44    return EIO;
45  }
46
47  if ((base + size) >= rtems_rfs_fs_blocks (fs))
48    size = rtems_rfs_fs_blocks (fs) - base;
49
50  /*
51   * Limit the inodes to the same size as the blocks. This is what the
52   * format does and if this is not done the accounting of inodes does
53   * not work. If we are so pushed for inodes that this makes a difference
54   * the format configuration needs reviewing.
55   */
56  if (inodes > size)
57    inodes = size;
58
59  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
60    printf ("rtems-rfs: group-open: base=%" PRId32 ", blocks=%zd inodes=%zd\n",
61            base, size, inodes);
62
63  group->base = base;
64  group->size = size;
65
66  rc = rtems_rfs_buffer_handle_open (fs, &group->block_bitmap_buffer);
67  if (rc > 0)
68  {
69    if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
70      printf ("rtems-rfs: group-open: could not open block bitmap handle: %d: %s\n",
71              rc, strerror (rc));
72    return rc;
73  }
74
75  rc = rtems_rfs_bitmap_open (&group->block_bitmap, fs,
76                              &group->block_bitmap_buffer, size,
77                              group->base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
78  if (rc > 0)
79  {
80    rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
81    if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
82      printf ("rtems-rfs: group-open: could not open block bitmap: %d: %s\n",
83              rc, strerror (rc));
84    return rc;
85  }
86
87  rc = rtems_rfs_buffer_handle_open (fs, &group->inode_bitmap_buffer);
88  if (rc > 0)
89  {
90    rtems_rfs_bitmap_close (&group->block_bitmap);
91    rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
92    if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
93      printf ("rtems-rfs: group-open: could not open inode bitmap handle: %d: %s\n",
94              rc, strerror (rc));
95    return rc;
96  }
97
98  rc = rtems_rfs_bitmap_open (&group->inode_bitmap, fs,
99                              &group->inode_bitmap_buffer, inodes,
100                              group->base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
101  if (rc > 0)
102  {
103    rtems_rfs_buffer_handle_close (fs, &group->inode_bitmap_buffer);
104    rtems_rfs_bitmap_close (&group->block_bitmap);
105    rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
106    if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_OPEN))
107      printf ("rtems-rfs: group-open: could not open inode bitmap: %d: %s\n",
108              rc, strerror (rc));
109    return rc;
110  }
111
112  if (rtems_rfs_fs_release_bitmaps (fs))
113  {
114    rtems_rfs_bitmap_release_buffer (fs, &group->block_bitmap);
115    rtems_rfs_bitmap_release_buffer (fs, &group->inode_bitmap);
116  }
117
118  return 0;
119}
120
121int
122rtems_rfs_group_close (rtems_rfs_file_system* fs, rtems_rfs_group* group)
123{
124  int result = 0;
125  int rc;
126
127  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_CLOSE))
128    printf ("rtems-rfs: group-close: base=%" PRId32 "\n", group->base);
129
130  /*
131   * We need to close as much as possible and also return any error if one
132   * occurs but this may result in one even more important error being lost but
133   * we cannot OR the errors together so this is a reasonable compromise.
134   */
135  rc = rtems_rfs_bitmap_close (&group->inode_bitmap);
136  if (rc > 0)
137    result = rc;
138  rc = rtems_rfs_buffer_handle_close (fs, &group->inode_bitmap_buffer);
139  if (rc > 0)
140    result = rc;
141  rc = rtems_rfs_bitmap_close (&group->block_bitmap);
142  if (rc > 0)
143    result = rc;
144  rc = rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
145  if (rc > 0)
146    result = rc;
147
148  return result;
149}
150
151int
152rtems_rfs_group_bitmap_alloc (rtems_rfs_file_system* fs,
153                              rtems_rfs_bitmap_bit   goal,
154                              bool                   inode,
155                              rtems_rfs_bitmap_bit*  result)
156{
157  int                  group_start;
158  size_t               size;
159  rtems_rfs_bitmap_bit bit;
160  int                  offset;
161  bool                 updown;
162  int                  direction;
163
164  if (inode)
165  {
166    size = fs->group_inodes;
167    goal -= RTEMS_RFS_ROOT_INO;
168  }
169  else
170  {
171    size = fs->group_blocks;
172    /*
173     * It is possible for 'goal' to be zero. Any newly created inode will have
174     * its 'last_data_block' set to zero, which is then used as 'goal' to
175     * allocate new blocks. When that happens, we simply set 'goal' to zero and
176     * continue the search from there.
177     */
178    if (goal >= RTEMS_RFS_ROOT_INO)
179        goal -= RTEMS_RFS_ROOT_INO;
180  }
181
182  group_start = goal / size;
183  bit = (rtems_rfs_bitmap_bit) (goal % size);
184  offset = 0;
185  updown = true;
186  direction = 1;
187
188  /*
189   * Try the goal group first and if that group fails try the groups either
190   * side until the whole file system has be tried.
191   */
192  while (true)
193  {
194    rtems_rfs_bitmap_control* bitmap;
195    int                       group;
196    bool                      allocated = false;
197    int                       rc;
198
199    /*
200     * We can start at any location and we move out from that point in each
201     * direction. The offset grows until we find a free bit or we hit an end.
202     */
203    group = group_start + (direction * offset);
204    if (offset)
205      bit = direction > 0 ? 0 : size - 1;
206
207    /*
208     * If we are still looking up and down and if the group is out of range we
209     * have reached one end. Stopping looking up and down and just move in the
210     * one direction one group at a time.
211     */
212    if ((group < 0) || (group >= fs->group_count))
213    {
214      if (!updown)
215        break;
216      direction = direction > 0 ? -1 : 1;
217      updown = false;
218      continue;
219    }
220
221   if (inode)
222      bitmap = &fs->groups[group].inode_bitmap;
223    else
224      bitmap = &fs->groups[group].block_bitmap;
225
226    rc = rtems_rfs_bitmap_map_alloc (bitmap, bit, &allocated, &bit);
227    if (rc > 0)
228      return rc;
229
230    if (rtems_rfs_fs_release_bitmaps (fs))
231      rtems_rfs_bitmap_release_buffer (fs, bitmap);
232
233    if (allocated)
234    {
235      if (inode)
236        *result = rtems_rfs_group_inode (fs, group, bit);
237      else
238        *result = rtems_rfs_group_block (&fs->groups[group], bit);
239      if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
240        printf ("rtems-rfs: group-bitmap-alloc: %s allocated: %" PRId32 "\n",
241                inode ? "inode" : "block", *result);
242      return 0;
243    }
244
245    /*
246     * If we are still looking back and forth around the
247     * group_start, then alternate the direction and
248     * increment the offset on every other iteration.
249     * Otherwise we are marching through the groups, so just
250     * increment the offset.
251     */
252    if (updown)
253    {
254      direction = direction > 0 ? -1 : 1;
255      if ( direction == -1 )
256        offset++;
257    }
258    else
259    {
260       offset++;
261    }
262
263  }
264
265  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
266    printf ("rtems-rfs: group-bitmap-alloc: no blocks available\n");
267
268  return ENOSPC;
269}
270
271int
272rtems_rfs_group_bitmap_free (rtems_rfs_file_system* fs,
273                             bool                   inode,
274                             rtems_rfs_bitmap_bit   no)
275{
276  rtems_rfs_bitmap_control* bitmap;
277  unsigned int              group;
278  rtems_rfs_bitmap_bit      bit;
279  size_t                    size;
280  int                       rc;
281
282  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
283    printf ("rtems-rfs: group-bitmap-free: %s free: %" PRId32 "\n",
284            inode ? "inode" : "block", no);
285
286  if (inode)
287  {
288    no -= RTEMS_RFS_ROOT_INO;
289    size = fs->group_inodes;
290  }
291  else
292  {
293    no -= RTEMS_RFS_SUPERBLOCK_SIZE;
294    size = fs->group_blocks;
295  }
296
297  group = no / size;
298  bit = (rtems_rfs_bitmap_bit) (no % size);
299
300  if (inode)
301    bitmap = &fs->groups[group].inode_bitmap;
302  else
303    bitmap = &fs->groups[group].block_bitmap;
304
305  rc = rtems_rfs_bitmap_map_clear (bitmap, bit);
306
307  rtems_rfs_bitmap_release_buffer (fs, bitmap);
308
309  return rc;
310}
311
312int
313rtems_rfs_group_bitmap_test (rtems_rfs_file_system* fs,
314                             bool                   inode,
315                             rtems_rfs_bitmap_bit   no,
316                             bool*                  state)
317{
318  rtems_rfs_bitmap_control* bitmap;
319  unsigned int              group;
320  rtems_rfs_bitmap_bit      bit;
321  size_t                    size;
322  int                       rc;
323
324  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
325    printf ("rtems-rfs: group-bitmap-test: %s test: %" PRId32 "\n",
326            inode ? "inode" : "block", no);
327
328  if (inode)
329  {
330    if ((no < RTEMS_RFS_ROOT_INO) || (no > rtems_rfs_fs_inodes (fs)))
331        return EINVAL;
332    no -= RTEMS_RFS_ROOT_INO;
333    size = fs->group_inodes;
334  }
335  else
336  {
337    if ((no < RTEMS_RFS_ROOT_INO) || (no >= rtems_rfs_fs_blocks (fs)))
338        return EINVAL;
339    no -= RTEMS_RFS_ROOT_INO;
340    size = fs->group_blocks;
341  }
342
343  group = no / size;
344  bit = (rtems_rfs_bitmap_bit) (no % size);
345
346  if (inode)
347    bitmap = &fs->groups[group].inode_bitmap;
348  else
349    bitmap = &fs->groups[group].block_bitmap;
350
351  rc = rtems_rfs_bitmap_map_test (bitmap, bit, state);
352
353  rtems_rfs_bitmap_release_buffer (fs, bitmap);
354
355  return rc;
356}
357
358int
359rtems_rfs_group_usage (rtems_rfs_file_system* fs,
360                       size_t*                blocks,
361                       size_t*                inodes)
362{
363  int g;
364
365  *blocks = 0;
366  *inodes = 0;
367
368  for (g = 0; g < fs->group_count; g++)
369  {
370    rtems_rfs_group* group = &fs->groups[g];
371    *blocks +=
372      rtems_rfs_bitmap_map_size(&group->block_bitmap) -
373      rtems_rfs_bitmap_map_free (&group->block_bitmap);
374    *inodes +=
375      rtems_rfs_bitmap_map_size (&group->inode_bitmap) -
376      rtems_rfs_bitmap_map_free (&group->inode_bitmap);
377  }
378
379  if (*blocks > rtems_rfs_fs_blocks (fs))
380    *blocks = rtems_rfs_fs_blocks (fs);
381  if (*inodes > rtems_rfs_fs_inodes (fs))
382    *inodes = rtems_rfs_fs_inodes (fs);
383
384  return 0;
385}
386
Note: See TracBrowser for help on using the repository browser.