linux/fs/hfsplus/bitmap.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/hfsplus/bitmap.c
   3 *
   4 * Copyright (C) 2001
   5 * Brad Boyer (flar@allandria.com)
   6 * (C) 2003 Ardis Technologies <roman@ardistech.com>
   7 *
   8 * Handling of allocation file
   9 */
  10
  11#include <linux/pagemap.h>
  12
  13#include "hfsplus_fs.h"
  14#include "hfsplus_raw.h"
  15
  16#define PAGE_CACHE_BITS (PAGE_CACHE_SIZE * 8)
  17
  18int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
  19{
  20        struct page *page;
  21        struct address_space *mapping;
  22        __be32 *pptr, *curr, *end;
  23        u32 mask, start, len, n;
  24        __be32 val;
  25        int i;
  26
  27        len = *max;
  28        if (!len)
  29                return size;
  30
  31        dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
  32        mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
  33        mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
  34        page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
  35        pptr = kmap(page);
  36        curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
  37        i = offset % 32;
  38        offset &= ~(PAGE_CACHE_BITS - 1);
  39        if ((size ^ offset) / PAGE_CACHE_BITS)
  40                end = pptr + PAGE_CACHE_BITS / 32;
  41        else
  42                end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
  43
  44        /* scan the first partial u32 for zero bits */
  45        val = *curr;
  46        if (~val) {
  47                n = be32_to_cpu(val);
  48                mask = (1U << 31) >> i;
  49                for (; i < 32; mask >>= 1, i++) {
  50                        if (!(n & mask))
  51                                goto found;
  52                }
  53        }
  54        curr++;
  55
  56        /* scan complete u32s for the first zero bit */
  57        while (1) {
  58                while (curr < end) {
  59                        val = *curr;
  60                        if (~val) {
  61                                n = be32_to_cpu(val);
  62                                mask = 1 << 31;
  63                                for (i = 0; i < 32; mask >>= 1, i++) {
  64                                        if (!(n & mask))
  65                                                goto found;
  66                                }
  67                        }
  68                        curr++;
  69                }
  70                kunmap(page);
  71                offset += PAGE_CACHE_BITS;
  72                if (offset >= size)
  73                        break;
  74                page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
  75                                         NULL);
  76                curr = pptr = kmap(page);
  77                if ((size ^ offset) / PAGE_CACHE_BITS)
  78                        end = pptr + PAGE_CACHE_BITS / 32;
  79                else
  80                        end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
  81        }
  82        dprint(DBG_BITMAP, "bitmap full\n");
  83        start = size;
  84        goto out;
  85
  86found:
  87        start = offset + (curr - pptr) * 32 + i;
  88        if (start >= size) {
  89                dprint(DBG_BITMAP, "bitmap full\n");
  90                goto out;
  91        }
  92        /* do any partial u32 at the start */
  93        len = min(size - start, len);
  94        while (1) {
  95                n |= mask;
  96                if (++i >= 32)
  97                        break;
  98                mask >>= 1;
  99                if (!--len || n & mask)
 100                        goto done;
 101        }
 102        if (!--len)
 103                goto done;
 104        *curr++ = cpu_to_be32(n);
 105        /* do full u32s */
 106        while (1) {
 107                while (curr < end) {
 108                        n = be32_to_cpu(*curr);
 109                        if (len < 32)
 110                                goto last;
 111                        if (n) {
 112                                len = 32;
 113                                goto last;
 114                        }
 115                        *curr++ = cpu_to_be32(0xffffffff);
 116                        len -= 32;
 117                }
 118                set_page_dirty(page);
 119                kunmap(page);
 120                offset += PAGE_CACHE_BITS;
 121                page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
 122                                         NULL);
 123                pptr = kmap(page);
 124                curr = pptr;
 125                end = pptr + PAGE_CACHE_BITS / 32;
 126        }
 127last:
 128        /* do any partial u32 at end */
 129        mask = 1U << 31;
 130        for (i = 0; i < len; i++) {
 131                if (n & mask)
 132                        break;
 133                n |= mask;
 134                mask >>= 1;
 135        }
 136done:
 137        *curr = cpu_to_be32(n);
 138        set_page_dirty(page);
 139        kunmap(page);
 140        *max = offset + (curr - pptr) * 32 + i - start;
 141        HFSPLUS_SB(sb).free_blocks -= *max;
 142        sb->s_dirt = 1;
 143        dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
 144out:
 145        mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
 146        return start;
 147}
 148
 149int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 150{
 151        struct page *page;
 152        struct address_space *mapping;
 153        __be32 *pptr, *curr, *end;
 154        u32 mask, len, pnr;
 155        int i;
 156
 157        /* is there any actual work to be done? */
 158        if (!count)
 159                return 0;
 160
 161        dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
 162        /* are all of the bits in range? */
 163        if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
 164                return -2;
 165
 166        mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
 167        mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
 168        pnr = offset / PAGE_CACHE_BITS;
 169        page = read_mapping_page(mapping, pnr, NULL);
 170        pptr = kmap(page);
 171        curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
 172        end = pptr + PAGE_CACHE_BITS / 32;
 173        len = count;
 174
 175        /* do any partial u32 at the start */
 176        i = offset % 32;
 177        if (i) {
 178                int j = 32 - i;
 179                mask = 0xffffffffU << j;
 180                if (j > count) {
 181                        mask |= 0xffffffffU >> (i + count);
 182                        *curr++ &= cpu_to_be32(mask);
 183                        goto out;
 184                }
 185                *curr++ &= cpu_to_be32(mask);
 186                count -= j;
 187        }
 188
 189        /* do full u32s */
 190        while (1) {
 191                while (curr < end) {
 192                        if (count < 32)
 193                                goto done;
 194                        *curr++ = 0;
 195                        count -= 32;
 196                }
 197                if (!count)
 198                        break;
 199                set_page_dirty(page);
 200                kunmap(page);
 201                page = read_mapping_page(mapping, ++pnr, NULL);
 202                pptr = kmap(page);
 203                curr = pptr;
 204                end = pptr + PAGE_CACHE_BITS / 32;
 205        }
 206done:
 207        /* do any partial u32 at end */
 208        if (count) {
 209                mask = 0xffffffffU >> count;
 210                *curr &= cpu_to_be32(mask);
 211        }
 212out:
 213        set_page_dirty(page);
 214        kunmap(page);
 215        HFSPLUS_SB(sb).free_blocks += len;
 216        sb->s_dirt = 1;
 217        mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
 218
 219        return 0;
 220}
 221