[Qemu-devel] [PATCH 2/2] iscsi: add intelligent has_zero_init check
iscsi targets are not created by bdrv_create and thus we cannot blindly assume that a target is empty. to avoid writing and allocating blocks of zeroes we now check if all blocks of an existing target are unallocated and return 1 for bdrv_has_zero_init if the target is completely unalloacted and unallocated blocks read as zeroes. Signed-off-by: Peter Lieven --- block/iscsi.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/block/iscsi.c b/block/iscsi.c index e6b966d..fe41d9a 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -50,6 +50,7 @@ typedef struct IscsiLun { int events; QEMUTimer *nop_timer; uint8_t lbpme; +uint8_t lbprz; } IscsiLun; typedef struct IscsiAIOCB { @@ -1004,6 +1005,7 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun) iscsilun->block_size = rc16->block_length; iscsilun->num_blocks = rc16->returned_lba + 1; iscsilun->lbpme = rc16->lbpme; +iscsilun->lbprz = rc16->lbprz; } } break; @@ -1249,7 +1251,28 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset) static int iscsi_has_zero_init(BlockDriverState *bs) { -return 0; +IscsiLun *iscsilun = bs->opaque; +uint64_t lba; +int n, ret, nb_sectors; + +if (iscsilun->lbprz == 0) { +return 0; +} + +for (lba = 0; lba < iscsilun->num_blocks; lba += 1 << 26) { +nb_sectors = 1 << 26; +if (lba + nb_sectors > iscsilun->num_blocks) { +nb_sectors = iscsilun->num_blocks - lba; +} +nb_sectors *= (iscsilun->block_size / BDRV_SECTOR_SIZE); +n = 0; +ret = iscsi_co_is_allocated(bs, lba, nb_sectors, &n); +if (ret || n != nb_sectors) { +return 0; +} +} + +return 1; } static int iscsi_create(const char *filename, QEMUOptionParameter *options) -- 1.7.9.5
[Qemu-devel] [PATCH 2/2] iscsi: add intelligent has_zero_init check
iscsi targets are not created by bdrv_create and thus we cannot blindly assume that a target is empty. to avoid writing and allocating blocks of zeroes we now check if all blocks of an existing target are unallocated and return 1 for bdrv_has_zero_init if the target is completely unalloacted and unallocated blocks read as zeroes. Signed-off-by: Peter Lieven --- block/iscsi.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/block/iscsi.c b/block/iscsi.c index e6b966d..fe41d9a 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -50,6 +50,7 @@ typedef struct IscsiLun { int events; QEMUTimer *nop_timer; uint8_t lbpme; +uint8_t lbprz; } IscsiLun; typedef struct IscsiAIOCB { @@ -1004,6 +1005,7 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun) iscsilun->block_size = rc16->block_length; iscsilun->num_blocks = rc16->returned_lba + 1; iscsilun->lbpme = rc16->lbpme; +iscsilun->lbprz = rc16->lbprz; } } break; @@ -1249,7 +1251,28 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset) static int iscsi_has_zero_init(BlockDriverState *bs) { -return 0; +IscsiLun *iscsilun = bs->opaque; +uint64_t lba; +int n, ret, nb_sectors; + +if (iscsilun->lbprz == 0) { +return 0; +} + +for (lba = 0; lba < iscsilun->num_blocks; lba += 1 << 26) { +nb_sectors = 1 << 26; +if (lba + nb_sectors > iscsilun->num_blocks) { +nb_sectors = iscsilun->num_blocks - lba; +} +nb_sectors *= (iscsilun->block_size / BDRV_SECTOR_SIZE); +n = 0; +ret = iscsi_co_is_allocated(bs, lba, nb_sectors, &n); +if (ret || n != nb_sectors) { +return 0; +} +} + +return 1; } static int iscsi_create(const char *filename, QEMUOptionParameter *options) -- 1.7.9.5
Re: [Qemu-devel] [PATCH 2/2] iscsi: add intelligent has_zero_init check
Il 20/06/2013 20:20, Peter Lieven ha scritto: > +for (lba = 0; lba < iscsilun->num_blocks; lba += 1 << 26) { > +nb_sectors = 1 << 26; > +if (lba + nb_sectors > iscsilun->num_blocks) { > +nb_sectors = iscsilun->num_blocks - lba; > +} > +nb_sectors *= (iscsilun->block_size / BDRV_SECTOR_SIZE); > +n = 0; > +ret = iscsi_co_is_allocated(bs, lba, nb_sectors, &n); > +if (ret || n != nb_sectors) { > +return 0; > +} I would just do lba += n in the for loop, and only exit if n == 0. The SCSI spec does not forbid splitting a single allocated area into multiple descriptors, or only returning part of an allocated area into the last descriptor. Otherwise looks good, but you may want to cache the result. It would not be 1 anymore after the first write. Paolo
Re: [Qemu-devel] [PATCH 2/2] iscsi: add intelligent has_zero_init check
Von meinem iPhone gesendet Am 21.06.2013 um 22:00 schrieb Paolo Bonzini : > Il 20/06/2013 20:20, Peter Lieven ha scritto: >> +for (lba = 0; lba < iscsilun->num_blocks; lba += 1 << 26) { >> +nb_sectors = 1 << 26; >> +if (lba + nb_sectors > iscsilun->num_blocks) { >> +nb_sectors = iscsilun->num_blocks - lba; >> +} >> +nb_sectors *= (iscsilun->block_size / BDRV_SECTOR_SIZE); >> +n = 0; >> +ret = iscsi_co_is_allocated(bs, lba, nb_sectors, &n); >> +if (ret || n != nb_sectors) { >> +return 0; >> +} > > I would just do lba += n in the for loop, and only exit if n == 0. The > SCSI spec does not forbid splitting a single allocated area into > multiple descriptors, or only returning part of an allocated area into > the last descriptor. > > Otherwise looks good, but you may want to cache the result. It would > not be 1 anymore after the first write. > Of course, but after some discussions with Kevin we might have found a better Solution than extending has_zero_init this far. Let you know soon :-) > Paolo