^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) * linux/fs/hfs/bitmap.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) * Copyright (C) 1996-1997 Paul H. Hargrove
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * (C) 2003 Ardis Technologies <roman@ardistech.com>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * This file may be distributed under the terms of the GNU General Public License.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * Based on GPLed code Copyright (C) 1995 Michael Dreher
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) * This file contains the code to modify the volume bitmap:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) * search/set/clear bits.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include "hfs_fs.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) * hfs_find_zero_bit()
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) * Description:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) * Given a block of memory, its length in bits, and a starting bit number,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) * determine the number of the first zero bits (in left-to-right ordering)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) * in that range.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) * Returns >= 'size' if no zero bits are found in the range.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) * Accesses memory in 32-bit aligned chunks of 32-bits and thus
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) * may read beyond the 'size'th bit.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) static u32 hfs_find_set_zero_bits(__be32 *bitmap, u32 size, u32 offset, u32 *max)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) __be32 *curr, *end;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) u32 mask, start, len, n;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) __be32 val;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) int i;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) len = *max;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37) if (!len)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 38) return size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) curr = bitmap + (offset / 32);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41) end = bitmap + ((size + 31) / 32);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43) /* scan the first partial u32 for zero bits */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) val = *curr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) if (~val) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) n = be32_to_cpu(val);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) i = offset % 32;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) mask = (1U << 31) >> i;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) for (; i < 32; mask >>= 1, i++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) if (!(n & mask))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 51) goto found;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 53) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 55) /* scan complete u32s for the first zero bit */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56) while (++curr < end) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 57) val = *curr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 58) if (~val) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 59) n = be32_to_cpu(val);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) mask = 1 << 31;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61) for (i = 0; i < 32; mask >>= 1, i++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) if (!(n & mask))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 63) goto found;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 67) return size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) found:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) start = (curr - bitmap) * 32 + i;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) if (start >= size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) return start;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) /* do any partial u32 at the start */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) len = min(size - start, len);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75) while (1) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) n |= mask;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) if (++i >= 32)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 78) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 79) mask >>= 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) if (!--len || n & mask)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 81) goto done;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 82) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 83) if (!--len)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 84) goto done;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 85) *curr++ = cpu_to_be32(n);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 86) /* do full u32s */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 87) while (1) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88) n = be32_to_cpu(*curr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 89) if (len < 32)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 90) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 91) if (n) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 92) len = 32;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 93) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 94) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 95) *curr++ = cpu_to_be32(0xffffffff);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 96) len -= 32;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 97) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 98) /* do any partial u32 at end */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99) mask = 1U << 31;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 100) for (i = 0; i < len; i++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 101) if (n & mask)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 102) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 103) n |= mask;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 104) mask >>= 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 105) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 106) done:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 107) *curr = cpu_to_be32(n);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 108) *max = (curr - bitmap) * 32 + i - start;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 109) return start;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 110) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 111)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 112) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113) * hfs_vbm_search_free()
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 114) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115) * Description:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 116) * Search for 'num_bits' consecutive cleared bits in the bitmap blocks of
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 117) * the hfs MDB. 'mdb' had better be locked or the returned range
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) * may be no longer free, when this functions returns!
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119) * XXX Currently the search starts from bit 0, but it should start with
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 120) * the bit number stored in 's_alloc_ptr' of the MDB.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 121) * Input Variable(s):
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 122) * struct hfs_mdb *mdb: Pointer to the hfs MDB
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 123) * u16 *num_bits: Pointer to the number of cleared bits
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 124) * to search for
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 125) * Output Variable(s):
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 126) * u16 *num_bits: The number of consecutive clear bits of the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 127) * returned range. If the bitmap is fragmented, this will be less than
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) * requested and it will be zero, when the disk is full.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 129) * Returns:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130) * The number of the first bit of the range of cleared bits which has been
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 131) * found. When 'num_bits' is zero, this is invalid!
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 132) * Preconditions:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 133) * 'mdb' points to a "valid" (struct hfs_mdb).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134) * 'num_bits' points to a variable of type (u16), which contains
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 135) * the number of cleared bits to find.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 136) * Postconditions:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 137) * 'num_bits' is set to the length of the found sequence.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 138) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 139) u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 140) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 141) void *bitmap;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142) u32 pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 143)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144) /* make sure we have actual work to perform */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 145) if (!*num_bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 146) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 147)
3084b72de73a6 (Matthias Kaehlcke 2008-07-25 01:46:34 -0700 148) mutex_lock(&HFS_SB(sb)->bitmap_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 149) bitmap = HFS_SB(sb)->bitmap;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 150)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 151) pos = hfs_find_set_zero_bits(bitmap, HFS_SB(sb)->fs_ablocks, goal, num_bits);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 152) if (pos >= HFS_SB(sb)->fs_ablocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 153) if (goal)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 154) pos = hfs_find_set_zero_bits(bitmap, goal, 0, num_bits);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155) if (pos >= HFS_SB(sb)->fs_ablocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 156) *num_bits = pos = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 158) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 159) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160)
c2b3e1f76e5c9 (Joe Perches 2013-04-30 15:27:54 -0700 161) hfs_dbg(BITMAP, "alloc_bits: %u,%u\n", pos, *num_bits);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 162) HFS_SB(sb)->free_ablocks -= *num_bits;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163) hfs_bitmap_dirty(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) out:
3084b72de73a6 (Matthias Kaehlcke 2008-07-25 01:46:34 -0700 165) mutex_unlock(&HFS_SB(sb)->bitmap_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166) return pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 171) * hfs_clear_vbm_bits()
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173) * Description:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) * Clear the requested bits in the volume bitmap of the hfs filesystem
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 175) * Input Variable(s):
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 176) * struct hfs_mdb *mdb: Pointer to the hfs MDB
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 177) * u16 start: The offset of the first bit
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 178) * u16 count: The number of bits
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 179) * Output Variable(s):
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 180) * None
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 181) * Returns:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 182) * 0: no error
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 183) * -1: One of the bits was already clear. This is a strange
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) * error and when it happens, the filesystem must be repaired!
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 185) * -2: One or more of the bits are out of range of the bitmap.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 186) * Preconditions:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 187) * 'mdb' points to a "valid" (struct hfs_mdb).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 188) * Postconditions:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 189) * Starting with bit number 'start', 'count' bits in the volume bitmap
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 190) * are cleared. The affected bitmap blocks are marked "dirty", the free
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 191) * block count of the MDB is updated and the MDB is marked dirty.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 192) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193) int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 194) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 195) __be32 *curr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 196) u32 mask;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 197) int i, len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 199) /* is there any actual work to be done? */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 200) if (!count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202)
c2b3e1f76e5c9 (Joe Perches 2013-04-30 15:27:54 -0700 203) hfs_dbg(BITMAP, "clear_bits: %u,%u\n", start, count);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204) /* are all of the bits in range? */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 205) if ((start + count) > HFS_SB(sb)->fs_ablocks)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 206) return -2;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207)
3084b72de73a6 (Matthias Kaehlcke 2008-07-25 01:46:34 -0700 208) mutex_lock(&HFS_SB(sb)->bitmap_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209) /* bitmap is always on a 32-bit boundary */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 210) curr = HFS_SB(sb)->bitmap + (start / 32);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 211) len = count;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 212)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 213) /* do any partial u32 at the start */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 214) i = start % 32;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 215) if (i) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 216) int j = 32 - i;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) mask = 0xffffffffU << j;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) if (j > count) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 219) mask |= 0xffffffffU >> (i + count);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220) *curr &= cpu_to_be32(mask);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) *curr++ &= cpu_to_be32(mask);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224) count -= j;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 226)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 227) /* do full u32s */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 228) while (count >= 32) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229) *curr++ = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 230) count -= 32;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 231) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 232) /* do any partial u32 at end */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) if (count) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234) mask = 0xffffffffU >> count;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) *curr &= cpu_to_be32(mask);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 238) HFS_SB(sb)->free_ablocks += len;
3084b72de73a6 (Matthias Kaehlcke 2008-07-25 01:46:34 -0700 239) mutex_unlock(&HFS_SB(sb)->bitmap_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) hfs_bitmap_dirty(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243) }