The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/hfs/bitmap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * linux/fs/hfs/bitmap.c
    3  *
    4  * Copyright (C) 1996-1997  Paul H. Hargrove
    5  * This file may be distributed under the terms of the GNU General Public License.
    6  *
    7  * Based on GPLed code Copyright (C) 1995  Michael Dreher
    8  *
    9  * This file contains the code to modify the volume bitmap:
   10  * search/set/clear bits.
   11  *
   12  * "XXX" in a comment is a note to myself to consider changing something.
   13  *
   14  * In function preconditions the term "valid" applied to a pointer to
   15  * a structure means that the pointer is non-NULL and the structure it
   16  * points to has all fields initialized to consistent values.
   17  */
   18 
   19 #include "hfs.h"
   20 
   21 /*================ Global functions ================*/
   22 
   23 /*
   24  * hfs_vbm_count_free()
   25  *
   26  * Description:
   27  *   Count the number of consecutive cleared bits in the bitmap blocks of
   28  *   the hfs MDB starting at bit number 'start'.  'mdb' had better
   29  *   be locked or the indicated number of blocks may be no longer free,
   30  *   when this functions returns!
   31  * Input Variable(s):
   32  *   struct hfs_mdb *mdb: Pointer to the hfs MDB
   33  *   hfs_u16 start: bit number to start at
   34  * Output Variable(s):
   35  *   NONE
   36  * Returns:
   37  *   The number of consecutive cleared bits starting at bit 'start'
   38  * Preconditions:
   39  *   'mdb' points to a "valid" (struct hfs_mdb).
   40  * Postconditions:
   41  *   NONE
   42  */
   43 hfs_u16 hfs_vbm_count_free(const struct hfs_mdb *mdb, hfs_u16 start)
   44 {
   45         hfs_u16 block_nr;       /* index of the current bitmap block */
   46         hfs_u16 bit_nr;         /* index of the current bit in block */
   47         hfs_u16 count;          /* number of bits found so far */
   48         hfs_u16 len;            /* number of bits found in this block */
   49         hfs_u16 max_block;      /* index of last bitmap block */
   50         hfs_u16 max_bits;       /* index of last bit in block */
   51 
   52         /* is this a valid HFS MDB? */
   53         if (!mdb) {
   54                 return 0;
   55         }
   56 
   57         block_nr = start / HFS_BM_BPB;
   58         bit_nr   = start % HFS_BM_BPB;
   59         max_block = (mdb->fs_ablocks + HFS_BM_BPB - 1) / HFS_BM_BPB - 1;
   60 
   61         count = 0;
   62         while (block_nr <= max_block) {
   63                 if (block_nr != max_block) {
   64                         max_bits = HFS_BM_BPB;
   65                 } else {
   66                         max_bits = mdb->fs_ablocks % HFS_BM_BPB;
   67                 }
   68 
   69                 len=hfs_count_zero_bits(hfs_buffer_data(mdb->bitmap[block_nr]),
   70                                         max_bits, bit_nr);
   71                 count += len;
   72 
   73                 /* see if we fell short of the end of this block */
   74                 if ((len + bit_nr) < max_bits) {
   75                         break;
   76                 }
   77 
   78                 ++block_nr;
   79                 bit_nr = 0;
   80         }
   81         return count;
   82 }
   83 
   84 /*
   85  * hfs_vbm_search_free()
   86  *
   87  * Description:
   88  *   Search for 'num_bits' consecutive cleared bits in the bitmap blocks of
   89  *   the hfs MDB. 'mdb' had better be locked or the returned range
   90  *   may be no longer free, when this functions returns!
   91  *   XXX Currently the search starts from bit 0, but it should start with
   92  *   the bit number stored in 's_alloc_ptr' of the MDB.
   93  * Input Variable(s):
   94  *   struct hfs_mdb *mdb: Pointer to the hfs MDB
   95  *   hfs_u16 *num_bits: Pointer to the number of cleared bits
   96  *     to search for
   97  * Output Variable(s):
   98  *   hfs_u16 *num_bits: The number of consecutive clear bits of the
   99  *     returned range. If the bitmap is fragmented, this will be less than
  100  *     requested and it will be zero, when the disk is full.
  101  * Returns:
  102  *   The number of the first bit of the range of cleared bits which has been
  103  *   found. When 'num_bits' is zero, this is invalid!
  104  * Preconditions:
  105  *   'mdb' points to a "valid" (struct hfs_mdb).
  106  *   'num_bits' points to a variable of type (hfs_u16), which contains
  107  *      the number of cleared bits to find.
  108  * Postconditions:
  109  *   'num_bits' is set to the length of the found sequence.
  110  */
  111 hfs_u16 hfs_vbm_search_free(const struct hfs_mdb *mdb, hfs_u16 *num_bits)
  112 {
  113         hfs_u16 block_nr; /* index of the current bitmap block */
  114 
  115         /* position and length of current portion of a run */
  116         hfs_u16 cur_pos, cur_len;
  117 
  118         /* position and length of current complete run */
  119         hfs_u16 pos=0, len=0;
  120         
  121         /* position and length of longest complete run */
  122         hfs_u16 longest_pos=0, longest_len=0;
  123 
  124         void *bitmap; /* contents of the current bitmap block */
  125         hfs_u16 max_block; /* upper limit of outer loop */
  126         hfs_u16 max_bits; /* upper limit of inner loop */
  127 
  128         /* is this a valid HFS MDB? */
  129         if (!mdb) {
  130                 *num_bits = 0;
  131                 hfs_warn("hfs_vbm_search_free: not a valid MDB\n");
  132                 return 0;
  133         }
  134         
  135         /* make sure we have actual work to perform */
  136         if (!(*num_bits)) {
  137                 return 0;
  138         }
  139 
  140         max_block = (mdb->fs_ablocks+HFS_BM_BPB-1) / HFS_BM_BPB - 1;
  141         
  142         /* search all bitmap blocks */
  143         for (block_nr = 0; block_nr <= max_block; block_nr++) {
  144                 bitmap = hfs_buffer_data(mdb->bitmap[block_nr]);
  145 
  146                 if (block_nr != max_block) {
  147                         max_bits = HFS_BM_BPB;
  148                 } else {
  149                         max_bits = mdb->fs_ablocks % HFS_BM_BPB;
  150                 }
  151 
  152                 cur_pos = 0;
  153                 do {
  154                         cur_len = hfs_count_zero_bits(bitmap, max_bits,
  155                                                       cur_pos);
  156                         len += cur_len;
  157                         if (len > longest_len) {
  158                                 longest_pos = pos;
  159                                 longest_len = len;
  160                                 if (len >= *num_bits) {
  161                                         goto search_end;
  162                                 }
  163                         }
  164                         if ((cur_pos + cur_len) == max_bits) {
  165                                 break; /* zeros may continue into next block */
  166                         }
  167 
  168                         /* find start of next run of zeros */
  169                         cur_pos = hfs_find_zero_bit(bitmap, max_bits,
  170                                                     cur_pos + cur_len);
  171                         pos = cur_pos + HFS_BM_BPB*block_nr;
  172                         len = 0;
  173                 } while (cur_pos < max_bits);
  174         }
  175 
  176 search_end:
  177         *num_bits = longest_len;
  178         return longest_pos;
  179 }
  180 
  181 
  182 /*
  183  * hfs_set_vbm_bits()
  184  *
  185  * Description:
  186  *   Set the requested bits in the volume bitmap of the hfs filesystem
  187  * Input Variable(s):
  188  *   struct hfs_mdb *mdb: Pointer to the hfs MDB
  189  *   hfs_u16 start: The offset of the first bit
  190  *   hfs_u16 count: The number of bits
  191  * Output Variable(s):
  192  *   None
  193  * Returns:
  194  *    0: no error
  195  *   -1: One of the bits was already set.  This is a strange
  196  *       error and when it happens, the filesystem must be repaired!
  197  *   -2: One or more of the bits are out of range of the bitmap.
  198  *   -3: The 's_magic' field of the MDB does not match
  199  * Preconditions:
  200  *   'mdb' points to a "valid" (struct hfs_mdb).
  201  * Postconditions:
  202  *   Starting with bit number 'start', 'count' bits in the volume bitmap
  203  *   are set. The affected bitmap blocks are marked "dirty", the free
  204  *   block count of the MDB is updated and the MDB is marked dirty.
  205  */
  206 int hfs_set_vbm_bits(struct hfs_mdb *mdb, hfs_u16 start, hfs_u16 count)
  207 {
  208         hfs_u16 block_nr;       /* index of the current bitmap block */
  209         hfs_u16 u32_nr;         /* index of the current hfs_u32 in block */
  210         hfs_u16 bit_nr;         /* index of the current bit in hfs_u32 */
  211         hfs_u16 left = count;   /* number of bits left to be set */
  212         hfs_u32 *bitmap;        /* the current bitmap block's contents */
  213 
  214         /* is this a valid HFS MDB? */
  215         if (!mdb) {
  216                 return -3;
  217         }
  218 
  219         /* is there any actual work to be done? */
  220         if (!count) {
  221                 return 0;
  222         }
  223 
  224         /* are all of the bits in range? */
  225         if ((start + count) > mdb->fs_ablocks) {
  226                 return -2;
  227         }
  228 
  229         block_nr = start / HFS_BM_BPB;
  230         u32_nr = (start % HFS_BM_BPB) / 32;
  231         bit_nr = start % 32;
  232 
  233         /* bitmap is always on a 32-bit boundary */
  234         bitmap = (hfs_u32 *)hfs_buffer_data(mdb->bitmap[block_nr]);
  235 
  236         /* do any partial hfs_u32 at the start */
  237         if (bit_nr != 0) {
  238                 while ((bit_nr < 32) && left) {
  239                         if (hfs_set_bit(bit_nr, bitmap + u32_nr)) {
  240                                 hfs_buffer_dirty(mdb->bitmap[block_nr]);
  241                                 return -1;
  242                         }
  243                         ++bit_nr;
  244                         --left;
  245                 }
  246                 bit_nr=0;
  247 
  248                 /* advance u32_nr and check for end of this block */
  249                 if (++u32_nr > 127) {
  250                         u32_nr = 0;
  251                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  252                         ++block_nr;
  253                         /* bitmap is always on a 32-bit boundary */
  254                         bitmap = (hfs_u32 *)
  255                                         hfs_buffer_data(mdb->bitmap[block_nr]);
  256                 }
  257         }
  258 
  259         /* do full hfs_u32s */
  260         while (left > 31) {
  261                 if (bitmap[u32_nr] != ((hfs_u32)0)) {
  262                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  263                         return -1;
  264                 }
  265                 bitmap[u32_nr] = ~((hfs_u32)0);
  266                 left -= 32;
  267 
  268                 /* advance u32_nr and check for end of this block */
  269                 if (++u32_nr > 127) {
  270                         u32_nr = 0;
  271                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  272                         ++block_nr;
  273                         /* bitmap is always on a 32-bit boundary */
  274                         bitmap = (hfs_u32 *)
  275                                         hfs_buffer_data(mdb->bitmap[block_nr]);
  276                 }
  277         }
  278 
  279                         
  280         /* do any partial hfs_u32 at end */
  281         while (left) {
  282                 if (hfs_set_bit(bit_nr, bitmap + u32_nr)) {
  283                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  284                         return -1;
  285                 }
  286                 ++bit_nr;
  287                 --left;
  288         }
  289 
  290         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  291         mdb->free_ablocks -= count;
  292 
  293         /* successful completion */
  294         hfs_mdb_dirty(mdb->sys_mdb);
  295         return 0;
  296 }
  297 
  298 /*
  299  * hfs_clear_vbm_bits()
  300  *
  301  * Description:
  302  *   Clear the requested bits in the volume bitmap of the hfs filesystem
  303  * Input Variable(s):
  304  *   struct hfs_mdb *mdb: Pointer to the hfs MDB
  305  *   hfs_u16 start: The offset of the first bit
  306  *   hfs_u16 count: The number of bits
  307  * Output Variable(s):
  308  *   None
  309  * Returns:
  310  *    0: no error
  311  *   -1: One of the bits was already clear.  This is a strange
  312  *       error and when it happens, the filesystem must be repaired!
  313  *   -2: One or more of the bits are out of range of the bitmap.
  314  *   -3: The 's_magic' field of the MDB does not match
  315  * Preconditions:
  316  *   'mdb' points to a "valid" (struct hfs_mdb).
  317  * Postconditions:
  318  *   Starting with bit number 'start', 'count' bits in the volume bitmap
  319  *   are cleared. The affected bitmap blocks are marked "dirty", the free
  320  *   block count of the MDB is updated and the MDB is marked dirty.
  321  */
  322 int hfs_clear_vbm_bits(struct hfs_mdb *mdb, hfs_u16 start, hfs_u16 count)
  323 {
  324         hfs_u16 block_nr;       /* index of the current bitmap block */
  325         hfs_u16 u32_nr;         /* index of the current hfs_u32 in block */
  326         hfs_u16 bit_nr;         /* index of the current bit in hfs_u32 */
  327         hfs_u16 left = count;   /* number of bits left to be set */
  328         hfs_u32 *bitmap;        /* the current bitmap block's contents */
  329 
  330         /* is this a valid HFS MDB? */
  331         if (!mdb) {
  332                 return -3;
  333         }
  334 
  335         /* is there any actual work to be done? */
  336         if (!count) {
  337                 return 0;
  338         }
  339 
  340         /* are all of the bits in range? */
  341         if ((start + count) > mdb->fs_ablocks) {
  342                 return -2;
  343         }
  344 
  345         block_nr = start / HFS_BM_BPB;
  346         u32_nr = (start % HFS_BM_BPB) / 32;
  347         bit_nr = start % 32;
  348 
  349         /* bitmap is always on a 32-bit boundary */
  350         bitmap = (hfs_u32 *)hfs_buffer_data(mdb->bitmap[block_nr]);
  351 
  352         /* do any partial hfs_u32 at the start */
  353         if (bit_nr != 0) {
  354                 while ((bit_nr < 32) && left) {
  355                         if (!hfs_clear_bit(bit_nr, bitmap + u32_nr)) {
  356                                 hfs_buffer_dirty(mdb->bitmap[block_nr]);
  357                                 return -1;
  358                         }
  359                         ++bit_nr;
  360                         --left;
  361                 }
  362                 bit_nr=0;
  363 
  364                 /* advance u32_nr and check for end of this block */
  365                 if (++u32_nr > 127) {
  366                         u32_nr = 0;
  367                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  368                         ++block_nr;
  369                         /* bitmap is always on a 32-bit boundary */
  370                         bitmap = (hfs_u32 *)
  371                                         hfs_buffer_data(mdb->bitmap[block_nr]);
  372                 }
  373         }
  374 
  375         /* do full hfs_u32s */
  376         while (left > 31) {
  377                 if (bitmap[u32_nr] != ~((hfs_u32)0)) {
  378                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  379                         return -1;
  380                 }
  381                 bitmap[u32_nr] = ((hfs_u32)0);
  382                 left -= 32;
  383 
  384                 /* advance u32_nr and check for end of this block */
  385                 if (++u32_nr > 127) {
  386                         u32_nr = 0;
  387                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  388                         ++block_nr;
  389                         /* bitmap is always on a 32-bit boundary */
  390                         bitmap = (hfs_u32 *)
  391                                         hfs_buffer_data(mdb->bitmap[block_nr]);
  392                 }
  393         }
  394 
  395                         
  396         /* do any partial hfs_u32 at end */
  397         while (left) {
  398                 if (!hfs_clear_bit(bit_nr, bitmap + u32_nr)) {
  399                         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  400                         return -1;
  401                 }
  402                 ++bit_nr;
  403                 --left;
  404         }
  405 
  406         hfs_buffer_dirty(mdb->bitmap[block_nr]);
  407         mdb->free_ablocks += count;
  408 
  409         /* successful completion */
  410         hfs_mdb_dirty(mdb->sys_mdb);
  411         return 0;
  412 }

Cache object: eb93a0c2b90b19b1078498c375f7eed1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.