vvfat: Use BdrvChild for s->qcow
vvfat uses a temporary qcow file to cache written data in read-write mode. In order to do things properly, this should show up in the BDS graph and I/O should go through BdrvChild like for every other node. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
		
							parent
							
								
									a9d52a7563
								
							
						
					
					
						commit
						eecc77473b
					
				|  | @ -341,9 +341,8 @@ typedef struct BDRVVVFATState { | ||||||
|     unsigned int current_cluster; |     unsigned int current_cluster; | ||||||
| 
 | 
 | ||||||
|     /* write support */ |     /* write support */ | ||||||
|     BlockDriverState* write_target; |  | ||||||
|     char* qcow_filename; |     char* qcow_filename; | ||||||
|     BlockDriverState* qcow; |     BdrvChild* qcow; | ||||||
|     void* fat2; |     void* fat2; | ||||||
|     char* used_clusters; |     char* used_clusters; | ||||||
|     array_t commits; |     array_t commits; | ||||||
|  | @ -981,7 +980,7 @@ static int init_directories(BDRVVVFATState* s, | ||||||
| static BDRVVVFATState *vvv = NULL; | static BDRVVVFATState *vvv = NULL; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| static int enable_write_target(BDRVVVFATState *s, Error **errp); | static int enable_write_target(BlockDriverState *bs, Error **errp); | ||||||
| static int is_consistent(BDRVVVFATState *s); | static int is_consistent(BDRVVVFATState *s); | ||||||
| 
 | 
 | ||||||
| static QemuOptsList runtime_opts = { | static QemuOptsList runtime_opts = { | ||||||
|  | @ -1159,7 +1158,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, | ||||||
| 
 | 
 | ||||||
|     /* read only is the default for safety */ |     /* read only is the default for safety */ | ||||||
|     bs->read_only = true; |     bs->read_only = true; | ||||||
|     s->qcow = s->write_target = NULL; |     s->qcow = NULL; | ||||||
|     s->qcow_filename = NULL; |     s->qcow_filename = NULL; | ||||||
|     s->fat2 = NULL; |     s->fat2 = NULL; | ||||||
|     s->downcase_short_names = 1; |     s->downcase_short_names = 1; | ||||||
|  | @ -1170,7 +1169,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, | ||||||
|     s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1); |     s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1); | ||||||
| 
 | 
 | ||||||
|     if (qemu_opt_get_bool(opts, "rw", false)) { |     if (qemu_opt_get_bool(opts, "rw", false)) { | ||||||
|         ret = enable_write_target(s, errp); |         ret = enable_write_target(bs, errp); | ||||||
|         if (ret < 0) { |         if (ret < 0) { | ||||||
|             goto fail; |             goto fail; | ||||||
|         } |         } | ||||||
|  | @ -1391,9 +1390,10 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num, | ||||||
| 	   return -1; | 	   return -1; | ||||||
| 	if (s->qcow) { | 	if (s->qcow) { | ||||||
| 	    int n; | 	    int n; | ||||||
|             if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) { |             if (bdrv_is_allocated(s->qcow->bs, sector_num, nb_sectors-i, &n)) { | ||||||
| DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n)); |                 DLOG(fprintf(stderr, "sectors %d+%d allocated\n", | ||||||
|                 if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) { |                              (int)sector_num, n)); | ||||||
|  |                 if (bdrv_read(s->qcow->bs, sector_num, buf + i * 0x200, n)) { | ||||||
|                     return -1; |                     return -1; | ||||||
|                 } |                 } | ||||||
|                 i += n - 1; |                 i += n - 1; | ||||||
|  | @ -1669,12 +1669,15 @@ static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num) | ||||||
|     int was_modified = 0; |     int was_modified = 0; | ||||||
|     int i, dummy; |     int i, dummy; | ||||||
| 
 | 
 | ||||||
|     if (s->qcow == NULL) |     if (s->qcow == NULL) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) |     for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) { | ||||||
| 	was_modified = bdrv_is_allocated(s->qcow, |         was_modified = bdrv_is_allocated(s->qcow->bs, | ||||||
| 		cluster2sector(s, cluster_num) + i, 1, &dummy); |                                          cluster2sector(s, cluster_num) + i, | ||||||
|  |                                          1, &dummy); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return was_modified; |     return was_modified; | ||||||
| } | } | ||||||
|  | @ -1823,11 +1826,17 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s, | ||||||
| 
 | 
 | ||||||
