mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
block: Honor unmap flag in write zeroes requests
The write zeroes segment descriptor (struct virtio_blk_discard_write_zeroes, virtio spec v1.2 section 5.2.6) includes a flags field with an unmap bit. Per section 5.2.6.2, if unmap is set, the device MAY deallocate the specified range of sectors in the device backend storage, as if the discard command had been sent. Read the flags field and when the unmap bit is set, use punch_hole to deallocate the range. Otherwise continue using write_zeroes via ZERO_RANGE which preserves allocation. This allows the guest to reclaim host disk space through write zeroes requests on thin provisioned images. Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
d609410b8b
commit
3e2e453d89
@@ -621,15 +621,18 @@ impl Request {
|
||||
}
|
||||
|
||||
let mut wz_sector = [0u8; 8];
|
||||
|
||||
let mut wz_num_sectors = [0u8; 4];
|
||||
let mut wz_flags = [0u8; 4];
|
||||
mem.read_slice(&mut wz_sector, data_addr)
|
||||
.map_err(ExecuteError::Read)?;
|
||||
mem.read_slice(&mut wz_num_sectors, data_addr.checked_add(8).unwrap())
|
||||
.map_err(ExecuteError::Read)?;
|
||||
mem.read_slice(&mut wz_flags, data_addr.checked_add(12).unwrap())
|
||||
.map_err(ExecuteError::Read)?;
|
||||
|
||||
let wz_sector = u64::from_le_bytes(wz_sector);
|
||||
let wz_num_sectors = u32::from_le_bytes(wz_num_sectors);
|
||||
let wz_flags = u32::from_le_bytes(wz_flags);
|
||||
|
||||
let wz_offset = wz_sector * SECTOR_SIZE;
|
||||
if wz_offset == 0 && disable_sector0_writes {
|
||||
@@ -637,9 +640,15 @@ impl Request {
|
||||
}
|
||||
let wz_length = (wz_num_sectors as u64) * SECTOR_SIZE;
|
||||
|
||||
disk_image
|
||||
.write_zeroes(wz_offset, wz_length, user_data)
|
||||
.map_err(ExecuteError::AsyncWriteZeroes)?;
|
||||
if wz_flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP != 0 {
|
||||
disk_image
|
||||
.punch_hole(wz_offset, wz_length, user_data)
|
||||
.map_err(ExecuteError::AsyncPunchHole)?;
|
||||
} else {
|
||||
disk_image
|
||||
.write_zeroes(wz_offset, wz_length, user_data)
|
||||
.map_err(ExecuteError::AsyncWriteZeroes)?;
|
||||
}
|
||||
}
|
||||
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user