bitmap.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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