block/parallels: add backing support to readv/writev
Since parallels format supports backing files, refine readv/writev (allocate_clusters) to redirect read/write requests to a backing file (if cluster is not available in the current bs). Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Signed-off-by: Denis V. Lunev <den@openvz.org> Signed-off-by: Klim Kireev <klim.kireev@virtuozzo.com> Message-id: 20180112090122.1702-6-klim.kireev@virtuozzo.com CC: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
		
							parent
							
								
									908b1c848e
								
							
						
					
					
						commit
						bcbb3866da
					
				@ -142,6 +142,7 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
 | 
				
			|||||||
static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
 | 
					static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
 | 
				
			||||||
                                 int nb_sectors, int *pnum)
 | 
					                                 int nb_sectors, int *pnum)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
    BDRVParallelsState *s = bs->opaque;
 | 
					    BDRVParallelsState *s = bs->opaque;
 | 
				
			||||||
    int64_t pos, space, idx, to_allocate, i, len;
 | 
					    int64_t pos, space, idx, to_allocate, i, len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -170,7 +171,6 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
        return len;
 | 
					        return len;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (s->data_end + space > (len >> BDRV_SECTOR_BITS)) {
 | 
					    if (s->data_end + space > (len >> BDRV_SECTOR_BITS)) {
 | 
				
			||||||
        int ret;
 | 
					 | 
				
			||||||
        space += s->prealloc_size;
 | 
					        space += s->prealloc_size;
 | 
				
			||||||
        if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
 | 
					        if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
 | 
				
			||||||
            ret = bdrv_pwrite_zeroes(bs->file,
 | 
					            ret = bdrv_pwrite_zeroes(bs->file,
 | 
				
			||||||
@ -186,6 +186,37 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Try to read from backing to fill empty clusters
 | 
				
			||||||
 | 
					     * FIXME: 1. previous write_zeroes may be redundant
 | 
				
			||||||
 | 
					     *        2. most of data we read from backing will be rewritten by
 | 
				
			||||||
 | 
					     *           parallels_co_writev. On aligned-to-cluster write we do not need
 | 
				
			||||||
 | 
					     *           this read at all.
 | 
				
			||||||
 | 
					     *        3. it would be good to combine write of data from backing and new
 | 
				
			||||||
 | 
					     *           data into one write call */
 | 
				
			||||||
 | 
					    if (bs->backing) {
 | 
				
			||||||
 | 
					        int64_t nb_cow_sectors = to_allocate * s->tracks;
 | 
				
			||||||
 | 
					        int64_t nb_cow_bytes = nb_cow_sectors << BDRV_SECTOR_BITS;
 | 
				
			||||||
 | 
					        QEMUIOVector qiov;
 | 
				
			||||||
 | 
					        struct iovec iov = {
 | 
				
			||||||
 | 
					            .iov_len = nb_cow_bytes,
 | 
				
			||||||
 | 
					            .iov_base = qemu_blockalign(bs, nb_cow_bytes)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        qemu_iovec_init_external(&qiov, &iov, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ret = bdrv_co_readv(bs->backing, idx * s->tracks, nb_cow_sectors,
 | 
				
			||||||
 | 
					                            &qiov);
 | 
				
			||||||
 | 
					        if (ret < 0) {
 | 
				
			||||||
 | 
					            qemu_vfree(iov.iov_base);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ret = bdrv_co_writev(bs->file, s->data_end, nb_cow_sectors, &qiov);
 | 
				
			||||||
 | 
					        qemu_vfree(iov.iov_base);
 | 
				
			||||||
 | 
					        if (ret < 0) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < to_allocate; i++) {
 | 
					    for (i = 0; i < to_allocate; i++) {
 | 
				
			||||||
        s->bat_bitmap[idx + i] = cpu_to_le32(s->data_end / s->off_multiplier);
 | 
					        s->bat_bitmap[idx + i] = cpu_to_le32(s->data_end / s->off_multiplier);
 | 
				
			||||||
        s->data_end += s->tracks;
 | 
					        s->data_end += s->tracks;
 | 
				
			||||||
@ -309,12 +340,19 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        nbytes = n << BDRV_SECTOR_BITS;
 | 
					        nbytes = n << BDRV_SECTOR_BITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (position < 0) {
 | 
					        qemu_iovec_reset(&hd_qiov);
 | 
				
			||||||
            qemu_iovec_memset(qiov, bytes_done, 0, nbytes);
 | 
					        qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            qemu_iovec_reset(&hd_qiov);
 | 
					 | 
				
			||||||
            qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (position < 0) {
 | 
				
			||||||
 | 
					            if (bs->backing) {
 | 
				
			||||||
 | 
					                ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
 | 
				
			||||||
 | 
					                if (ret < 0) {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                qemu_iovec_memset(&hd_qiov, 0, 0, nbytes);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
 | 
					            ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
 | 
				
			||||||
            if (ret < 0) {
 | 
					            if (ret < 0) {
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
@ -748,7 +786,7 @@ static BlockDriver bdrv_parallels = {
 | 
				
			|||||||
    .bdrv_co_flush_to_os      = parallels_co_flush_to_os,
 | 
					    .bdrv_co_flush_to_os      = parallels_co_flush_to_os,
 | 
				
			||||||
    .bdrv_co_readv  = parallels_co_readv,
 | 
					    .bdrv_co_readv  = parallels_co_readv,
 | 
				
			||||||
    .bdrv_co_writev = parallels_co_writev,
 | 
					    .bdrv_co_writev = parallels_co_writev,
 | 
				
			||||||
 | 
					    .supports_backing = true,
 | 
				
			||||||
    .bdrv_create    = parallels_create,
 | 
					    .bdrv_create    = parallels_create,
 | 
				
			||||||
    .bdrv_check     = parallels_check,
 | 
					    .bdrv_check     = parallels_check,
 | 
				
			||||||
    .create_opts    = ¶llels_create_opts,
 | 
					    .create_opts    = ¶llels_create_opts,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user