[Qemu-devel] [PATCH 2/2] iscsi: add intelligent has_zero_init check

2013-06-20 Thread Peter Lieven
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

2013-06-20 Thread Peter Lieven
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

2013-06-21 Thread 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.

Paolo



Re: [Qemu-devel] [PATCH 2/2] iscsi: add intelligent has_zero_init check

2013-06-21 Thread Peter Lieven


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