diff --git a/qemu-img.c b/qemu-img.c
index c8a70ff..3fb6cbf 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -629,11 +629,12 @@ static int img_convert(int argc, char **argv)
     int progress = 0, flags;
     const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
     BlockDriver *drv, *proto_drv;
-    BlockDriverState **bs = NULL, *out_bs = NULL;
+    BlockDriverState **bs = NULL, *out_bs = NULL, *out_bf = NULL;
     int64_t total_sectors, nb_sectors, sector_num, bs_offset;
-    uint64_t bs_sectors;
+    uint64_t bf_sectors, bs_sectors;
     uint8_t * buf = NULL;
     const uint8_t *buf1;
+    uint8_t * bf_buf = NULL;
     BlockDriverInfo bdi;
     QEMUOptionParameter *param = NULL, *create_options = NULL;
     QEMUOptionParameter *out_baseimg_param;
@@ -797,6 +798,16 @@ static int img_convert(int argc, char **argv)
     out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
     if (out_baseimg_param) {
         out_baseimg = out_baseimg_param->value.s;
+
+        /* out_baseimg_parm != NULL even if there is no base img specified! */
+        if (out_baseimg) {
+            out_bf = bdrv_new_open(out_baseimg, NULL, BDRV_O_FLAGS);
+            if (!out_bf) {
+                ret = -1;
+                goto out;
+            }
+            bdrv_get_geometry(out_bf, &bf_sectors);
+        }
     }
 
     /* Check if compression is supported */
@@ -862,6 +873,9 @@ static int img_convert(int argc, char **argv)
     bs_offset = 0;
     bdrv_get_geometry(bs[0], &bs_sectors);
     buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
+    if (out_baseimg) {
+        bf_buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
+    }
 
     if (compress) {
         ret = bdrv_get_info(out_bs, &bdi);
@@ -979,31 +993,52 @@ static int img_convert(int argc, char **argv)
                 n = bs_offset + bs_sectors - sector_num;
             }
 
+            ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
+            if (ret < 0) {
+                error_report("error while reading sector %" PRId64 ": %s",
+                             sector_num - bs_offset, strerror(-ret));
+                goto out;
+            }
+	 
             if (has_zero_init) {
                 /* If the output image is being created as a copy on write image,
-                   assume that sectors which are unallocated in the input image
-                   are present in both the output's and input's base images (no
-                   need to copy them). */
+                   check that sectors which are unallocated in the input image
+                   are present in both the output's and input's base images (or 
+                   copy them). */
                 if (out_baseimg) {
-                    if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
-                                           n, &n1)) {
-                        sector_num += n1;
-                        continue;
+                    if (sector_num < bf_sectors) {
+                        /* Check if source sectors match those in the new backing file and
+                           skip the copy if true. */
+                        n = MIN(n, bf_sectors - sector_num);
+                        ret = bdrv_read(out_bf, sector_num - bs_offset, bf_buf, n);
+                        if (ret < 0) {
+                            error_report("error while reading backing file");
+                            goto out;
+                        }
+                        if (!compare_sectors(buf, bf_buf, n, &n1)) {
+                            sector_num += n1;
+                            continue;
+                        }
+ 
+                    } else {
+                        /* Source file(s) is larger than the backing file. Just check for
+                           allocated sectors */
+                        if (!is_allocated_sectors_min(buf, n, &n1, min_sparse)) {
+                            /* if we got zero, how many of the next ones are zero? */
+                            is_allocated_sectors(buf, n, &n1);
+                            sector_num += n1;
+                            continue;
+                        }
                     }
-                    /* The next 'n1' sectors are allocated in the input image. Copy
-                       only those as they may be followed by unallocated sectors. */
+                    /* The next 'n1' sectors are allocated in the input image or the
+                       backing files are different. Copy only those as they may be 
+                       followed by unallocated sectors. */
                     n = n1;
                 }
             } else {
                 n1 = n;
             }
 
-            ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
-            if (ret < 0) {
-                error_report("error while reading sector %" PRId64 ": %s",
-                             sector_num - bs_offset, strerror(-ret));
-                goto out;
-            }
             /* NOTE: at the same time we convert, we do not write zero
                sectors to have a chance to compress the image. Ideally, we
                should add a specific call to have the info to go faster */
@@ -1037,6 +1072,7 @@ out:
     free_option_parameters(create_options);
     free_option_parameters(param);
     qemu_vfree(buf);
+    qemu_vfree(bf_buf);
     if (out_bs) {
         bdrv_delete(out_bs);
     }
@@ -1048,6 +1084,10 @@ out:
         }
         g_free(bs);
     }
+    if (out_bf) {
+        bdrv_delete(out_bf);
+    }
+
     if (ret) {
         return 1;
     }
