source: rtems/cpukit/libfs/src/rfs/rtems-rfs-bitmaps.c @ 355b0544

4.104.115
Last change on this file since 355b0544 was 355b0544, checked in by Chris Johns <chrisj@…>, on 03/27/10 at 04:04:40

2010-03-27 Chris Johns <chrisj@…>

libfs/src/nfsclient/src/cexphelp.c,
libfs/src/nfsclient/src/dirutils.c,
libfs/src/nfsclient/src/nfs.modini.c,
libfs/src/nfsclient/src/nfsTest.c,
libfs/src/nfsclient/src/rpcio.c,
libfs/src/nfsclient/src/rpcio.modini.c,
libfs/src/nfsclient/src/sock_mbuf.c,
libfs/src/nfsclient/src/xdr_mbuf.c,
libfs/src/rfs/rtems-rfs-bitmaps-ut.c,
libfs/src/rfs/rtems-rfs-bitmaps.c,
libfs/src/rfs/rtems-rfs-block.c,
libfs/src/rfs/rtems-rfs-buffer-bdbuf.c,
libfs/src/rfs/rtems-rfs-buffer-devio.c,
libfs/src/rfs/rtems-rfs-buffer.c,
libfs/src/rfs/rtems-rfs-dir-hash.c, libfs/src/rfs/rtems-rfs-dir.c,
libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-file.c, libfs/src/rfs/rtems-rfs-format.c,
libfs/src/rfs/rtems-rfs-group.c, libfs/src/rfs/rtems-rfs-inode.c,
libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-mutex.c,
libfs/src/rfs/rtems-rfs-rtems-dev.c,
libfs/src/rfs/rtems-rfs-rtems-dir.c,
libfs/src/rfs/rtems-rfs-rtems-file.c,
libfs/src/rfs/rtems-rfs-rtems-utils.c,
libfs/src/rfs/rtems-rfs-rtems.c, libfs/src/rfs/rtems-rfs-shell.c,
libfs/src/rfs/rtems-rfs-trace.c: Add HAVE_CONFIG_H support to let
files receive configure defines.

  • Property mode set to 100644
