@@ -1604,14 +1604,24 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
1604
1604
is_request_serialising_and_aligned (req ));
1605
1605
assert (req -> overlap_offset <= offset );
1606
1606
assert (offset + bytes <= req -> overlap_offset + req -> overlap_bytes );
1607
+ assert (end_sector <= bs -> total_sectors || child -> perm & BLK_PERM_RESIZE );
1607
1608
1608
- if (flags & BDRV_REQ_WRITE_UNCHANGED ) {
1609
- assert (child -> perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE ));
1610
- } else {
1611
- assert (child -> perm & BLK_PERM_WRITE );
1609
+ switch (req -> type ) {
1610
+ case BDRV_TRACKED_WRITE :
1611
+ case BDRV_TRACKED_DISCARD :
1612
+ if (flags & BDRV_REQ_WRITE_UNCHANGED ) {
1613
+ assert (child -> perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE ));
1614
+ } else {
1615
+ assert (child -> perm & BLK_PERM_WRITE );
1616
+ }
1617
+ return notifier_with_return_list_notify (& bs -> before_write_notifiers ,
1618
+ req );
1619
+ case BDRV_TRACKED_TRUNCATE :
1620
+ assert (child -> perm & BLK_PERM_RESIZE );
1621
+ return 0 ;
1622
+ default :
1623
+ abort ();
1612
1624
}
1613
- assert (end_sector <= bs -> total_sectors || child -> perm & BLK_PERM_RESIZE );
1614
- return notifier_with_return_list_notify (& bs -> before_write_notifiers , req );
1615
1625
}
1616
1626
1617
1627
static inline void coroutine_fn
@@ -1631,8 +1641,9 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
1631
1641
* beyond EOF cannot expand the image anyway.
1632
1642
*/
1633
1643
if (ret == 0 &&
1634
- end_sector > bs -> total_sectors &&
1635
- req -> type != BDRV_TRACKED_DISCARD ) {
1644
+ (req -> type == BDRV_TRACKED_TRUNCATE ||
1645
+ end_sector > bs -> total_sectors ) &&
1646
+ req -> type != BDRV_TRACKED_DISCARD ) {
1636
1647
bs -> total_sectors = end_sector ;
1637
1648
bdrv_parent_cb_resize (bs );
1638
1649
bdrv_dirty_bitmap_truncate (bs , end_sector << BDRV_SECTOR_BITS );
@@ -3111,7 +3122,6 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
3111
3122
int64_t old_size , new_bytes ;
3112
3123
int ret ;
3113
3124
3114
- assert (child -> perm & BLK_PERM_RESIZE );
3115
3125
3116
3126
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
3117
3127
if (!drv ) {
@@ -3144,7 +3154,18 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
3144
3154
* concurrently or they might be overwritten by preallocation. */
3145
3155
if (new_bytes ) {
3146
3156
mark_request_serialising (& req , 1 );
3147
- wait_serialising_requests (& req );
3157
+ }
3158
+ if (bs -> read_only ) {
3159
+ error_setg (errp , "Image is read-only" );
3160
+ ret = - EACCES ;
3161
+ goto out ;
3162
+ }
3163
+ ret = bdrv_co_write_req_prepare (child , offset - new_bytes , new_bytes , & req ,
3164
+ 0 );
3165
+ if (ret < 0 ) {
3166
+ error_setg_errno (errp , - ret ,
3167
+ "Failed to prepare request for truncation" );
3168
+ goto out ;
3148
3169
}
3149
3170
3150
3171
if (!drv -> bdrv_co_truncate ) {
@@ -3156,13 +3177,6 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
3156
3177
ret = - ENOTSUP ;
3157
3178
goto out ;
3158
3179
}
3159
- if (bs -> read_only ) {
3160
- error_setg (errp , "Image is read-only" );
3161
- ret = - EACCES ;
3162
- goto out ;
3163
- }
3164
-
3165
- assert (!(bs -> open_flags & BDRV_O_INACTIVE ));
3166
3180
3167
3181
ret = drv -> bdrv_co_truncate (bs , offset , prealloc , errp );
3168
3182
if (ret < 0 ) {
@@ -3174,9 +3188,10 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
3174
3188
} else {
3175
3189
offset = bs -> total_sectors * BDRV_SECTOR_SIZE ;
3176
3190
}
3177
- bdrv_dirty_bitmap_truncate (bs , offset );
3178
- bdrv_parent_cb_resize (bs );
3179
- atomic_inc (& bs -> write_gen );
3191
+ /* It's possible that truncation succeeded but refresh_total_sectors
3192
+ * failed, but the latter doesn't affect how we should finish the request.
3193
+ * Pass 0 as the last parameter so that dirty bitmaps etc. are handled. */
3194
+ bdrv_co_write_req_finish (child , offset - new_bytes , new_bytes , & req , 0 );
3180
3195
3181
3196
out :
3182
3197
tracked_request_end (& req );
0 commit comments