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