File size: 18.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 Bitmap Routines.
16 *
17 * These functions manage bit maps. A bit map consists of the map of bit
18 * allocated in a block and a search map where a bit represents 32 actual
19 * bits. The search map allows for a faster search for an available bit as 32
20 * search bits can checked in a test.
21 */
22
23#if HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27/**
28 * Set to 1 to enable warnings when developing.
29 */
30#define RTEMS_RFS_BITMAP_WARNINGS 0
31
32#if RTEMS_RFS_BITMAP_WARNINGS
33#include <stdio.h>
34#endif
35#include <stdlib.h>
36#include <rtems/rfs/rtems-rfs-bitmaps.h>
37
38/**
39 * Test a bit in an element. If set return true else return false.
40 *
41 * @param target The target to test the bit in.
42 * @param bit The bit to test.
43 * @retval true The bit is set.
44 * @retval false The bit is clear.
45 */
46static bool
47rtems_rfs_bitmap_test (rtems_rfs_bitmap_element target,
48                       rtems_rfs_bitmap_bit     bit)
49{
50  return RTEMS_RFS_BITMAP_TEST_BIT (target, bit);
51}
52
53/**
54 * Set the bits in the element. Bits not set in the bit argument are left
55 * unchanged.
56 *
57 * @param target The target element bits are set.
58 * @param bits The bits in the target to set. A 1 in the bits will set the
59 *             same bit in the target.
60 */
61static rtems_rfs_bitmap_element
62rtems_rfs_bitmap_set (rtems_rfs_bitmap_element target,
63                      rtems_rfs_bitmap_element bits)
64{
65  return RTEMS_RFS_BITMAP_SET_BITS (target, bits);
66}
67
68/**
69 * Clear the bits in the element. Bits not set in the bit argument are left
70 * unchanged.
71 *
72 * @param target The target element to clear the bits in.
73 * @param bits The bits in the target to clear. A 1 in the bits will clear the
74 *             bit in the target.
75 */
76static rtems_rfs_bitmap_element
77rtems_rfs_bitmap_clear (rtems_rfs_bitmap_element target,
78                        rtems_rfs_bitmap_element bits)
79{
80  return RTEMS_RFS_BITMAP_CLEAR_BITS (target, bits);
81}
82
83/**
84 * Merge the bits in 2 variables based on the mask. A set bit in the mask will
85 * merge the bits from bits1 and a clear bit will merge the bits from bits2.
86 * The mask is always defined as 1 being set and 0 being clear.
87 */
88static rtems_rfs_bitmap_element
89rtems_rfs_bitmap_merge (rtems_rfs_bitmap_element bits1,
90                        rtems_rfs_bitmap_element bits2,
91                        rtems_rfs_bitmap_element mask)
92{
93  /*
94   * Use the normal bit operators because we do not change the bits just merge
95   * the 2 separate parts.
96   */
97  bits1 &= mask;
98  bits2 &= RTEMS_RFS_BITMAP_INVERT_MASK (mask);
99  return bits1 | bits2;
100}
101
102/**
103 * Match the bits of 2 elements and return true if they match else return
104 * false.
105 *
106 * @param bits1 One set of bits to match.
107 * @param bits2 The second set of bits to match.
108 * @retval true The bits match.
109 * @retval false The bits do not match.
110 */
111static bool
112rtems_rfs_bitmap_match (rtems_rfs_bitmap_element bits1,
113                        rtems_rfs_bitmap_element bits2)
114{
115  return bits1 ^ bits2 ? false : true;
116}
117
118#if RTEMS_NOT_USED_BUT_KEPT
119/**
120 * Match the bits of 2 elements within the mask and return true if they match
121 * else return false.
122 *
123 * @param mask The mask over which the match occurs. A 1 is a valid mask bit.
124 * @param bits1 One set of bits to match.
125 * @param bits2 The second set of bits to match.
126 * @retval true The bits match.
127 * @retval false The bits do not match.
128 */
129static bool
130rtems_rfs_bitmap_match_masked (rtems_rfs_bitmap_element mask,
131                               rtems_rfs_bitmap_element bits1,
132                               rtems_rfs_bitmap_element bits2)
133{
134  return (bits1 ^ bits2) & mask ? false : true;
135}
136#endif
137
138/**
139 * Return the map after loading from disk if not already loaded.
140 *
141 * @param control The bitmap control.
142 * @param rtems_rfs_bitmap_map* Pointer to the bitmap map data if no error.
143 * @return int The error number (errno). No error if 0.
144 */
145static int
146rtems_rfs_bitmap_load_map (rtems_rfs_bitmap_control* control,
147                           rtems_rfs_bitmap_map*     map)
148{
149  int rc;
150 
151  if (!control->buffer)
152    return ENXIO;
153
154  *map = NULL;
155 
156  rc = rtems_rfs_buffer_handle_request (control->fs,
157                                        control->buffer,
158                                        control->block,
159                                        true);
160  if (rc)
161    return rc;
162 
163  *map = rtems_rfs_buffer_data (control->buffer);
164  return 0;
165}
166
167rtems_rfs_bitmap_element
168rtems_rfs_bitmap_mask (unsigned int size)
169{
170  rtems_rfs_bitmap_element mask = RTEMS_RFS_BITMAP_ELEMENT_FULL_MASK;
171  mask >>= (rtems_rfs_bitmap_element_bits () - size);
172  return mask;
173}
174
175rtems_rfs_bitmap_element
176rtems_rfs_bitmap_mask_section (unsigned int start, unsigned int end)
177{
178  rtems_rfs_bitmap_element mask = 0;
179  if (end > start)
180    mask = rtems_rfs_bitmap_mask (end - start) << start;
181  return mask;
182}
183
184int
185rtems_rfs_bitmap_map_set (rtems_rfs_bitmap_control* control,
186                          rtems_rfs_bitmap_bit      bit)
187{
188  rtems_rfs_bitmap_map map;
189  rtems_rfs_bitmap_map search_map;
190  int                  index;
191  int                  offset;
192  int                 rc;
193  rc = rtems_rfs_bitmap_load_map (control, &map);
194  if (rc > 0)
195    return rc;
196  if (bit >= control->size)
197    return EINVAL;
198  search_map = control->search_bits;
199  index      = rtems_rfs_bitmap_map_index (bit);
200  offset     = rtems_rfs_bitmap_map_offset (bit);
201  map[index] = rtems_rfs_bitmap_set (map[index], 1 << offset);
202  if (rtems_rfs_bitmap_match(map[index], RTEMS_RFS_BITMAP_ELEMENT_SET))
203  {
204    bit = index;
205    index  = rtems_rfs_bitmap_map_index (bit);
206    offset = rtems_rfs_bitmap_map_offset (bit);
207    search_map[index] = rtems_rfs_bitmap_set (search_map[index], 1 << offset);
208    control->free--;
209    rtems_rfs_buffer_mark_dirty (control->buffer);
210  }
211  return 0;
212}
213
214int
215rtems_rfs_bitmap_map_clear (rtems_rfs_bitmap_control* control,
216                            rtems_rfs_bitmap_bit      bit)
217{
218  rtems_rfs_bitmap_map map;
219  rtems_rfs_bitmap_map search_map;
220  int                  index;
221  int                  offset;
222  int                  rc;
223  rc = rtems_rfs_bitmap_load_map (control, &map);
224  if (rc > 0)
225    return rc;
226  if (bit >= control->size)
227    return EINVAL;
228  search_map        = control->search_bits;
229  index             = rtems_rfs_bitmap_map_index (bit);
230  offset            = rtems_rfs_bitmap_map_offset (bit);
231  map[index]        = rtems_rfs_bitmap_clear (map[index], 1 << offset);
232  bit               = index;
233  index             = rtems_rfs_bitmap_map_index (bit);
234  offset            = rtems_rfs_bitmap_map_offset(bit);
235  search_map[index] = rtems_rfs_bitmap_clear (search_map[index], 1 << offset);
236  rtems_rfs_buffer_mark_dirty (control->buffer);
237  control->free++;
238  return 0;
239}
240
241int
242rtems_rfs_bitmap_map_test (rtems_rfs_bitmap_control* control,
243                           rtems_rfs_bitmap_bit      bit,
244                           bool*                     state)
245{
246  rtems_rfs_bitmap_map map;
247  int                  index;
248  int                  rc;
249  rc = rtems_rfs_bitmap_load_map (control, &map);
250  if (rc > 0)
251    return rc;
252  if (bit >= control->size)
253    return EINVAL;
254  index = rtems_rfs_bitmap_map_index (bit);
255  *state = rtems_rfs_bitmap_test (map[index], bit);
256  return 0;
257}
258
259int
260rtems_rfs_bitmap_map_set_all (rtems_rfs_bitmap_control* control)
261{
262  rtems_rfs_bitmap_map map;
263  size_t               elements;
264  int                  e;
265  int                  rc;
266
267  rc = rtems_rfs_bitmap_load_map (control, &map);
268  if (rc > 0)
269    return rc;
270 
271  elements = rtems_rfs_bitmap_elements (control->size);
272
273  control->free = 0;
274 
275  for (e = 0; e < elements; e++)
276    map[e] = RTEMS_RFS_BITMAP_ELEMENT_SET;
277 
278  elements = rtems_rfs_bitmap_elements (elements);
279 
280  for (e = 0; e < elements; e++)
281    control->search_bits[e] = RTEMS_RFS_BITMAP_ELEMENT_SET;
282
283  rtems_rfs_buffer_mark_dirty (control->buffer);
284
285  return 0;
286}
287
288int
289rtems_rfs_bitmap_map_clear_all (rtems_rfs_bitmap_control* control)
290{
291  rtems_rfs_bitmap_map map;
292  rtems_rfs_bitmap_bit last_search_bit;
293  size_t               elements;
294  int                  e;
295  int                  rc;
296 
297  rc = rtems_rfs_bitmap_load_map (control, &map);
298  if (rc > 0)
299    return rc;
300 
301  elements = rtems_rfs_bitmap_elements (control->size);
302 
303  control->free = elements;
304 
305  for (e = 0; e < elements; e++)
306    map[e] = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
307
308  /*
309   * Set the un-mapped bits in the last search element so the available logic
310   * works.
311   */
312  last_search_bit = rtems_rfs_bitmap_map_offset (elements);
313
314  if (last_search_bit == 0)
315    last_search_bit = rtems_rfs_bitmap_element_bits ();
316 
317  elements = rtems_rfs_bitmap_elements (elements);
318 
319  for (e = 0; e < (elements - 1); e++)
320    control->search_bits[e] = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
321 
322  control->search_bits[elements - 1] =
323    rtems_rfs_bitmap_merge (RTEMS_RFS_BITMAP_ELEMENT_CLEAR,
324                            RTEMS_RFS_BITMAP_ELEMENT_SET,
325                            rtems_rfs_bitmap_mask (last_search_bit));
326
327  rtems_rfs_buffer_mark_dirty (control->buffer);
328
329  return 0;
330}
331
332static int
333rtems_rfs_search_map_for_clear_bit (rtems_rfs_bitmap_control* control,
334                                    rtems_rfs_bitmap_bit*     bit,
335                                    bool*                     found,
336                                    size_t                    window,
337                                    int                       direction)
338{
339  rtems_rfs_bitmap_map      map;
340  rtems_rfs_bitmap_bit      test_bit;
341  rtems_rfs_bitmap_bit      end_bit;
342  rtems_rfs_bitmap_element* search_bits;
343  int                       search_index;
344  int                       search_offset;
345  rtems_rfs_bitmap_element* map_bits;
346  int                       map_index;
347  int                       map_offset;
348  int                       rc;
349
350  *found = false;
351 
352  /*
353   * Load the bitmap.
354   */
355  rc = rtems_rfs_bitmap_load_map (control, &map);
356  if (rc > 0)
357    return rc;
358 
359  /*
360   * Calculate the bit we are testing plus the end point we search over.
361   */
362  test_bit = *bit;
363  end_bit  = test_bit + (window * direction);
364
365  if (end_bit < 0)
366    end_bit = 0;
367  else if (end_bit >= control->size)
368    end_bit = control->size - 1;
369 
370  map_index     = rtems_rfs_bitmap_map_index (test_bit);
371  map_offset    = rtems_rfs_bitmap_map_offset (test_bit);
372  search_index  = rtems_rfs_bitmap_map_index (map_index);
373  search_offset = rtems_rfs_bitmap_map_offset (map_index);
374
375  search_bits = &control->search_bits[search_index];
376  map_bits    = &map[map_index];
377 
378  /*
379   * Check each bit from the search map offset for a clear bit.
380   */
381  do
382  {
383    /*
384     * If any bit is clear find that bit and then search the map element. If
385     * all bits are set there are no map bits so move to the next search
386     * element.
387     */
388    if (!rtems_rfs_bitmap_match (*search_bits, RTEMS_RFS_BITMAP_ELEMENT_SET))
389    {
390      while ((search_offset >= 0)
391             && (search_offset < rtems_rfs_bitmap_element_bits ()))
392      {
393        if (!rtems_rfs_bitmap_test (*search_bits, search_offset))
394        {
395          /*
396           * Find the clear bit in the map. Update the search map and map if
397           * found. We may find none are spare if searching up from the seed.
398           */
399          while ((map_offset >= 0)
400                 && (map_offset < rtems_rfs_bitmap_element_bits ()))
401          {
402            if (!rtems_rfs_bitmap_test (*map_bits, map_offset))
403            {
404              *map_bits = rtems_rfs_bitmap_set (*map_bits, 1 << map_offset);
405              if (rtems_rfs_bitmap_match(*map_bits,
406                                         RTEMS_RFS_BITMAP_ELEMENT_SET))
407                *search_bits = rtems_rfs_bitmap_set (*search_bits,
408                                                     1 << search_offset);
409              control->free--;
410              *bit = test_bit;
411              *found = true;
412              rtems_rfs_buffer_mark_dirty (control->buffer);
413              return 0;
414            }
415
416            if (test_bit == end_bit)
417              break;
418
419            map_offset += direction;
420            test_bit   += direction;
421          }
422        }
423
424        map_bits  += direction;
425        map_index += direction;
426        map_offset = direction > 0 ? 0 : rtems_rfs_bitmap_element_bits () - 1;
427       
428        test_bit = (map_index * rtems_rfs_bitmap_element_bits ()) + map_offset;
429   
430        search_offset += direction;
431     
432        if (((direction < 0) && (test_bit <= end_bit))
433            || ((direction > 0) && (test_bit >= end_bit)))
434          break;
435      }
436    }
437    else
438    {
439      /*
440       * Move to the next search element. We need to determine the number of
441       * bits in the search offset that are being skipped so the map bits
442       * pointer can be updated. If we are moving down and we have a search
443       * offset of 0 then the search map adjustment is to the top bit of the
444       * pervious search bit's value.
445       *
446       * Align test_bit either up or down depending on the direction to next 32
447       * bit boundary.
448       */
449      rtems_rfs_bitmap_bit bits_skipped;
450      test_bit &= ~((1 << RTEMS_RFS_ELEMENT_BITS_POWER_2) - 1);
451      if (direction > 0)
452      {
453        bits_skipped = rtems_rfs_bitmap_element_bits () - search_offset;
454        test_bit += bits_skipped * rtems_rfs_bitmap_element_bits ();
455        map_offset = 0;
456      }
457      else
458      {
459        bits_skipped = search_offset + 1;
460        /*
461         * Need to remove 1 for the rounding up. The above rounds down and
462         * adds 1. Remember the logic is for subtraction.
463         */
464        test_bit -= ((bits_skipped - 1) * rtems_rfs_bitmap_element_bits ()) + 1;
465        map_offset = rtems_rfs_bitmap_element_bits () - 1;
466      }
467      map_bits += direction * bits_skipped;
468      map_index += direction * bits_skipped;
469    }
470
471    search_bits  += direction;
472    search_offset = direction > 0 ? 0 : rtems_rfs_bitmap_element_bits () - 1;
473  }
474  while (((direction < 0) && (test_bit >= end_bit))
475         || ((direction > 0) && (test_bit <= end_bit)));
476   
477  return 0;
478}
479
480int
481rtems_rfs_bitmap_map_alloc (rtems_rfs_bitmap_control* control,
482                            rtems_rfs_bitmap_bit      seed,
483                            bool*                     allocated,
484                            rtems_rfs_bitmap_bit*     bit)
485{
486  rtems_rfs_bitmap_bit upper_seed;
487  rtems_rfs_bitmap_bit lower_seed;
488  rtems_rfs_bitmap_bit window;     /* may become a parameter */
489  int                  rc = 0;
490
491  /*
492   * By default we assume the allocation failed.
493   */
494  *allocated = false;
495 
496  /*
497   * The window is the number of bits we search over in either direction each
498   * time.
499   */
500  window = RTEMS_RFS_BITMAP_SEARCH_WINDOW;
501
502  /*
503   * Start from the seed and move in either direction. Search in window amounts
504   * of bits from the original seed above then below. That is search from the
505   * seed up then from the seed down a window number of bits, then repeat the
506   * process from the window distance from the seed, again above then
507   * below. Keep moving out until all bits have been searched.
508   */
509  upper_seed = seed;
510  lower_seed = seed;
511
512  /*
513   * If the upper and lower seed values have reached the limits of the bitmap
514   * we have searched all of the map. The seed may not be aligned to a window
515   * boundary so we may need to search a partial window and this may also not
516   * be balanced for the upper or lower seeds. We move to the limits, search
517   * then return false if no clear bits are found.
518   */
519  while (((upper_seed >= 0) && (upper_seed < control->size))
520         || ((lower_seed >= 0) && (lower_seed < control->size)))
521  {
522    /*
523     * Search up first so bits allocated in succession are grouped together.
524     */
525    if (upper_seed < control->size)
526    {
527      *bit = upper_seed;
528      rc = rtems_rfs_search_map_for_clear_bit (control, bit, allocated,
529                                               window, 1);
530      if ((rc > 0) || *allocated)
531        break;
532    }
533
534    if (lower_seed >= 0)
535    {
536      *bit = lower_seed;
537      rc = rtems_rfs_search_map_for_clear_bit (control, bit, allocated,
538                                               window, -1);
539      if ((rc > 0) || *allocated)
540        break;
541    }
542
543    /*
544     * Do not bound the limits at the edges of the map. Do not update if an
545     * edge has been passed.
546     */
547    if (upper_seed < control->size)
548      upper_seed += window;
549    if (lower_seed >= 0)
550      lower_seed -= window;
551  }
552 
553  return 0;
554}
555
556int
557rtems_rfs_bitmap_create_search (rtems_rfs_bitmap_control* control)
558{
559  rtems_rfs_bitmap_map search_map;
560  rtems_rfs_bitmap_map map;
561  size_t               size;
562  rtems_rfs_bitmap_bit bit;
563  int                  rc;
564 
565  rc = rtems_rfs_bitmap_load_map (control, &map);
566  if (rc > 0)
567    return rc;
568
569  control->free = 0;
570  search_map = control->search_bits;
571  size = control->size;
572  bit = 0;
573 
574  *search_map = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
575  while (size)
576  {
577    rtems_rfs_bitmap_element bits;
578    int                      available;
579    if (size < rtems_rfs_bitmap_element_bits ())
580    {
581      bits = rtems_rfs_bitmap_merge (*map,
582                                     RTEMS_RFS_BITMAP_ELEMENT_SET,
583                                     rtems_rfs_bitmap_mask_section (0, size));
584      available = size;
585    }
586    else
587    {
588      bits      = *map;
589      available = rtems_rfs_bitmap_element_bits ();
590    }
591   
592    if (rtems_rfs_bitmap_match (bits, RTEMS_RFS_BITMAP_ELEMENT_SET))
593      rtems_rfs_bitmap_set (*search_map, bit);
594    else
595    {
596      int b;
597      for (b = 0; b < available; b++)
598        if (!rtems_rfs_bitmap_test (bits, b))
599          control->free++;
600    }
601
602    size -= available;
603   
604    if (bit == rtems_rfs_bitmap_element_bits ())
605    {
606      bit = 0;
607      search_map++;
608      *search_map = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
609    }
610    else
611      bit++;
612    map++;
613  }
614
615  return 0;
616}
617
618int
619rtems_rfs_bitmap_open (rtems_rfs_bitmap_control* control,
620                       rtems_rfs_file_system*    fs,
621                       rtems_rfs_buffer_handle*  buffer,
622                       size_t                    size,
623                       rtems_rfs_buffer_block    block)
624{
625  size_t elements = rtems_rfs_bitmap_elements (size);
626 
627  control->buffer = buffer;
628  control->fs = fs;
629  control->block = block;
630  control->size = size;
631 
632  elements = rtems_rfs_bitmap_elements (elements);
633  control->search_bits = malloc (elements * sizeof (rtems_rfs_bitmap_element));
634 
635  if (!control->search_bits)
636    return ENOMEM;
637
638  return rtems_rfs_bitmap_create_search (control);
639}
640
641int
642rtems_rfs_bitmap_close (rtems_rfs_bitmap_control* control)
643{
644  free (control->search_bits);
645  return 0;
646}
Note: See TracBrowser for help on using the repository browser.