Revision 8f0720ec block.c

b/block.c
1286 1286
    bs_dest->iostatus           = bs_src->iostatus;
1287 1287

  
1288 1288
    /* dirty bitmap */
1289
    bs_dest->dirty_count        = bs_src->dirty_count;
1290 1289
    bs_dest->dirty_bitmap       = bs_src->dirty_bitmap;
1291 1290

  
1292 1291
    /* job */
......
2035 2034
    return ret;
2036 2035
}
2037 2036

  
2038
#define BITS_PER_LONG  (sizeof(unsigned long) * 8)
2039

  
2040
static void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num,
2041
                             int nb_sectors, int dirty)
2042
{
2043
    int64_t start, end;
2044
    unsigned long val, idx, bit;
2045

  
2046
    start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK;
2047
    end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK;
2048

  
2049
    for (; start <= end; start++) {
2050
        idx = start / BITS_PER_LONG;
2051
        bit = start % BITS_PER_LONG;
2052
        val = bs->dirty_bitmap[idx];
2053
        if (dirty) {
2054
            if (!(val & (1UL << bit))) {
2055
                bs->dirty_count++;
2056
                val |= 1UL << bit;
2057
            }
2058
        } else {
2059
            if (val & (1UL << bit)) {
2060
                bs->dirty_count--;
2061
                val &= ~(1UL << bit);
2062
            }
2063
        }
2064
        bs->dirty_bitmap[idx] = val;
2065
    }
2066
}
2067

  
2068 2037
/* Return < 0 if error. Important errors are:
2069 2038
  -EIO         generic I/O error (may happen for all errors)
2070 2039
  -ENOMEDIUM   No media inserted.
......
4173 4142
    }
4174 4143

  
4175 4144
    if (bs->dirty_bitmap) {
4176
        set_dirty_bitmap(bs, sector_num, nb_sectors, 0);
4145
        bdrv_reset_dirty(bs, sector_num, nb_sectors);
4177 4146
    }
4178 4147

  
4179 4148
    if (bs->drv->bdrv_co_discard) {
......
4335 4304
{
4336 4305
    int64_t bitmap_size;
4337 4306

  
4338
    bs->dirty_count = 0;
4339 4307
    if (enable) {
4340 4308
        if (!bs->dirty_bitmap) {
4341
            bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) +
4342
                    BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG - 1;
4343
            bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG;
4344

  
4345
            bs->dirty_bitmap = g_new0(unsigned long, bitmap_size);
4309
            bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
4310
            bs->dirty_bitmap = hbitmap_alloc(bitmap_size,
4311
                                             BDRV_LOG_SECTORS_PER_DIRTY_CHUNK);
4346 4312
        }
4347 4313
    } else {
4348 4314
        if (bs->dirty_bitmap) {
4349
            g_free(bs->dirty_bitmap);
4315
            hbitmap_free(bs->dirty_bitmap);
4350 4316
            bs->dirty_bitmap = NULL;
4351 4317
        }
4352 4318
    }
......
4354 4320

  
4355 4321
int bdrv_get_dirty(BlockDriverState *bs, int64_t sector)
4356 4322
{
4357
    int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
4358

  
4359
    if (bs->dirty_bitmap &&
4360
        (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) {
4361
        return !!(bs->dirty_bitmap[chunk / BITS_PER_LONG] &
4362
            (1UL << (chunk % BITS_PER_LONG)));
4323
    if (bs->dirty_bitmap) {
4324
        return hbitmap_get(bs->dirty_bitmap, sector);
4363 4325
    } else {
4364 4326
        return 0;
4365 4327
    }
4366 4328
}
4367 4329

  
4368
int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector)
4330
void bdrv_dirty_iter_init(BlockDriverState *bs, HBitmapIter *hbi)
4369 4331
{
4370
    int64_t chunk;
4371
    int bit, elem;
4372

  
4373
    /* Avoid an infinite loop.  */
4374
    assert(bs->dirty_count > 0);
4375

  
4376
    sector = (sector | (BDRV_SECTORS_PER_DIRTY_CHUNK - 1)) + 1;
4377
    chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
4378

  
4379
    QEMU_BUILD_BUG_ON(sizeof(bs->dirty_bitmap[0]) * 8 != BITS_PER_LONG);
4380
    elem = chunk / BITS_PER_LONG;
4381
    bit = chunk % BITS_PER_LONG;
4382
    for (;;) {
4383
        if (sector >= bs->total_sectors) {
4384
            sector = 0;
4385
            bit = elem = 0;
4386
        }
4387
        if (bit == 0 && bs->dirty_bitmap[elem] == 0) {
4388
            sector += BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG;
4389
            elem++;
4390
        } else {
4391
            if (bs->dirty_bitmap[elem] & (1UL << bit)) {
4392
                return sector;
4393
            }
4394
            sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
4395
            if (++bit == BITS_PER_LONG) {
4396
                bit = 0;
4397
                elem++;
4398
            }
4399
        }
4400
    }
4332
    hbitmap_iter_init(hbi, bs->dirty_bitmap, 0);
4401 4333
}
4402 4334

  
4403 4335
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
4404 4336
                    int nr_sectors)
4405 4337
{
4406
    set_dirty_bitmap(bs, cur_sector, nr_sectors, 1);
4338
    hbitmap_set(bs->dirty_bitmap, cur_sector, nr_sectors);
4407 4339
}
4408 4340

  
4409 4341
void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
4410 4342
                      int nr_sectors)
4411 4343
{
4412
    set_dirty_bitmap(bs, cur_sector, nr_sectors, 0);
4344
    hbitmap_reset(bs->dirty_bitmap, cur_sector, nr_sectors);
4413 4345
}
4414 4346

  
4415 4347
int64_t bdrv_get_dirty_count(BlockDriverState *bs)
4416 4348
{
4417
    return bs->dirty_count;
4349
    if (bs->dirty_bitmap) {
4350
        return hbitmap_count(bs->dirty_bitmap) >> BDRV_LOG_SECTORS_PER_DIRTY_CHUNK;
4351
    } else {
4352
        return 0;
4353
    }
4418 4354
}
4419 4355

  
4420 4356
void bdrv_set_in_use(BlockDriverState *bs, int in_use)

Also available in: Unified diff