| 		vvfat_close_current_file(s); | 		vvfat_close_current_file(s); | ||||||
|                 for (i = 0; i < s->sectors_per_cluster; i++) { |                 for (i = 0; i < s->sectors_per_cluster; i++) { | ||||||
|                     if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) { |                     int res; | ||||||
|                         if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) { | 
 | ||||||
|  |                     res = bdrv_is_allocated(s->qcow->bs, offset + i, 1, &dummy); | ||||||
|  |                     if (!res) { | ||||||
|  |                         res = vvfat_read(s->bs, offset, s->cluster_buffer, 1); | ||||||
|  |                         if (res) { | ||||||
|                             return -1; |                             return -1; | ||||||
|                         } |                         } | ||||||
|                         if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) { |                         res = bdrv_write(s->qcow->bs, offset, | ||||||
|  |                                          s->cluster_buffer, 1); | ||||||
|  |                         if (res) { | ||||||
|                             return -2; |                             return -2; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  | @ -2783,8 +2792,8 @@ static int do_commit(BDRVVVFATState* s) | ||||||
| 	return ret; | 	return ret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (s->qcow->drv->bdrv_make_empty) { |     if (s->qcow->bs->drv->bdrv_make_empty) { | ||||||
|         s->qcow->drv->bdrv_make_empty(s->qcow); |         s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     memset(s->used_clusters, 0, sector2cluster(s, s->sector_count)); |     memset(s->used_clusters, 0, sector2cluster(s, s->sector_count)); | ||||||
|  | @ -2880,7 +2889,7 @@ DLOG(checkpoint()); | ||||||
|      * Use qcow backend. Commit later. |      * Use qcow backend. Commit later. | ||||||
|      */ |      */ | ||||||
| DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors)); | DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors)); | ||||||
|     ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors); |     ret = bdrv_write(s->qcow->bs, sector_num, buf, nb_sectors); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
| 	fprintf(stderr, "Error writing to qcow backend\n"); | 	fprintf(stderr, "Error writing to qcow backend\n"); | ||||||
| 	return ret; | 	return ret; | ||||||
|  | @ -2950,7 +2959,7 @@ write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes, | ||||||
| 
 | 
 | ||||||
| static void write_target_close(BlockDriverState *bs) { | static void write_target_close(BlockDriverState *bs) { | ||||||
|     BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque); |     BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque); | ||||||
|     bdrv_unref(s->qcow); |     bdrv_unref_child(s->bs, s->qcow); | ||||||
|     g_free(s->qcow_filename); |     g_free(s->qcow_filename); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2960,8 +2969,19 @@ static BlockDriver vvfat_write_target = { | ||||||
|     .bdrv_close         = write_target_close, |     .bdrv_close         = write_target_close, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int enable_write_target(BDRVVVFATState *s, Error **errp) | static void vvfat_qcow_options(int *child_flags, QDict *child_options, | ||||||
|  |                                int parent_flags, QDict *parent_options) | ||||||
| { | { | ||||||
|  |     *child_flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const BdrvChildRole child_vvfat_qcow = { | ||||||
|  |     .inherit_options    = vvfat_qcow_options, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int enable_write_target(BlockDriverState *bs, Error **errp) | ||||||
|  | { | ||||||
|  |     BDRVVVFATState *s = bs->opaque; | ||||||
|     BlockDriver *bdrv_qcow = NULL; |     BlockDriver *bdrv_qcow = NULL; | ||||||
|     BlockDriverState *backing; |     BlockDriverState *backing; | ||||||
|     QemuOpts *opts = NULL; |     QemuOpts *opts = NULL; | ||||||
|  | @ -3000,8 +3020,8 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp) | ||||||
| 
 | 
 | ||||||
|     options = qdict_new(); |     options = qdict_new(); | ||||||
|     qdict_put(options, "driver", qstring_from_str("qcow")); |     qdict_put(options, "driver", qstring_from_str("qcow")); | ||||||
|     s->qcow = bdrv_open(s->qcow_filename, NULL, options, |     s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs, | ||||||
|                         BDRV_O_RDWR | BDRV_O_NO_FLUSH, errp); |                               &child_vvfat_qcow, false, errp); | ||||||
|     if (!s->qcow) { |     if (!s->qcow) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto err; |         goto err; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Kevin Wolf
						Kevin Wolf