From 9e88776c801a3a76f055ad935bd8ff1b0e48ce2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 18 Jul 2013 18:25:59 +0200 Subject: [PATCH] virtio_block: takes capacity change into account * allows live resizing. --- .../virtual/virtio_block/virtio_block.cpp | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp index 1e41a7163d..a1a6d1d316 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp @@ -58,6 +58,7 @@ typedef struct { uint32 features; uint64 capacity; uint32 block_size; + status_t media_status; sem_id sem_cb; } virtio_block_driver_info; @@ -159,6 +160,29 @@ log2(uint32 x) } +static void +virtio_block_config_callback(void* driverCookie) +{ + virtio_block_driver_info* info = (virtio_block_driver_info*)driverCookie; + + status_t status = info->virtio->read_device_config(info->virtio_device, 0, + &info->config, sizeof(struct virtio_blk_config)); + if (status != B_OK) + return; + + uint32 block_size = 512; + if ((info->features & VIRTIO_BLK_F_BLK_SIZE) != 0) + block_size = info->config.blk_size; + uint64 capacity = info->config.capacity * 512 / block_size; + + if (block_size != info->block_size || capacity != info->capacity) { + virtio_block_set_capacity(info, capacity, block_size); + info->media_status = B_DEV_MEDIA_CHANGED; + } + +} + + static void virtio_block_callback(void* driverCookie, void* cookie) { @@ -268,7 +292,8 @@ virtio_block_init_device(void* _info, void** _cookie) ERROR("queue allocation failed (%s)\n", strerror(status)); return status; } - status = info->virtio->setup_interrupt(info->virtio_device, NULL, NULL); + status = info->virtio->setup_interrupt(info->virtio_device, + virtio_block_config_callback, info); *_cookie = info; return status; @@ -398,6 +423,15 @@ virtio_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) TRACE("ioctl(op = %ld)\n", op); switch (op) { + case B_GET_MEDIA_STATUS: + { + *(status_t *)buffer = info->media_status; + info->media_status = B_OK; + TRACE("B_GET_MEDIA_STATUS: 0x%08lx\n", *(status_t *)buffer); + return B_OK; + break; + } + case B_GET_DEVICE_SIZE: { size_t size = info->capacity * info->block_size; @@ -555,6 +589,7 @@ virtio_block_init_driver(device_node *node, void **cookie) memset(info, 0, sizeof(*info)); + info->media_status = B_OK; info->dma_resource = new(std::nothrow) DMAResource; if (info->dma_resource == NULL) { free(info); @@ -659,4 +694,3 @@ module_info* modules[] = { (module_info*)&sVirtioBlockDevice, NULL }; -